Merge remote-tracking branch 'origin/master' into staging
authorAnthony Liguori <aliguori@us.ibm.com>
Mon, 11 Mar 2013 01:39:17 +0000 (20:39 -0500)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 11 Mar 2013 01:39:17 +0000 (20:39 -0500)
* origin/master: (75 commits)
  tcg: Don't make exitreq flag a local temporary
  Makefile: Add subdir dependency on config-devices-all.mak
  make_device_config.sh: Emit dependency file to directory where included
  Revert "make_device_config.sh: Fix target path in generated dependency file"
  s390/virtio-ccw: remove redundant call to blockdev_mark_auto_del
  s390/css: Fix subchannel detection
  Allow virtio-net features for legacy s390 virtio bus
  s390: virtio-ccw maintainer
  s390: simplify kvm cpu init
  pseries: Add compatible property to root of device tree
  target-ppc: Move CPU aliases out of translate_init.c
  target-ppc: Report CPU aliases for QMP
  target-ppc: List alias names alongside CPU models
  target-ppc: Make host CPU a subclass of the host's CPU model
  PPC: xnu kernel expects FLUSH to be cleared on STOP
  PPC: Fix dma interrupt
  target-ppc: Fix PPC_DUMP_SPR_ACCESS build
  target-ppc: Synchronize FPU state with KVM
  target-ppc: Add mechanism for synchronizing SPRs with KVM
  Save memory allocation in the elf loader
  ...

644 files changed:
Makefile.objs
Makefile.target
backends/Makefile.objs
backends/baum.c [new file with mode: 0644]
backends/msmouse.c [new file with mode: 0644]
backends/rng-random.c
block/iscsi.c
configure
default-configs/ppc-softmmu.mak
default-configs/ppc64-softmmu.mak
default-configs/ppcemb-softmmu.mak
device-hotplug.c [new file with mode: 0644]
hw/9p.h [deleted file]
hw/9pfs/virtio-9p-device.c
hw/9pfs/virtio-9p-device.h [new file with mode: 0644]
hw/9pfs/virtio-9p-proxy.c
hw/9pfs/virtio-9p.c
hw/9pfs/virtio-9p.h
hw/Makefile.objs
hw/a15mpcore.c
hw/a9mpcore.c
hw/a9scu.c
hw/ac97.c
hw/acpi.c
hw/acpi_ich9.c
hw/acpi_ich9.h
hw/acpi_piix4.c
hw/adb.c
hw/adb.h
hw/adlib.c
hw/ads7846.c
hw/alpha/Makefile.objs
hw/alpha/dp264.c [new file with mode: 0644]
hw/alpha/pci.c [new file with mode: 0644]
hw/alpha_dp264.c [deleted file]
hw/alpha_pci.c [deleted file]
hw/alpha_sys.h
hw/alpha_typhoon.c
hw/an5206.c [deleted file]
hw/apb_pci.c
hw/apic.c
hw/apic_common.c
hw/apic_internal.h
hw/apm.c
hw/apm.h
hw/applesmc.c
hw/arm/Makefile.objs
hw/arm/armv7m.c [new file with mode: 0644]
hw/arm/boot.c [new file with mode: 0644]
hw/arm/collie.c [new file with mode: 0644]
hw/arm/exynos4210.c [new file with mode: 0644]
hw/arm/exynos4_boards.c [new file with mode: 0644]
hw/arm/gumstix.c [new file with mode: 0644]
hw/arm/highbank.c [new file with mode: 0644]
hw/arm/integratorcp.c [new file with mode: 0644]
hw/arm/kzm.c [new file with mode: 0644]
hw/arm/mainstone.c [new file with mode: 0644]
hw/arm/musicpal.c [new file with mode: 0644]
hw/arm/nseries.c [new file with mode: 0644]
hw/arm/omap1.c [new file with mode: 0644]
hw/arm/omap2.c [new file with mode: 0644]
hw/arm/omap_sx1.c [new file with mode: 0644]
hw/arm/palm.c [new file with mode: 0644]
hw/arm/pic_cpu.c [new file with mode: 0644]
hw/arm/pxa2xx.c [new file with mode: 0644]
hw/arm/pxa2xx_gpio.c [new file with mode: 0644]
hw/arm/pxa2xx_pic.c [new file with mode: 0644]
hw/arm/realview.c [new file with mode: 0644]
hw/arm/spitz.c [new file with mode: 0644]
hw/arm/stellaris.c [new file with mode: 0644]
hw/arm/tosa.c [new file with mode: 0644]
hw/arm/versatilepb.c [new file with mode: 0644]
hw/arm/vexpress.c [new file with mode: 0644]
hw/arm/xilinx_zynq.c [new file with mode: 0644]
hw/arm/z2.c [new file with mode: 0644]
hw/arm11mpcore.c
hw/arm_boot.c [deleted file]
hw/arm_gic.c
hw/arm_gic_common.c
hw/arm_gic_internal.h
hw/arm_l2x0.c
hw/arm_mptimer.c
hw/arm_pic.c [deleted file]
hw/arm_sysctl.c
hw/arm_timer.c
hw/armv7m.c [deleted file]
hw/armv7m_nvic.c
hw/axis_dev88.c [deleted file]
hw/baum.c [deleted file]
hw/bitbang_i2c.c
hw/bitbang_i2c.h
hw/blizzard.c
hw/boards.h
hw/bonito.c
hw/bt-hci-csr.c
hw/bt-hci.c
hw/bt-hid.c
hw/bt-l2cap.c
hw/bt-sdp.c
hw/bt.c
hw/cadence_gem.c
hw/cadence_ttc.c
hw/cadence_uart.c
hw/cbus.c
hw/ccid.h
hw/cdrom.c
hw/cirrus_vga.c
hw/cirrus_vga_rop.h
hw/collie.c [deleted file]
hw/cris-boot.c [deleted file]
hw/cris/Makefile.objs
hw/cris/axis_dev88.c [new file with mode: 0644]
hw/cris/boot.c [new file with mode: 0644]
hw/cris/pic_cpu.c [new file with mode: 0644]
hw/cris_pic_cpu.c [deleted file]
hw/cs4231.c
hw/cs4231a.c
hw/cuda.c
hw/dataplane/ioq.c
hw/dataplane/virtio-blk.c
hw/dataplane/vring.c
hw/dataplane/vring.h
hw/debugcon.c
hw/debugexit.c
hw/dec_pci.c
hw/device-hotplug.c [deleted file]
hw/dma.c
hw/dp8393x.c
hw/ds1225y.c
hw/ds1338.c
hw/dummy_m68k.c [deleted file]
hw/e1000.c
hw/ecc.c
hw/eccmemctl.c
hw/eepro100.c
hw/eeprom93xx.c
hw/empty_slot.c
hw/es1370.c
hw/escc.c
hw/esp-pci.c
hw/esp.c
hw/esp.h
hw/etraxfs.h
hw/etraxfs_dma.c
hw/etraxfs_eth.c
hw/etraxfs_pic.c
hw/etraxfs_ser.c
hw/etraxfs_timer.c
hw/exynos4210.c [deleted file]
hw/exynos4210_combiner.c
hw/exynos4210_fimd.c
hw/exynos4210_gic.c
hw/exynos4210_i2c.c
hw/exynos4210_mct.c
hw/exynos4210_pmu.c
hw/exynos4210_pwm.c
hw/exynos4210_rtc.c
hw/exynos4210_uart.c
hw/exynos4_boards.c [deleted file]
hw/fdc.c
hw/fifo.c [deleted file]
hw/fifo.h [deleted file]
hw/fmopl.c
hw/framebuffer.c
hw/fw_cfg.c
hw/g364fb.c
hw/grackle_pci.c
hw/grlib.h
hw/grlib_apbuart.c
hw/grlib_gptimer.c
hw/grlib_irqmp.c
hw/gt64xxx.c
hw/gumstix.c [deleted file]
hw/gus.c
hw/gusemu_hal.c
hw/gusemu_mixer.c
hw/hda-audio.c
hw/heathrow_pic.c
hw/hid.c
hw/highbank.c [deleted file]
hw/hpet.c
hw/hw.h
hw/i2c.c
hw/i2c.h
hw/i386/Makefile.objs
hw/i386/kvmvapic.c [new file with mode: 0644]
hw/i386/multiboot.c [new file with mode: 0644]
hw/i386/pc.c [new file with mode: 0644]
hw/i386/pc_piix.c [new file with mode: 0644]
hw/i386/pc_q35.c [new file with mode: 0644]
hw/i386/smbios.c [new file with mode: 0644]
hw/i386/xen_domainbuild.c [new file with mode: 0644]
hw/i386/xen_machine_pv.c [new file with mode: 0644]
hw/i82374.c
hw/i82378.c
hw/i8254.c
hw/i8254.h
hw/i8254_common.c
hw/i8254_internal.h
hw/i8259.c
hw/i8259_common.c
hw/i8259_internal.h
hw/i82801b11.c
hw/ich9.h
hw/ide.h
hw/imx_avic.c
hw/imx_ccm.c
hw/imx_serial.c
hw/imx_timer.c
hw/integratorcp.c [deleted file]
hw/intel-hda.c
hw/intel-hda.h
hw/ioapic.c
hw/ioapic_common.c
hw/ioapic_internal.h
hw/ioh3420.c
hw/ioh3420.h
hw/ipack.c
hw/ipack.h
hw/ipoctal232.c
hw/irq.c
hw/isa-bus.c
hw/isa.h
hw/isa_mmio.c
hw/ivshmem.c
hw/jazz_led.c
hw/kvmvapic.c [deleted file]
hw/kzm.c [deleted file]
hw/lan9118.c
hw/lance.c
hw/leon3.c [deleted file]
hw/lm32/Makefile.objs
hw/lm32/lm32_boards.c [new file with mode: 0644]
hw/lm32/milkymist.c [new file with mode: 0644]
hw/lm32_boards.c [deleted file]
hw/lm32_hwsetup.h
hw/lm32_juart.c
hw/lm32_pic.c
hw/lm32_sys.c
hw/lm32_timer.c
hw/lm32_uart.c
hw/lm4549.c
hw/lm832x.c
hw/loader.c
hw/lpc_ich9.c
hw/lsi53c895a.c
hw/m25p80.c
hw/m48t59.c
hw/m68k/Makefile.objs
hw/m68k/an5206.c [new file with mode: 0644]
hw/m68k/dummy_m68k.c [new file with mode: 0644]
hw/m68k/mcf5206.c [new file with mode: 0644]
hw/m68k/mcf5208.c [new file with mode: 0644]
hw/m68k/mcf_intc.c [new file with mode: 0644]
hw/mac_dbdma.c
hw/mac_nvram.c
hw/macio.c
hw/mainstone.c [deleted file]
hw/marvell_88w8618_audio.c
hw/max111x.c
hw/max7310.c
hw/mc146818rtc.c
hw/mc146818rtc.h
hw/mcf5206.c [deleted file]
hw/mcf5208.c [deleted file]
hw/mcf_fec.c
hw/mcf_intc.c [deleted file]
hw/mcf_uart.c
hw/megasas.c
hw/microblaze/Makefile.objs
hw/microblaze/boot.c [new file with mode: 0644]
hw/microblaze/petalogix_ml605_mmu.c [new file with mode: 0644]
hw/microblaze/petalogix_s3adsp1800_mmu.c [new file with mode: 0644]
hw/microblaze/pic_cpu.c [new file with mode: 0644]
hw/microblaze_boot.c [deleted file]
hw/microblaze_boot.h
hw/microblaze_pic_cpu.c [deleted file]
hw/milkymist-ac97.c
hw/milkymist-hpdmc.c
hw/milkymist-hw.h
hw/milkymist-memcard.c
hw/milkymist-minimac2.c
hw/milkymist-pfpu.c
hw/milkymist-softusb.c
hw/milkymist-sysctl.c
hw/milkymist-tmu2.c
hw/milkymist-uart.c
hw/milkymist-vgafb.c
hw/milkymist.c [deleted file]
hw/mips/Makefile.objs
hw/mips/addr.c [new file with mode: 0644]
hw/mips/cputimer.c [new file with mode: 0644]
hw/mips/mips_fulong2e.c [new file with mode: 0644]
hw/mips/mips_int.c [new file with mode: 0644]
hw/mips/mips_jazz.c [new file with mode: 0644]
hw/mips/mips_malta.c [new file with mode: 0644]
hw/mips/mips_mipssim.c [new file with mode: 0644]
hw/mips/mips_r4k.c [new file with mode: 0644]
hw/mips_addr.c [deleted file]
hw/mips_fulong2e.c [deleted file]
hw/mips_int.c [deleted file]
hw/mips_jazz.c [deleted file]
hw/mips_malta.c [deleted file]
hw/mips_mipssim.c [deleted file]
hw/mips_r4k.c [deleted file]
hw/mips_timer.c [deleted file]
hw/mipsnet.c
hw/mpc8544_guts.c [deleted file]
hw/msmouse.c [deleted file]
hw/mst_fpga.c
hw/multiboot.c [deleted file]
hw/musicpal.c [deleted file]
hw/nand.c
hw/ne2000-isa.c
hw/ne2000.c
hw/nseries.c [deleted file]
hw/omap1.c [deleted file]
hw/omap2.c [deleted file]
hw/omap_clk.c
hw/omap_dma.c
hw/omap_dss.c
hw/omap_gpio.c
hw/omap_gpmc.c
hw/omap_gptimer.c
hw/omap_i2c.c
hw/omap_intc.c
hw/omap_l4.c
hw/omap_lcdc.c
hw/omap_mmc.c
hw/omap_sdrc.c
hw/omap_spi.c
hw/omap_sx1.c [deleted file]
hw/omap_synctimer.c
hw/omap_tap.c
hw/omap_uart.c
hw/onenand.c
hw/opencores_eth.c
hw/openpic.c
hw/openrisc/Makefile.objs
hw/openrisc/cputimer.c [new file with mode: 0644]
hw/openrisc/openrisc_sim.c [new file with mode: 0644]
hw/openrisc/pic_cpu.c [new file with mode: 0644]
hw/openrisc_pic.c [deleted file]
hw/openrisc_sim.c [deleted file]
hw/openrisc_timer.c [deleted file]
hw/palm.c [deleted file]
hw/pam.c
hw/parallel.c
hw/pc-testdev.c
hw/pc.c [deleted file]
hw/pc.h
hw/pc87312.c
hw/pc87312.h
hw/pc_piix.c [deleted file]
hw/pc_q35.c [deleted file]
hw/pc_sysfw.c
hw/pci/pci_host.h
hw/pci/shpc.c
hw/pci/slotid_cap.c
hw/pci_bridge_dev.c
hw/pckbd.c
hw/pcnet-pci.c
hw/pcnet.c
hw/pcspk.c
hw/pcspk.h
hw/petalogix_ml605_mmu.c [deleted file]
hw/petalogix_s3adsp1800_mmu.c [deleted file]
hw/pflash_cfi01.c
hw/pflash_cfi02.c
hw/piix4.c
hw/piix_pci.c
hw/pl011.c
hw/pl022.c
hw/pl031.c
hw/pl041.c
hw/pl050.c
hw/pl061.c
hw/pl080.c
hw/pl110.c
hw/pl110_template.h
hw/pl181.c
hw/pl190.c
hw/pm_smbus.c
hw/ppc.c [deleted file]
hw/ppc/Makefile.objs
hw/ppc/e500-ccsr.h
hw/ppc/e500plat.c
hw/ppc/mpc8544_guts.c [new file with mode: 0644]
hw/ppc/mpc8544ds.c
hw/ppc/ppc.c [new file with mode: 0644]
hw/ppc/ppc405_boards.c [new file with mode: 0644]
hw/ppc/ppc405_uc.c [new file with mode: 0644]
hw/ppc/ppc440_bamboo.c [new file with mode: 0644]
hw/ppc/ppc4xx_devs.c [new file with mode: 0644]
hw/ppc/ppc_booke.c [new file with mode: 0644]
hw/ppc/ppce500_spin.c [new file with mode: 0644]
hw/ppc/prep.c
hw/ppc/spapr.c [new file with mode: 0644]
hw/ppc/spapr_events.c [new file with mode: 0644]
hw/ppc/spapr_hcall.c [new file with mode: 0644]
hw/ppc/spapr_iommu.c [new file with mode: 0644]
hw/ppc/spapr_rtas.c [new file with mode: 0644]
hw/ppc/spapr_vio.c [new file with mode: 0644]
hw/ppc/virtex_ml507.c [new file with mode: 0644]
hw/ppc/xics.c [new file with mode: 0644]
hw/ppc405.h
hw/ppc405_boards.c [deleted file]
hw/ppc405_uc.c [deleted file]
hw/ppc440_bamboo.c [deleted file]
hw/ppc4xx.h
hw/ppc4xx_devs.c [deleted file]
hw/ppc4xx_pci.c
hw/ppc_booke.c [deleted file]
hw/ppce500_pci.c
hw/ppce500_spin.c [deleted file]
hw/prep_pci.c
hw/ps2.c
hw/ptimer.c
hw/puv3.c [deleted file]
hw/puv3_dma.c
hw/puv3_gpio.c
hw/puv3_intc.c
hw/puv3_ost.c
hw/puv3_pm.c
hw/pxa2xx.c [deleted file]
hw/pxa2xx_dma.c
hw/pxa2xx_gpio.c [deleted file]
hw/pxa2xx_keypad.c
hw/pxa2xx_lcd.c
hw/pxa2xx_mmci.c
hw/pxa2xx_pcmcia.c
hw/pxa2xx_pic.c [deleted file]
hw/pxa2xx_timer.c
hw/q35.c
hw/q35.h
hw/qdev-addr.c
hw/qdev-monitor.c [deleted file]
hw/qdev-monitor.h [deleted file]
hw/qdev-properties-system.c
hw/qdev-properties.c
hw/qdev-properties.h
hw/qdev.c
hw/qdev.h
hw/qxl-logger.c
hw/qxl-render.c
hw/qxl.c
hw/qxl.h
hw/r2d.c [deleted file]
hw/rc4030.c
hw/realview.c [deleted file]
hw/realview_gic.c
hw/rtl8139.c
hw/s390x/event-facility.c
hw/s390x/s390-virtio-ccw.c
hw/s390x/sclp.c
hw/s390x/sclpconsole.c
hw/s390x/sclpquiesce.c
hw/sb16.c
hw/sbi.c
hw/scsi-bus.c
hw/scsi-disk.c
hw/scsi-generic.c
hw/scsi.h
hw/sd.c
hw/sdhci.c
hw/sdhci.h
hw/serial-isa.c
hw/serial-pci.c
hw/serial.c
hw/serial.h
hw/sga.c
hw/sh.h
hw/sh4/Makefile.objs
hw/sh4/r2d.c [new file with mode: 0644]
hw/sh4/sh7750.c [new file with mode: 0644]
hw/sh4/sh7750_regnames.c [new file with mode: 0644]
hw/sh4/shix.c [new file with mode: 0644]
hw/sh7750.c [deleted file]
hw/sh7750_regnames.c [deleted file]
hw/sh_intc.c
hw/sh_intc.h
hw/sh_pci.c
hw/sh_serial.c
hw/sh_timer.c
hw/shix.c [deleted file]
hw/slavio_intctl.c
hw/slavio_misc.c
hw/slavio_timer.c
hw/sm501.c
hw/smbios.c [deleted file]
hw/smbus.c
hw/smbus.h
hw/smbus_eeprom.c
hw/smbus_ich9.c
hw/smc91c111.c
hw/soc_dma.c
hw/spapr.c [deleted file]
hw/spapr_events.c [deleted file]
hw/spapr_hcall.c [deleted file]
hw/spapr_iommu.c [deleted file]
hw/spapr_llan.c
hw/spapr_pci.c
hw/spapr_rtas.c [deleted file]
hw/spapr_vio.c [deleted file]
hw/spapr_vscsi.c
hw/spapr_vty.c
hw/sparc/Makefile.objs
hw/sparc/leon3.c [new file with mode: 0644]
hw/sparc/sun4m.c [new file with mode: 0644]
hw/sparc32_dma.c
hw/sparc64/Makefile.objs
hw/sparc64/sun4u.c [new file with mode: 0644]
hw/spitz.c [deleted file]
hw/ssd0303.c
hw/ssd0323.c
hw/ssi-sd.c
hw/ssi.c
hw/ssi.h
hw/stellaris.c [deleted file]
hw/stellaris_enet.c
hw/stellaris_input.c
hw/stream.c
hw/strongarm.c
hw/sun4c_intctl.c
hw/sun4m.c [deleted file]
hw/sun4m.h
hw/sun4m_iommu.c
hw/sun4u.c [deleted file]
hw/sysbus.c
hw/sysbus.h
hw/tc58128.c
hw/tc6393xb.c
hw/tcx.c
hw/tmp105.c
hw/tmp105.h
hw/tosa.c [deleted file]
hw/tpci200.c
hw/tsc2005.c
hw/tsc210x.c
hw/tusb6010.c
hw/twl92230.c
hw/unicore32/Makefile.objs
hw/unicore32/puv3.c [new file with mode: 0644]
hw/unin_pci.c
hw/usb.h
hw/usb/dev-network.c
hw/versatile_i2c.c
hw/versatile_pci.c
hw/versatilepb.c [deleted file]
hw/vexpress.c [deleted file]
hw/vfio_pci.c
hw/vga-isa-mm.c
hw/vga-isa.c
hw/vga-pci.c
hw/vga.c
hw/vhost.c
hw/vhost_net.c
hw/virtex_ml507.c [deleted file]
hw/virtio-balloon.c
hw/virtio-balloon.h
hw/virtio-blk.c
hw/virtio-blk.h
hw/virtio-bus.c
hw/virtio-bus.h
hw/virtio-console.c
hw/virtio-net.c
hw/virtio-net.h
hw/virtio-pci.c
hw/virtio-pci.h
hw/virtio-rng.c
hw/virtio-scsi.c
hw/virtio-scsi.h
hw/virtio-serial-bus.c
hw/virtio-serial.h
hw/virtio.c
hw/virtio.h
hw/vmmouse.c
hw/vmport.c
hw/vmware_vga.c
hw/vt82c686.c
hw/wdt_i6300esb.c
hw/wdt_ib700.c
hw/wm8750.c
hw/xen-host-pci-device.c
hw/xen-host-pci-device.h
hw/xen_apic.c
hw/xen_backend.c
hw/xen_backend.h
hw/xen_common.h
hw/xen_console.c
hw/xen_devconfig.c
hw/xen_disk.c
hw/xen_domainbuild.c [deleted file]
hw/xen_domainbuild.h
hw/xen_machine_pv.c [deleted file]
hw/xen_nic.c
hw/xen_platform.c
hw/xen_pt.c
hw/xen_pt.h
hw/xen_pt_config_init.c
hw/xen_pt_msi.c
hw/xenfb.c
hw/xgmac.c
hw/xics.c [deleted file]
hw/xilinx.h
hw/xilinx_axidma.c
hw/xilinx_axienet.c
hw/xilinx_ethlite.c
hw/xilinx_intc.c
hw/xilinx_spi.c
hw/xilinx_spips.c
hw/xilinx_timer.c
hw/xilinx_uartlite.c
hw/xilinx_zynq.c [deleted file]
hw/xio3130_downstream.c
hw/xio3130_downstream.h
hw/xio3130_upstream.c
hw/xio3130_upstream.h
hw/xtensa/Makefile.objs
hw/xtensa/pic_cpu.c [new file with mode: 0644]
hw/xtensa/xtensa_lx60.c [new file with mode: 0644]
hw/xtensa/xtensa_sim.c [new file with mode: 0644]
hw/xtensa_lx60.c [deleted file]
hw/xtensa_pic.c [deleted file]
hw/xtensa_sim.c [deleted file]
hw/z2.c [deleted file]
hw/zaurus.c
hw/zynq_slcr.c
include/migration/vmstate.h
include/monitor/qdev.h [new file with mode: 0644]
include/qemu/fifo8.h [new file with mode: 0644]
monitor.c
qdev-monitor.c [new file with mode: 0644]
qemu-char.c
qemu-options.hx
stubs/Makefile.objs
stubs/pci-drive-hot-add.c [new file with mode: 0644]
tests/rtc-test.c
trace-events
util/Makefile.objs
util/fifo8.c [new file with mode: 0644]
util/osdep.c
util/qemu-config.c
vl.c

index a68cdac7ce0bbb9a9a125dfaed2a413cc25c5366..8c90b92d01a363f54c20e4972528e7ede52cfc34 100644 (file)
@@ -51,6 +51,7 @@ ifeq ($(CONFIG_SOFTMMU),y)
 common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/
 common-obj-y += net/
 common-obj-y += readline.o
+common-obj-y += qdev-monitor.o device-hotplug.o
 common-obj-$(CONFIG_WIN32) += os-win32.o
 common-obj-$(CONFIG_POSIX) += os-posix.o
 
index ca657b325a9cb6b4d84dc9ce0b6841d7d3a722eb..2bd6d1471ca9e395765f5428496ed758d40f068f 100644 (file)
@@ -111,6 +111,7 @@ CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y)
 obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o
 obj-y += qtest.o
 obj-y += hw/
+obj-$(CONFIG_FDT) += device_tree.o
 obj-$(CONFIG_KVM) += kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-y += memory.o savevm.o cputlb.o
index 883676106b6d7e7c4ea8b7af8e92262b61149e99..464bc3e220f4ccc6d7e0f1d4fe5786dd3f7c0f31 100644 (file)
@@ -1,2 +1,6 @@
 common-obj-y += rng.o rng-egd.o
 common-obj-$(CONFIG_POSIX) += rng-random.o
+
+common-obj-y += msmouse.o
+common-obj-$(CONFIG_BRLAPI) += baum.o
+$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) 
diff --git a/backends/baum.c b/backends/baum.c
new file mode 100644 (file)
index 0000000..9063aea
--- /dev/null
@@ -0,0 +1,633 @@
+/*
+ * QEMU Baum Braille Device
+ *
+ * Copyright (c) 2008 Samuel Thibault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu-common.h"
+#include "char/char.h"
+#include "qemu/timer.h"
+#include "hw/usb.h"
+#include <brlapi.h>
+#include <brlapi_constants.h>
+#include <brlapi_keycodes.h>
+#ifdef CONFIG_SDL
+#include <SDL_syswm.h>
+#endif
+
+#if 0
+#define DPRINTF(fmt, ...) \
+        printf(fmt, ## __VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+#define ESC 0x1B
+
+#define BAUM_REQ_DisplayData           0x01
+#define BAUM_REQ_GetVersionNumber      0x05
+#define BAUM_REQ_GetKeys               0x08
+#define BAUM_REQ_SetMode               0x12
+#define BAUM_REQ_SetProtocol           0x15
+#define BAUM_REQ_GetDeviceIdentity     0x84
+#define BAUM_REQ_GetSerialNumber       0x8A
+
+#define BAUM_RSP_CellCount             0x01
+#define BAUM_RSP_VersionNumber         0x05
+#define BAUM_RSP_ModeSetting           0x11
+#define BAUM_RSP_CommunicationChannel  0x16
+#define BAUM_RSP_PowerdownSignal       0x17
+#define BAUM_RSP_HorizontalSensors     0x20
+#define BAUM_RSP_VerticalSensors       0x21
+#define BAUM_RSP_RoutingKeys           0x22
+#define BAUM_RSP_Switches              0x23
+#define BAUM_RSP_TopKeys               0x24
+#define BAUM_RSP_HorizontalSensor      0x25
+#define BAUM_RSP_VerticalSensor                0x26
+#define BAUM_RSP_RoutingKey            0x27
+#define BAUM_RSP_FrontKeys6            0x28
+#define BAUM_RSP_BackKeys6             0x29
+#define BAUM_RSP_CommandKeys           0x2B
+#define BAUM_RSP_FrontKeys10           0x2C
+#define BAUM_RSP_BackKeys10            0x2D
+#define BAUM_RSP_EntryKeys             0x33
+#define BAUM_RSP_JoyStick              0x34
+#define BAUM_RSP_ErrorCode             0x40
+#define BAUM_RSP_InfoBlock             0x42
+#define BAUM_RSP_DeviceIdentity                0x84
+#define BAUM_RSP_SerialNumber          0x8A
+#define BAUM_RSP_BluetoothName         0x8C
+
+#define BAUM_TL1 0x01
+#define BAUM_TL2 0x02
+#define BAUM_TL3 0x04
+#define BAUM_TR1 0x08
+#define BAUM_TR2 0x10
+#define BAUM_TR3 0x20
+
+#define BUF_SIZE 256
+
+typedef struct {
+    CharDriverState *chr;
+
+    brlapi_handle_t *brlapi;
+    int brlapi_fd;
+    unsigned int x, y;
+
+    uint8_t in_buf[BUF_SIZE];
+    uint8_t in_buf_used;
+    uint8_t out_buf[BUF_SIZE];
+    uint8_t out_buf_used, out_buf_ptr;
+
+    QEMUTimer *cellCount_timer;
+} BaumDriverState;
+
+/* Let's assume NABCC by default */
+static const uint8_t nabcc_translation[256] = {
+    [0] = ' ',
+#ifndef BRLAPI_DOTS
+#define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \
+    ((d1?BRLAPI_DOT1:0)|\
+     (d2?BRLAPI_DOT2:0)|\
+     (d3?BRLAPI_DOT3:0)|\
+     (d4?BRLAPI_DOT4:0)|\
+     (d5?BRLAPI_DOT5:0)|\
+     (d6?BRLAPI_DOT6:0)|\
+     (d7?BRLAPI_DOT7:0)|\
+     (d8?BRLAPI_DOT8:0))
+#endif
+    [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a',
+    [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b',
+    [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c',
+    [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd',
+    [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e',
+    [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f',
+    [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g',
+    [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h',
+    [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i',
+    [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j',
+    [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k',
+    [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l',
+    [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm',
+    [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n',
+    [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o',
+    [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p',
+    [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q',
+    [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r',
+    [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's',
+    [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't',
+    [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u',
+    [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v',
+    [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w',
+    [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x',
+    [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y',
+    [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z',
+
+    [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A',
+    [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B',
+    [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C',
+    [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D',
+    [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E',
+    [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F',
+    [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G',
+    [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H',
+    [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I',
+    [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J',
+    [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K',
+    [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L',
+    [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M',
+    [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N',
+    [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O',
+    [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P',
+    [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q',
+    [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R',
+    [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S',
+    [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T',
+    [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U',
+    [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V',
+    [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W',
+    [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X',
+    [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y',
+    [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z',
+
+    [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0',
+    [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1',
+    [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2',
+    [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3',
+    [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4',
+    [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5',
+    [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6',
+    [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7',
+    [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8',
+    [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9',
+
+    [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.',
+    [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+',
+    [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-',
+    [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*',
+    [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/',
+    [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(',
+    [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')',
+
+    [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&',
+    [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#',
+
+    [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',',
+    [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';',
+    [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':',
+    [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!',
+    [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?',
+    [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"',
+    [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'',
+    [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`',
+    [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^',
+    [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~',
+    [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[',
+    [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']',
+    [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{',
+    [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}',
+    [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=',
+    [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<',
+    [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>',
+    [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$',
+    [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%',
+    [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@',
+    [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|',
+    [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\',
+    [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_',
+};
+
+/* The serial port can receive more of our data */
+static void baum_accept_input(struct CharDriverState *chr)
+{
+    BaumDriverState *baum = chr->opaque;
+    int room, first;
+
+    if (!baum->out_buf_used)
+        return;
+    room = qemu_chr_be_can_write(chr);
+    if (!room)
+        return;
+    if (room > baum->out_buf_used)
+        room = baum->out_buf_used;
+
+    first = BUF_SIZE - baum->out_buf_ptr;
+    if (room > first) {
+        qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, first);
+        baum->out_buf_ptr = 0;
+        baum->out_buf_used -= first;
+        room -= first;
+    }
+    qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, room);
+    baum->out_buf_ptr += room;
+    baum->out_buf_used -= room;
+}
+
+/* We want to send a packet */
+static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len)
+{
+    uint8_t io_buf[1 + 2 * len], *cur = io_buf;
+    int room;
+    *cur++ = ESC;
+    while (len--)
+        if ((*cur++ = *buf++) == ESC)
+            *cur++ = ESC;
+    room = qemu_chr_be_can_write(baum->chr);
+    len = cur - io_buf;
+    if (len <= room) {
+        /* Fits */
+        qemu_chr_be_write(baum->chr, io_buf, len);
+    } else {
+        int first;
+        uint8_t out;
+        /* Can't fit all, send what can be, and store the rest. */
+        qemu_chr_be_write(baum->chr, io_buf, room);
+        len -= room;
+        cur = io_buf + room;
+        if (len > BUF_SIZE - baum->out_buf_used) {
+            /* Can't even store it, drop the previous data... */
+            assert(len <= BUF_SIZE);
+            baum->out_buf_used = 0;
+            baum->out_buf_ptr = 0;
+        }
+        out = baum->out_buf_ptr;
+        baum->out_buf_used += len;
+        first = BUF_SIZE - baum->out_buf_ptr;
+        if (len > first) {
+            memcpy(baum->out_buf + out, cur, first);
+            out = 0;
+            len -= first;
+            cur += first;
+        }
+        memcpy(baum->out_buf + out, cur, len);
+    }
+}
+
+/* Called when the other end seems to have a wrong idea of our display size */
+static void baum_cellCount_timer_cb(void *opaque)
+{
+    BaumDriverState *baum = opaque;
+    uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y };
+    DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
+    baum_write_packet(baum, cell_count, sizeof(cell_count));
+}
+
+/* Try to interpret a whole incoming packet */
+static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
+{
+    const uint8_t *cur = buf;
+    uint8_t req = 0;
+
+    if (!len--)
+        return 0;
+    if (*cur++ != ESC) {
+        while (*cur != ESC) {
+            if (!len--)
+                return 0;
+            cur++;
+        }
+        DPRINTF("Dropped %d bytes!\n", cur - buf);
+    }
+
+#define EAT(c) do {\
+    if (!len--) \
+        return 0; \
+    if ((c = *cur++) == ESC) { \
+        if (!len--) \
+            return 0; \
+        if (*cur++ != ESC) { \
+            DPRINTF("Broken packet %#2x, tossing\n", req); \
+               if (qemu_timer_pending(baum->cellCount_timer)) { \
+                qemu_del_timer(baum->cellCount_timer); \
+                baum_cellCount_timer_cb(baum); \
+            } \
+            return (cur - 2 - buf); \
+        } \
+    } \
+} while (0)
+
+    EAT(req);
+    switch (req) {
+    case BAUM_REQ_DisplayData:
+    {
+        uint8_t cells[baum->x * baum->y], c;
+        uint8_t text[baum->x * baum->y];
+        uint8_t zero[baum->x * baum->y];
+        int cursor = BRLAPI_CURSOR_OFF;
+        int i;
+
+        /* Allow 100ms to complete the DisplayData packet */
+        qemu_mod_timer(baum->cellCount_timer, qemu_get_clock_ns(vm_clock) +
+                       get_ticks_per_sec() / 10);
+        for (i = 0; i < baum->x * baum->y ; i++) {
+            EAT(c);
+            cells[i] = c;
+            if ((c & (BRLAPI_DOT7|BRLAPI_DOT8))
+                    == (BRLAPI_DOT7|BRLAPI_DOT8)) {
+                cursor = i + 1;
+                c &= ~(BRLAPI_DOT7|BRLAPI_DOT8);
+            }
+            if (!(c = nabcc_translation[c]))
+                c = '?';
+            text[i] = c;
+        }
+        qemu_del_timer(baum->cellCount_timer);
+
+        memset(zero, 0, sizeof(zero));
+
+        brlapi_writeArguments_t wa = {
+            .displayNumber = BRLAPI_DISPLAY_DEFAULT,
+            .regionBegin = 1,
+            .regionSize = baum->x * baum->y,
+            .text = (char *)text,
+            .textSize = baum->x * baum->y,
+            .andMask = zero,
+            .orMask = cells,
+            .cursor = cursor,
+            .charset = (char *)"ISO-8859-1",
+        };
+
+        if (brlapi__write(baum->brlapi, &wa) == -1)
+            brlapi_perror("baum brlapi_write");
+        break;
+    }
+    case BAUM_REQ_SetMode:
+    {
+        uint8_t mode, setting;
+        DPRINTF("SetMode\n");
+        EAT(mode);
+        EAT(setting);
+        /* ignore */
+        break;
+    }
+    case BAUM_REQ_SetProtocol:
+    {
+        uint8_t protocol;
+        DPRINTF("SetProtocol\n");
+        EAT(protocol);
+        /* ignore */
+        break;
+    }
+    case BAUM_REQ_GetDeviceIdentity:
+    {
+        uint8_t identity[17] = { BAUM_RSP_DeviceIdentity,
+            'B','a','u','m',' ','V','a','r','i','o' };
+        DPRINTF("GetDeviceIdentity\n");
+        identity[11] = '0' + baum->x / 10;
+        identity[12] = '0' + baum->x % 10;
+        baum_write_packet(baum, identity, sizeof(identity));
+        break;
+    }
+    case BAUM_REQ_GetVersionNumber:
+    {
+        uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */
+        DPRINTF("GetVersionNumber\n");
+        baum_write_packet(baum, version, sizeof(version));
+        break;
+    }
+    case BAUM_REQ_GetSerialNumber:
+    {
+        uint8_t serial[] = { BAUM_RSP_SerialNumber,
+            '0','0','0','0','0','0','0','0' };
+        DPRINTF("GetSerialNumber\n");
+        baum_write_packet(baum, serial, sizeof(serial));
+        break;
+    }
+    case BAUM_REQ_GetKeys:
+    {
+        DPRINTF("Get%0#2x\n", req);
+        /* ignore */
+        break;
+    }
+    default:
+        DPRINTF("unrecognized request %0#2x\n", req);
+        do
+            if (!len--)
+                return 0;
+        while (*cur++ != ESC);
+        cur--;
+        break;
+    }
+    return cur - buf;
+}
+
+/* The other end is writing some data.  Store it and try to interpret */
+static int baum_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    BaumDriverState *baum = chr->opaque;
+    int tocopy, cur, eaten, orig_len = len;
+
+    if (!len)
+        return 0;
+    if (!baum->brlapi)
+        return len;
+
+    while (len) {
+        /* Complete our buffer as much as possible */
+        tocopy = len;
+        if (tocopy > BUF_SIZE - baum->in_buf_used)
+            tocopy = BUF_SIZE - baum->in_buf_used;
+
+        memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy);
+        baum->in_buf_used += tocopy;
+        buf += tocopy;
+        len -= tocopy;
+
+        /* Interpret it as much as possible */
+        cur = 0;
+        while (cur < baum->in_buf_used &&
+                (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur)))
+            cur += eaten;
+
+        /* Shift the remainder */
+        if (cur) {
+            memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur);
+            baum->in_buf_used -= cur;
+        }
+
+        /* And continue if any data left */
+    }
+    return orig_len;
+}
+
+/* Send the key code to the other end */
+static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) {
+    uint8_t packet[] = { type, value };
+    DPRINTF("writing key %x %x\n", type, value);
+    baum_write_packet(baum, packet, sizeof(packet));
+}
+
+/* We got some data on the BrlAPI socket */
+static void baum_chr_read(void *opaque)
+{
+    BaumDriverState *baum = opaque;
+    brlapi_keyCode_t code;
+    int ret;
+    if (!baum->brlapi)
+        return;
+    while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) {
+        DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code);
+        /* Emulate */
+        switch (code & BRLAPI_KEY_TYPE_MASK) {
+        case BRLAPI_KEY_TYPE_CMD:
+            switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
+            case BRLAPI_KEY_CMD_ROUTE:
+                baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1);
+                baum_send_key(baum, BAUM_RSP_RoutingKey, 0);
+                break;
+            case 0:
+                switch (code & BRLAPI_KEY_CMD_ARG_MASK) {
+                case BRLAPI_KEY_CMD_FWINLT:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_FWINRT:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_LNUP:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_LNDN:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_TOP:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_BOT:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_TOP_LEFT:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_BOT_LEFT:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_HOME:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_PREFMENU:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                }
+            }
+            break;
+        case BRLAPI_KEY_TYPE_SYM:
+            break;
+        }
+    }
+    if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) {
+        brlapi_perror("baum: brlapi_readKey");
+        brlapi__closeConnection(baum->brlapi);
+        g_free(baum->brlapi);
+        baum->brlapi = NULL;
+    }
+}
+
+static void baum_close(struct CharDriverState *chr)
+{
+    BaumDriverState *baum = chr->opaque;
+
+    qemu_free_timer(baum->cellCount_timer);
+    if (baum->brlapi) {
+        brlapi__closeConnection(baum->brlapi);
+        g_free(baum->brlapi);
+    }
+    g_free(baum);
+}
+
+static CharDriverState *chr_baum_init(QemuOpts *opts)
+{
+    BaumDriverState *baum;
+    CharDriverState *chr;
+    brlapi_handle_t *handle;
+#ifdef CONFIG_SDL
+    SDL_SysWMinfo info;
+#endif
+    int tty;
+
+    baum = g_malloc0(sizeof(BaumDriverState));
+    baum->chr = chr = g_malloc0(sizeof(CharDriverState));
+
+    chr->opaque = baum;
+    chr->chr_write = baum_write;
+    chr->chr_accept_input = baum_accept_input;
+    chr->chr_close = baum_close;
+
+    handle = g_malloc0(brlapi_getHandleSize());
+    baum->brlapi = handle;
+
+    baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
+    if (baum->brlapi_fd == -1) {
+        brlapi_perror("baum_init: brlapi_openConnection");
+        goto fail_handle;
+    }
+
+    baum->cellCount_timer = qemu_new_timer_ns(vm_clock, baum_cellCount_timer_cb, baum);
+
+    if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
+        brlapi_perror("baum_init: brlapi_getDisplaySize");
+        goto fail;
+    }
+
+#ifdef CONFIG_SDL
+    memset(&info, 0, sizeof(info));
+    SDL_VERSION(&info.version);
+    if (SDL_GetWMInfo(&info))
+        tty = info.info.x11.wmwindow;
+    else
+#endif
+        tty = BRLAPI_TTY_DEFAULT;
+
+    if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
+        brlapi_perror("baum_init: brlapi_enterTtyMode");
+        goto fail;
+    }
+
+    qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
+
+    qemu_chr_generic_open(chr);
+
+    return chr;
+
+fail:
+    qemu_free_timer(baum->cellCount_timer);
+    brlapi__closeConnection(handle);
+fail_handle:
+    g_free(handle);
+    g_free(chr);
+    g_free(baum);
+    return NULL;
+}
+
+static void register_types(void)
+{
+    register_char_driver("braille", chr_baum_init);
+}
+
+type_init(register_types);
diff --git a/backends/msmouse.c b/backends/msmouse.c
new file mode 100644 (file)
index 0000000..407ec87
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * QEMU Microsoft serial mouse emulation
+ *
+ * Copyright (c) 2008 Lubomir Rintel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <stdlib.h>
+#include "qemu-common.h"
+#include "char/char.h"
+#include "ui/console.h"
+
+#define MSMOUSE_LO6(n) ((n) & 0x3f)
+#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
+
+static void msmouse_event(void *opaque,
+                          int dx, int dy, int dz, int buttons_state)
+{
+    CharDriverState *chr = (CharDriverState *)opaque;
+
+    unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 };
+
+    /* Movement deltas */
+    bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx);
+    bytes[1] |= MSMOUSE_LO6(dx);
+    bytes[2] |= MSMOUSE_LO6(dy);
+
+    /* Buttons */
+    bytes[0] |= (buttons_state & 0x01 ? 0x20 : 0x00);
+    bytes[0] |= (buttons_state & 0x02 ? 0x10 : 0x00);
+    bytes[3] |= (buttons_state & 0x04 ? 0x20 : 0x00);
+
+    /* We always send the packet of, so that we do not have to keep track
+       of previous state of the middle button. This can potentially confuse
+       some very old drivers for two button mice though. */
+    qemu_chr_be_write(chr, bytes, 4);
+}
+
+static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len)
+{
+    /* Ignore writes to mouse port */
+    return len;
+}
+
+static void msmouse_chr_close (struct CharDriverState *chr)
+{
+    g_free (chr);
+}
+
+static CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
+{
+    CharDriverState *chr;
+
+    chr = g_malloc0(sizeof(CharDriverState));
+    chr->chr_write = msmouse_chr_write;
+    chr->chr_close = msmouse_chr_close;
+
+    qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
+
+    return chr;
+}
+
+static void register_types(void)
+{
+    register_char_driver("msmouse", qemu_chr_open_msmouse);
+}
+
+type_init(register_types);
index 0d1108811d41e02ce20049a86c6722eab657b899..acd20afad2d4b7cfc492ca5e13daa746c742c432 100644 (file)
@@ -74,7 +74,7 @@ static void rng_random_opened(RngBackend *b, Error **errp)
         error_set(errp, QERR_INVALID_PARAMETER_VALUE,
                   "filename", "a valid filename");
     } else {
-        s->fd = open(s->filename, O_RDONLY | O_NONBLOCK);
+        s->fd = qemu_open(s->filename, O_RDONLY | O_NONBLOCK);
 
         if (s->fd == -1) {
             error_set(errp, QERR_OPEN_FILE_FAILED, s->filename);
@@ -130,7 +130,7 @@ static void rng_random_finalize(Object *obj)
     qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
 
     if (s->fd != -1) {
-        close(s->fd);
+        qemu_close(s->fd);
     }
 
     g_free(s->filename);
index deb3b688901b7e7fac4d80031e04d7eeff9c94ff..3d529213ff329975d45b778aa4c0dd134c7aa4f1 100644 (file)
@@ -60,8 +60,11 @@ typedef struct IscsiAIOCB {
     uint8_t *buf;
     int status;
     int canceled;
+    int retries;
     size_t read_size;
     size_t read_offset;
+    int64_t sector_num;
+    int nb_sectors;
 #ifdef __linux__
     sg_io_hdr_t *ioh;
 #endif
@@ -69,6 +72,7 @@ typedef struct IscsiAIOCB {
 
 #define NOP_INTERVAL 5000
 #define MAX_NOP_FAILURES 3
+#define ISCSI_CMD_RETRIES 5
 
 static void
 iscsi_bh_cb(void *p)
@@ -191,6 +195,8 @@ iscsi_process_write(void *arg)
     iscsi_set_events(iscsilun);
 }
 
+static int
+iscsi_aio_writev_acb(IscsiAIOCB *acb);
 
 static void
 iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
@@ -208,7 +214,19 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
     }
 
     acb->status = 0;
-    if (status < 0) {
+    if (status != 0) {
+        if (status == SCSI_STATUS_CHECK_CONDITION
+            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
+            && acb->retries-- > 0) {
+            if (acb->task != NULL) {
+                scsi_free_scsi_task(acb->task);
+                acb->task = NULL;
+            }
+            if (iscsi_aio_writev_acb(acb) == 0) {
+                iscsi_set_events(acb->iscsilun);
+                return;
+            }
+        }
         error_report("Failed to write16 data to iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
@@ -222,15 +240,10 @@ static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
     return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
 }
 
-static BlockDriverAIOCB *
-iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
-                 QEMUIOVector *qiov, int nb_sectors,
-                 BlockDriverCompletionFunc *cb,
-                 void *opaque)
+static int
+iscsi_aio_writev_acb(IscsiAIOCB *acb)
 {
-    IscsiLun *iscsilun = bs->opaque;
-    struct iscsi_context *iscsi = iscsilun->iscsi;
-    IscsiAIOCB *acb;
+    struct iscsi_context *iscsi = acb->iscsilun->iscsi;
     size_t size;
     uint32_t num_sectors;
     uint64_t lba;
@@ -239,19 +252,13 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
 #endif
     int ret;
 
-    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
-    trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
-
-    acb->iscsilun = iscsilun;
-    acb->qiov     = qiov;
-
     acb->canceled   = 0;
     acb->bh         = NULL;
     acb->status     = -EINPROGRESS;
     acb->buf        = NULL;
 
     /* this will allow us to get rid of 'buf' completely */
-    size = nb_sectors * BDRV_SECTOR_SIZE;
+    size = acb->nb_sectors * BDRV_SECTOR_SIZE;
 
 #if !defined(LIBISCSI_FEATURE_IOVECTOR)
     data.size = MIN(size, acb->qiov->size);
@@ -270,48 +277,76 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
     if (acb->task == NULL) {
         error_report("iSCSI: Failed to allocate task for scsi WRITE16 "
                      "command. %s", iscsi_get_error(iscsi));
-        qemu_aio_release(acb);
-        return NULL;
+        return -1;
     }
     memset(acb->task, 0, sizeof(struct scsi_task));
 
     acb->task->xfer_dir = SCSI_XFER_WRITE;
     acb->task->cdb_size = 16;
     acb->task->cdb[0] = 0x8a;
-    lba = sector_qemu2lun(sector_num, iscsilun);
+    lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
     *(uint32_t *)&acb->task->cdb[2]  = htonl(lba >> 32);
     *(uint32_t *)&acb->task->cdb[6]  = htonl(lba & 0xffffffff);
-    num_sectors = size / iscsilun->block_size;
+    num_sectors = size / acb->iscsilun->block_size;
     *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
     acb->task->expxferlen = size;
 
 #if defined(LIBISCSI_FEATURE_IOVECTOR)
-    ret = iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
+    ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
                                    iscsi_aio_write16_cb,
                                    NULL,
                                    acb);
 #else
-    ret = iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
+    ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
                                    iscsi_aio_write16_cb,
                                    &data,
                                    acb);
 #endif
     if (ret != 0) {
-        scsi_free_scsi_task(acb->task);
         g_free(acb->buf);
-        qemu_aio_release(acb);
-        return NULL;
+        return -1;
     }
 
 #if defined(LIBISCSI_FEATURE_IOVECTOR)
     scsi_task_set_iov_out(acb->task, (struct scsi_iovec*) acb->qiov->iov, acb->qiov->niov);
 #endif
 
-    iscsi_set_events(iscsilun);
+    return 0;
+}
+
+static BlockDriverAIOCB *
+iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
+                 QEMUIOVector *qiov, int nb_sectors,
+                 BlockDriverCompletionFunc *cb,
+                 void *opaque)
+{
+    IscsiLun *iscsilun = bs->opaque;
+    IscsiAIOCB *acb;
 
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
+    trace_iscsi_aio_writev(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);
+
+    acb->iscsilun    = iscsilun;
+    acb->qiov        = qiov;
+    acb->nb_sectors  = nb_sectors;
+    acb->sector_num  = sector_num;
+    acb->retries     = ISCSI_CMD_RETRIES;
+
+    if (iscsi_aio_writev_acb(acb) != 0) {
+        if (acb->task) {
+            scsi_free_scsi_task(acb->task);
+        }
+        qemu_aio_release(acb);
+        return NULL;
+    }
+
+    iscsi_set_events(iscsilun);
     return &acb->common;
 }
 
+static int
+iscsi_aio_readv_acb(IscsiAIOCB *acb);
+
 static void
 iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
                     void *command_data, void *opaque)
@@ -326,6 +361,18 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
 
     acb->status = 0;
     if (status != 0) {
+        if (status == SCSI_STATUS_CHECK_CONDITION
+            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
+            && acb->retries-- > 0) {
+            if (acb->task != NULL) {
+                scsi_free_scsi_task(acb->task);
+                acb->task = NULL;
+            }
+            if (iscsi_aio_readv_acb(acb) == 0) {
+                iscsi_set_events(acb->iscsilun);
+                return;
+            }
+        }
         error_report("Failed to read16 data from iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
@@ -334,35 +381,20 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
     iscsi_schedule_bh(acb);
 }
 
-static BlockDriverAIOCB *
-iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
-                QEMUIOVector *qiov, int nb_sectors,
-                BlockDriverCompletionFunc *cb,
-                void *opaque)
+static int
+iscsi_aio_readv_acb(IscsiAIOCB *acb)
 {
-    IscsiLun *iscsilun = bs->opaque;
-    struct iscsi_context *iscsi = iscsilun->iscsi;
-    IscsiAIOCB *acb;
-    size_t qemu_read_size;
+    struct iscsi_context *iscsi = acb->iscsilun->iscsi;
+    uint64_t lba;
+    uint32_t num_sectors;
+    int ret;
 #if !defined(LIBISCSI_FEATURE_IOVECTOR)
     int i;
 #endif
-    int ret;
-    uint64_t lba;
-    uint32_t num_sectors;
-
-    qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
-
-    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
-    trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb);
-
-    acb->iscsilun = iscsilun;
-    acb->qiov     = qiov;
 
     acb->canceled    = 0;
     acb->bh          = NULL;
     acb->status      = -EINPROGRESS;
-    acb->read_size   = qemu_read_size;
     acb->buf         = NULL;
 
     /* If LUN blocksize is bigger than BDRV_BLOCK_SIZE a read from QEMU
@@ -370,30 +402,29 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
      * data.
      */
     acb->read_offset = 0;
-    if (iscsilun->block_size > BDRV_SECTOR_SIZE) {
-        uint64_t bdrv_offset = BDRV_SECTOR_SIZE * sector_num;
+    if (acb->iscsilun->block_size > BDRV_SECTOR_SIZE) {
+        uint64_t bdrv_offset = BDRV_SECTOR_SIZE * acb->sector_num;
 
-        acb->read_offset  = bdrv_offset % iscsilun->block_size;
+        acb->read_offset  = bdrv_offset % acb->iscsilun->block_size;
     }
 
-    num_sectors  = (qemu_read_size + iscsilun->block_size
+    num_sectors  = (acb->read_size + acb->iscsilun->block_size
                     + acb->read_offset - 1)
-                    / iscsilun->block_size;
+                    / acb->iscsilun->block_size;
 
     acb->task = malloc(sizeof(struct scsi_task));
     if (acb->task == NULL) {
         error_report("iSCSI: Failed to allocate task for scsi READ16 "
                      "command. %s", iscsi_get_error(iscsi));
-        qemu_aio_release(acb);
-        return NULL;
+        return -1;
     }
     memset(acb->task, 0, sizeof(struct scsi_task));
 
     acb->task->xfer_dir = SCSI_XFER_READ;
-    lba = sector_qemu2lun(sector_num, iscsilun);
-    acb->task->expxferlen = qemu_read_size;
+    lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
+    acb->task->expxferlen = acb->read_size;
 
-    switch (iscsilun->type) {
+    switch (acb->iscsilun->type) {
     case TYPE_DISK:
         acb->task->cdb_size = 16;
         acb->task->cdb[0]  = 0x88;
@@ -409,14 +440,12 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
         break;
     }
 
-    ret = iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
+    ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
                                    iscsi_aio_read16_cb,
                                    NULL,
                                    acb);
     if (ret != 0) {
-        scsi_free_scsi_task(acb->task);
-        qemu_aio_release(acb);
-        return NULL;
+        return -1;
     }
 
 #if defined(LIBISCSI_FEATURE_IOVECTOR)
@@ -428,12 +457,42 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
                 acb->qiov->iov[i].iov_base);
     }
 #endif
+    return 0;
+}
 
-    iscsi_set_events(iscsilun);
+static BlockDriverAIOCB *
+iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
+                QEMUIOVector *qiov, int nb_sectors,
+                BlockDriverCompletionFunc *cb,
+                void *opaque)
+{
+    IscsiLun *iscsilun = bs->opaque;
+    IscsiAIOCB *acb;
 
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
+    trace_iscsi_aio_readv(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);
+
+    acb->nb_sectors  = nb_sectors;
+    acb->sector_num  = sector_num;
+    acb->iscsilun    = iscsilun;
+    acb->qiov        = qiov;
+    acb->read_size   = BDRV_SECTOR_SIZE * (size_t)acb->nb_sectors;
+    acb->retries     = ISCSI_CMD_RETRIES;
+
+    if (iscsi_aio_readv_acb(acb) != 0) {
+        if (acb->task) {
+            scsi_free_scsi_task(acb->task);
+        }
+        qemu_aio_release(acb);
+        return NULL;
+    }
+
+    iscsi_set_events(iscsilun);
     return &acb->common;
 }
 
+static int
+iscsi_aio_flush_acb(IscsiAIOCB *acb);
 
 static void
 iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
@@ -446,7 +505,19 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
     }
 
     acb->status = 0;
-    if (status < 0) {
+    if (status != 0) {
+        if (status == SCSI_STATUS_CHECK_CONDITION
+            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
+            && acb->retries-- > 0) {
+            if (acb->task != NULL) {
+                scsi_free_scsi_task(acb->task);
+                acb->task = NULL;
+            }
+            if (iscsi_aio_flush_acb(acb) == 0) {
+                iscsi_set_events(acb->iscsilun);
+                return;
+            }
+        }
         error_report("Failed to sync10 data on iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
@@ -455,29 +526,43 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
     iscsi_schedule_bh(acb);
 }
 
-static BlockDriverAIOCB *
-iscsi_aio_flush(BlockDriverState *bs,
-                BlockDriverCompletionFunc *cb, void *opaque)
+static int
+iscsi_aio_flush_acb(IscsiAIOCB *acb)
 {
-    IscsiLun *iscsilun = bs->opaque;
-    struct iscsi_context *iscsi = iscsilun->iscsi;
-    IscsiAIOCB *acb;
-
-    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
+    struct iscsi_context *iscsi = acb->iscsilun->iscsi;
 
-    acb->iscsilun = iscsilun;
     acb->canceled   = 0;
     acb->bh         = NULL;
     acb->status     = -EINPROGRESS;
     acb->buf        = NULL;
 
-    acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun,
+    acb->task = iscsi_synchronizecache10_task(iscsi, acb->iscsilun->lun,
                                          0, 0, 0, 0,
                                          iscsi_synccache10_cb,
                                          acb);
     if (acb->task == NULL) {
         error_report("iSCSI: Failed to send synchronizecache10 command. %s",
                      iscsi_get_error(iscsi));
+        return -1;
+    }
+
+    return 0;
+}
+
+static BlockDriverAIOCB *
+iscsi_aio_flush(BlockDriverState *bs,
+                BlockDriverCompletionFunc *cb, void *opaque)
+{
+    IscsiLun *iscsilun = bs->opaque;
+
+    IscsiAIOCB *acb;
+
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
+
+    acb->iscsilun    = iscsilun;
+    acb->retries     = ISCSI_CMD_RETRIES;
+
+    if (iscsi_aio_flush_acb(acb) != 0) {
         qemu_aio_release(acb);
         return NULL;
     }
@@ -487,6 +572,8 @@ iscsi_aio_flush(BlockDriverState *bs,
     return &acb->common;
 }
 
+static int iscsi_aio_discard_acb(IscsiAIOCB *acb);
+
 static void
 iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
                      void *command_data, void *opaque)
@@ -498,7 +585,19 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
     }
 
     acb->status = 0;
-    if (status < 0) {
+    if (status != 0) {
+        if (status == SCSI_STATUS_CHECK_CONDITION
+            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
+            && acb->retries-- > 0) {
+            if (acb->task != NULL) {
+                scsi_free_scsi_task(acb->task);
+                acb->task = NULL;
+            }
+            if (iscsi_aio_discard_acb(acb) == 0) {
+                iscsi_set_events(acb->iscsilun);
+                return;
+            }
+        }
         error_report("Failed to unmap data on iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
@@ -507,34 +606,50 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
     iscsi_schedule_bh(acb);
 }
 
-static BlockDriverAIOCB *
-iscsi_aio_discard(BlockDriverState *bs,
-                  int64_t sector_num, int nb_sectors,
-                  BlockDriverCompletionFunc *cb, void *opaque)
-{
-    IscsiLun *iscsilun = bs->opaque;
-    struct iscsi_context *iscsi = iscsilun->iscsi;
-    IscsiAIOCB *acb;
+static int iscsi_aio_discard_acb(IscsiAIOCB *acb) {
+    struct iscsi_context *iscsi = acb->iscsilun->iscsi;
     struct unmap_list list[1];
 
-    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
-
-    acb->iscsilun = iscsilun;
     acb->canceled   = 0;
     acb->bh         = NULL;
     acb->status     = -EINPROGRESS;
     acb->buf        = NULL;
 
-    list[0].lba = sector_qemu2lun(sector_num, iscsilun);
-    list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size;
+    list[0].lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
+    list[0].num = acb->nb_sectors * BDRV_SECTOR_SIZE / acb->iscsilun->block_size;
 
-    acb->task = iscsi_unmap_task(iscsi, iscsilun->lun,
+    acb->task = iscsi_unmap_task(iscsi, acb->iscsilun->lun,
                                  0, 0, &list[0], 1,
                                  iscsi_unmap_cb,
                                  acb);
     if (acb->task == NULL) {
         error_report("iSCSI: Failed to send unmap command. %s",
                      iscsi_get_error(iscsi));
+        return -1;
+    }
+
+    return 0;
+}
+
+static BlockDriverAIOCB *
+iscsi_aio_discard(BlockDriverState *bs,
+                  int64_t sector_num, int nb_sectors,
+                  BlockDriverCompletionFunc *cb, void *opaque)
+{
+    IscsiLun *iscsilun = bs->opaque;
+    IscsiAIOCB *acb;
+
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
+
+    acb->iscsilun    = iscsilun;
+    acb->nb_sectors  = nb_sectors;
+    acb->sector_num  = sector_num;
+    acb->retries     = ISCSI_CMD_RETRIES;
+
+    if (iscsi_aio_discard_acb(acb) != 0) {
+        if (acb->task) {
+            scsi_free_scsi_task(acb->task);
+        }
         qemu_aio_release(acb);
         return NULL;
     }
@@ -823,6 +938,71 @@ static void iscsi_nop_timed_event(void *opaque)
 }
 #endif
 
+static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
+{
+    struct scsi_task *task = NULL;
+    struct scsi_readcapacity10 *rc10 = NULL;
+    struct scsi_readcapacity16 *rc16 = NULL;
+    int ret = 0;
+    int retries = ISCSI_CMD_RETRIES; 
+
+try_again:
+    switch (iscsilun->type) {
+    case TYPE_DISK:
+        task = iscsi_readcapacity16_sync(iscsilun->iscsi, iscsilun->lun);
+        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
+            if (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
+                    && task->sense.key == SCSI_SENSE_UNIT_ATTENTION
+                    && retries-- > 0) {
+                scsi_free_scsi_task(task);
+                goto try_again;
+            }
+            error_report("iSCSI: failed to send readcapacity16 command.");
+            ret = -EINVAL;
+            goto out;
+        }
+        rc16 = scsi_datain_unmarshall(task);
+        if (rc16 == NULL) {
+            error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
+            ret = -EINVAL;
+            goto out;
+        }
+        iscsilun->block_size = rc16->block_length;
+        iscsilun->num_blocks = rc16->returned_lba + 1;
+        break;
+    case TYPE_ROM:
+        task = iscsi_readcapacity10_sync(iscsilun->iscsi, iscsilun->lun, 0, 0);
+        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
+            error_report("iSCSI: failed to send readcapacity10 command.");
+            ret = -EINVAL;
+            goto out;
+        }
+        rc10 = scsi_datain_unmarshall(task);
+        if (rc10 == NULL) {
+            error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
+            ret = -EINVAL;
+            goto out;
+        }
+        iscsilun->block_size = rc10->block_size;
+        if (rc10->lba == 0) {
+            /* blank disk loaded */
+            iscsilun->num_blocks = 0;
+        } else {
+            iscsilun->num_blocks = rc10->lba + 1;
+        }
+        break;
+    default:
+        break;
+    }
+
+out:
+    if (task) {
+        scsi_free_scsi_task(task);
+    }
+
+    return ret;
+}
+
 /*
  * We support iscsi url's on the form
  * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
@@ -834,8 +1014,6 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
     struct iscsi_url *iscsi_url = NULL;
     struct scsi_task *task = NULL;
     struct scsi_inquiry_standard *inq = NULL;
-    struct scsi_readcapacity10 *rc10 = NULL;
-    struct scsi_readcapacity16 *rc16 = NULL;
     char *initiator_name = NULL;
     int ret;
 
@@ -925,50 +1103,9 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
 
     iscsilun->type = inq->periperal_device_type;
 
-    scsi_free_scsi_task(task);
-
-    switch (iscsilun->type) {
-    case TYPE_DISK:
-        task = iscsi_readcapacity16_sync(iscsi, iscsilun->lun);
-        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
-            error_report("iSCSI: failed to send readcapacity16 command.");
-            ret = -EINVAL;
-            goto out;
-        }
-        rc16 = scsi_datain_unmarshall(task);
-        if (rc16 == NULL) {
-            error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
-            ret = -EINVAL;
-            goto out;
-        }
-        iscsilun->block_size = rc16->block_length;
-        iscsilun->num_blocks = rc16->returned_lba + 1;
-        break;
-    case TYPE_ROM:
-        task = iscsi_readcapacity10_sync(iscsi, iscsilun->lun, 0, 0);
-        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
-            error_report("iSCSI: failed to send readcapacity10 command.");
-            ret = -EINVAL;
-            goto out;
-        }
-        rc10 = scsi_datain_unmarshall(task);
-        if (rc10 == NULL) {
-            error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
-            ret = -EINVAL;
-            goto out;
-        }
-        iscsilun->block_size = rc10->block_size;
-        if (rc10->lba == 0) {
-            /* blank disk loaded */
-            iscsilun->num_blocks = 0;
-        } else {
-            iscsilun->num_blocks = rc10->lba + 1;
-        }
-        break;
-    default:
-        break;
+    if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
+        goto out;
     }
-
     bs->total_sectors    = iscsilun->num_blocks *
                            iscsilun->block_size / BDRV_SECTOR_SIZE ;
 
@@ -981,8 +1118,6 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
         bs->sg = 1;
     }
 
-    ret = 0;
-
 #if defined(LIBISCSI_FEATURE_NOP_COUNTER)
     /* Set up a timer for sending out iSCSI NOPs */
     iscsilun->nop_timer = qemu_new_timer_ms(rt_clock, iscsi_nop_timed_event, iscsilun);
@@ -1023,6 +1158,26 @@ static void iscsi_close(BlockDriverState *bs)
     memset(iscsilun, 0, sizeof(IscsiLun));
 }
 
+static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
+{
+    IscsiLun *iscsilun = bs->opaque;
+    int ret = 0;
+
+    if (iscsilun->type != TYPE_DISK) {
+        return -ENOTSUP;
+    }
+
+    if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
+        return ret;
+    }
+
+    if (offset > iscsi_getlength(bs)) {
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
 static int iscsi_has_zero_init(BlockDriverState *bs)
 {
     return 0;
@@ -1093,6 +1248,7 @@ static BlockDriver bdrv_iscsi = {
     .create_options  = iscsi_create_options,
 
     .bdrv_getlength  = iscsi_getlength,
+    .bdrv_truncate   = iscsi_truncate,
 
     .bdrv_aio_readv  = iscsi_aio_readv,
     .bdrv_aio_writev = iscsi_aio_writev,
index 2f98c5a242f30b793d687606d051e752c802c1f9..84317c6826f72ae9758774d30ce8857ccbb771aa 100755 (executable)
--- a/configure
+++ b/configure
@@ -2420,6 +2420,7 @@ int main(void) { return 0; }
 EOF
   if compile_prog "" "$fdt_libs" ; then
     fdt=yes
+    libs_softmmu="$libs_softmmu $fdt_libs"
   else
     if test "$fdt" = "yes" ; then
       feature_not_found "fdt"
@@ -2803,7 +2804,13 @@ if test "$libiscsi" != "no" ; then
 #include <iscsi/iscsi.h>
 int main(void) { iscsi_unmap_sync(NULL,0,0,0,NULL,0); return 0; }
 EOF
-  if compile_prog "" "-liscsi" ; then
+  if $pkg_config --atleast-version=1.7.0 libiscsi --modversion >/dev/null 2>&1; then
+    libiscsi="yes"
+    libiscsi_cflags=$($pkg_config --cflags libiscsi 2>/dev/null)
+    libiscsi_libs=$($pkg_config --libs libiscsi 2>/dev/null)
+    CFLAGS="$CFLAGS $libiscsi_cflags"
+    LIBS="$LIBS $libiscsi_libs"
+  elif compile_prog "" "-liscsi" ; then
     libiscsi="yes"
     LIBS="$LIBS -liscsi"
   else
@@ -2871,7 +2878,7 @@ EOF
   spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
   spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
   if $pkg_config --atleast-version=0.12.0 spice-server >/dev/null 2>&1 && \
-     $pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1 && \
+     $pkg_config --atleast-version=0.12.3 spice-protocol > /dev/null 2>&1 && \
      compile_prog "$spice_cflags" "$spice_libs" ; then
     spice="yes"
     libs_softmmu="$libs_softmmu $spice_libs"
@@ -3985,7 +3992,6 @@ case "$target_arch2" in
     target_nptl="yes"
     gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
     target_llong_alignment=4
-    target_libs_softmmu="$fdt_libs"
   ;;
   cris)
     target_nptl="yes"
@@ -4004,7 +4010,6 @@ case "$target_arch2" in
     TARGET_ARCH=microblaze
     bflt="yes"
     target_nptl="yes"
-    target_libs_softmmu="$fdt_libs"
   ;;
   mips|mipsel)
     TARGET_ARCH=mips
@@ -4030,21 +4035,18 @@ case "$target_arch2" in
   ppc)
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_nptl="yes"
-    target_libs_softmmu="$fdt_libs"
   ;;
   ppcemb)
     TARGET_BASE_ARCH=ppc
     TARGET_ABI_DIR=ppc
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_nptl="yes"
-    target_libs_softmmu="$fdt_libs"
   ;;
   ppc64)
     TARGET_BASE_ARCH=ppc
     TARGET_ABI_DIR=ppc
     gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_long_alignment=8
-    target_libs_softmmu="$fdt_libs"
   ;;
   ppc64abi32)
     TARGET_ARCH=ppc64
@@ -4052,7 +4054,6 @@ case "$target_arch2" in
     TARGET_ABI_DIR=ppc
     echo "TARGET_ABI32=y" >> $config_target_mak
     gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
-    target_libs_softmmu="$fdt_libs"
   ;;
   sh4|sh4eb)
     TARGET_ARCH=sh4
@@ -4154,9 +4155,6 @@ case "$target_arch2" in
   i386|x86_64)
     echo "CONFIG_HAVE_GET_MEMORY_MAPPING=y" >> $config_target_mak
 esac
-if test "$target_arch2" = "ppc64" -a "$fdt" = "yes"; then
-  echo "CONFIG_PSERIES=y" >> $config_target_mak
-fi
 if test "$target_bigendian" = "yes" ; then
   echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
 fi
@@ -4369,6 +4367,7 @@ FILES="$FILES tests/tcg/lm32/Makefile po/Makefile"
 FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
 FILES="$FILES pc-bios/spapr-rtas/Makefile"
 FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
+FILES="$FILES pc-bios/qemu-icon.bmp"
 for bios_file in \
     $source_path/pc-bios/*.bin \
     $source_path/pc-bios/*.aml \
index f9f8a8159b4ad0a5deafbaf77f2e37e4f8f20408..c209a8da65b17bbd04cc8f6fe80d25a8226e5500 100644 (file)
@@ -40,3 +40,4 @@ CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
 CONFIG_I8259=y
 CONFIG_XILINX=y
+CONFIG_E500=$(CONFIG_FDT)
index dc4429437838f01f17984dadbcb7575d19531745..8d490bd72eea60c1f5137f6f7596d465c890a1c3 100644 (file)
@@ -40,3 +40,5 @@ CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
 CONFIG_I8259=y
 CONFIG_XILINX=y
+CONFIG_PSERIES=$(CONFIG_FDT)
+CONFIG_E500=$(CONFIG_FDT)
index 1c6bcf93fc129d7523702e55244a1998f65aae5c..7f13421d93f59fec373e78d47d09fcffdc3a86f9 100644 (file)
@@ -35,3 +35,4 @@ CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
 CONFIG_I8259=y
 CONFIG_XILINX=y
+CONFIG_E500=$(CONFIG_FDT)
diff --git a/device-hotplug.c b/device-hotplug.c
new file mode 100644 (file)
index 0000000..103d34a
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * QEMU device hotplug helpers
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "sysemu/blockdev.h"
+#include "qemu/config-file.h"
+#include "sysemu/sysemu.h"
+#include "monitor/monitor.h"
+
+DriveInfo *add_init_drive(const char *optstr)
+{
+    DriveInfo *dinfo;
+    QemuOpts *opts;
+
+    opts = drive_def(optstr);
+    if (!opts)
+        return NULL;
+
+    dinfo = drive_init(opts, current_machine->block_default_type);
+    if (!dinfo) {
+        qemu_opts_del(opts);
+        return NULL;
+    }
+
+    return dinfo;
+}
+
+void drive_hot_add(Monitor *mon, const QDict *qdict)
+{
+    DriveInfo *dinfo = NULL;
+    const char *opts = qdict_get_str(qdict, "opts");
+
+    dinfo = add_init_drive(opts);
+    if (!dinfo) {
+        goto err;
+    }
+    if (dinfo->devaddr) {
+        monitor_printf(mon, "Parameter addr not supported\n");
+        goto err;
+    }
+
+    switch (dinfo->type) {
+    case IF_NONE:
+        monitor_printf(mon, "OK\n");
+        break;
+    default:
+        if (pci_drive_hot_add(mon, qdict, dinfo)) {
+            goto err;
+        }
+    }
+    return;
+
+err:
+    if (dinfo) {
+        drive_put_ref(dinfo);
+    }
+}
diff --git a/hw/9p.h b/hw/9p.h
deleted file mode 100644 (file)
index d9951d6..0000000
--- a/hw/9p.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Virtio 9p
- *
- * Copyright IBM, Corp. 2010
- *
- * Authors:
- *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- */
-
-#ifndef QEMU_9P_H
-#define QEMU_9P_H
-
-typedef struct V9fsConf
-{
-    /* tag name for the device */
-    char *tag;
-    char *fsdev_id;
-} V9fsConf;
-
-#endif
index 74155fb61eb0186a773a8f5738e7f792edd9f7b5..d321c802f24745b4c314f9ddc453fded75b894e6 100644 (file)
@@ -14,9 +14,9 @@
 #include "hw/virtio.h"
 #include "hw/pc.h"
 #include "qemu/sockets.h"
-#include "hw/virtio-pci.h"
 #include "virtio-9p.h"
 #include "fsdev/qemu-fsdev.h"
+#include "virtio-9p-device.h"
 #include "virtio-9p-xattr.h"
 #include "virtio-9p-coth.h"
 
@@ -136,54 +136,3 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
 
     return &s->vdev;
 }
-
-static int virtio_9p_init_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-    VirtIODevice *vdev;
-
-    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
-    vdev->nvectors = proxy->nvectors;
-    virtio_init_pci(proxy, vdev);
-    /* make the actual value visible */
-    proxy->nvectors = vdev->nvectors;
-    return 0;
-}
-
-static Property virtio_9p_properties[] = {
-    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
-    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
-    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-    DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
-    DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void virtio_9p_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = virtio_9p_init_pci;
-    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
-    k->device_id = PCI_DEVICE_ID_VIRTIO_9P;
-    k->revision = VIRTIO_PCI_ABI_VERSION;
-    k->class_id = 0x2;
-    dc->props = virtio_9p_properties;
-    dc->reset = virtio_pci_reset;
-}
-
-static const TypeInfo virtio_9p_info = {
-    .name          = "virtio-9p-pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(VirtIOPCIProxy),
-    .class_init    = virtio_9p_class_init,
-};
-
-static void virtio_9p_register_types(void)
-{
-    type_register_static(&virtio_9p_info);
-    virtio_9p_set_fd_limit();
-}
-
-type_init(virtio_9p_register_types)
diff --git a/hw/9pfs/virtio-9p-device.h b/hw/9pfs/virtio-9p-device.h
new file mode 100644 (file)
index 0000000..65789db
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_VIRTIO_9P_DEVICE_H
+#define QEMU_VIRTIO_9P_DEVICE_H
+
+typedef struct V9fsConf
+{
+    /* tag name for the device */
+    char *tag;
+    char *fsdev_id;
+} V9fsConf;
+
+#endif
index 54e98759f0313675acff3ed211b98f1b9c001c22..730027900e7fcbc15c4db327dd1c18c5fa854ee8 100644 (file)
@@ -13,6 +13,7 @@
 #include <sys/un.h>
 #include "hw/virtio.h"
 #include "virtio-9p.h"
+#include "qemu/error-report.h"
 #include "fsdev/qemu-fsdev.h"
 #include "virtio-9p-proxy.h"
 
index d3ea820eae46ac9c1069a8687717f5d38ab1e976..5cc4c92012a3c9d8ad74c4dd62496ece6536f2e2 100644 (file)
@@ -14,7 +14,6 @@
 #include "hw/virtio.h"
 #include "hw/pc.h"
 #include "qemu/sockets.h"
-#include "hw/virtio-pci.h"
 #include "virtio-9p.h"
 #include "fsdev/qemu-fsdev.h"
 #include "virtio-9p-xattr.h"
@@ -3269,7 +3268,7 @@ void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
     free_pdu(s, pdu);
 }
 
-void virtio_9p_set_fd_limit(void)
+static void __attribute__((__constructor__)) virtio_9p_set_fd_limit(void)
 {
     struct rlimit rlim;
     if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
index 406fe522db85a2656bf27c60b2aa84bfb680da91..52b1c6997f1f4d8e02fbf48061b606ea9f2049bb 100644 (file)
@@ -389,7 +389,6 @@ static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu)
 }
 
 extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
-extern void virtio_9p_set_fd_limit(void);
 extern void v9fs_reclaim_fd(V9fsPDU *pdu);
 extern void v9fs_path_init(V9fsPath *path);
 extern void v9fs_path_free(V9fsPath *path);
index 40ebe466ad404900ce9f934c6d5e5e7c03855a76..eb7eb31a198eb707ca61c1061216927faea93625 100644 (file)
@@ -44,7 +44,6 @@ common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
 endif
 common-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
 common-obj-$(CONFIG_SDHCI) += sdhci.o
-common-obj-y += fifo.o
 common-obj-y += pam.o
 
 # PPC devices
@@ -190,10 +189,8 @@ 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-monitor.o
+common-obj-y += ps2.o
 common-obj-y += qdev-properties-system.o
-common-obj-$(CONFIG_BRLAPI) += baum.o
 
 # xen backend driver support
 common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
@@ -209,8 +206,6 @@ obj-$(CONFIG_SOFTMMU) += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
 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 & VFIO PCI device assignment
 ifeq ($(CONFIG_PCI), y)
@@ -218,5 +213,4 @@ obj-$(CONFIG_KVM) += ivshmem.o
 obj-$(CONFIG_LINUX) += vfio_pci.o
 endif
 
-$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) 
 endif
index 97abe413c884eb6307cc816393ad5e76eaf9c8d4..648656d5b48b6911e382f7f214fb613ad97889f0 100644 (file)
@@ -18,7 +18,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/kvm.h"
 
 /* A15MP private memory region.  */
index 01aee0264dd0bc60ea20d3ddc5fa5787069be7c5..0a1a10f37ae88be84e1c837ec19b1c5aa5866434 100644 (file)
@@ -8,7 +8,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 typedef struct A9MPPrivState {
     SysBusDevice busdev;
index 0e9e54d7fbddbd899de848e1decbd8a5435b548a..05897c2fa2a55471351defd89deb4e1cd8de3282 100644 (file)
@@ -8,7 +8,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* A9MP private memory region.  */
 
index 6c565e755c0fac1b6d10c29bf01faac3cbaa2603..c7d601fdb7dcf736f4b38d8fc966775afb9e44f3 100644 (file)
--- a/hw/ac97.c
+++ b/hw/ac97.c
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 #include "sysemu/dma.h"
 
 enum {
index 8c9dcc51c4b8c403df6017a5f7a73cf5539110e3..53e47d5857a77b96adf746b9195f786eea75763b 100644 (file)
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -19,9 +19,9 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 #include "sysemu/sysemu.h"
-#include "hw.h"
-#include "pc.h"
-#include "acpi.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/acpi.h"
 #include "monitor/monitor.h"
 
 struct acpi_table_header {
index d2f9808242b5cdd23d044a98a153368be55de424..29f84ffb45703c5cbb103538b6967c9e90eb23ab 100644 (file)
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "pc.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
-#include "acpi.h"
+#include "hw/acpi.h"
 #include "sysemu/kvm.h"
 #include "exec/address-spaces.h"
 
-#include "ich9.h"
+#include "hw/ich9.h"
 
 //#define DEBUG
 
index ecb82abc65b34bd1286951de713efc1753b07acb..91c3aeb7ea946ae2bf1578a81266c6836fc0214c 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef HW_ACPI_ICH9_H
 #define HW_ACPI_ICH9_H
 
-#include "acpi.h"
+#include "hw/acpi.h"
 
 typedef struct ICH9LPCPMRegs {
     /*
index 65b26013bd1492794965693e930e12f9a7a08963..7a4b71291997756ad978e63133a39b1a2c82fa44 100644 (file)
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "pc.h"
-#include "apm.h"
-#include "pm_smbus.h"
-#include "pci/pci.h"
-#include "acpi.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/apm.h"
+#include "hw/pm_smbus.h"
+#include "hw/pci/pci.h"
+#include "hw/acpi.h"
 #include "sysemu/sysemu.h"
 #include "qemu/range.h"
 #include "exec/ioport.h"
-#include "fw_cfg.h"
+#include "hw/fw_cfg.h"
 #include "exec/address-spaces.h"
 
 //#define DEBUG
index 6cf54650c8afab96fb048eca840a89174ca5e13b..fd9052c16b04571b6198d42e07e28b91031abbeb 100644 (file)
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -21,8 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "adb.h"
+#include "hw/hw.h"
+#include "hw/adb.h"
 #include "ui/console.h"
 
 /* debug ADB */
index 721f1ac43ef260a30f9e028c2d3f879d9c42f14f..bdfccd40416497bf7c5594c58fc8dec2edd5ad45 100644 (file)
--- a/hw/adb.h
+++ b/hw/adb.h
@@ -26,7 +26,7 @@
 #if !defined(__ADB_H__)
 #define __ADB_H__
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 #define MAX_ADB_DEVICES 16
 
index 07c69fc967842a8ff556d69072751cbed30634da..e6bce59512d98a7dfca646c3262ec540123e850e 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "isa.h"
+#include "hw/isa.h"
 
 //#define DEBUG
 
@@ -47,7 +47,7 @@
 void YMF262UpdateOneQEMU (int which, INT16 *dst, int length);
 #define SHIFT 2
 #else
-#include "fmopl.h"
+#include "hw/fmopl.h"
 #define SHIFT 1
 #endif
 
index 29e5585d9150fc567204ea863cf57ba6e2919ccc..5da3dc5b2cf7914ea5b3664baa72072f555d7e19 100644 (file)
@@ -10,7 +10,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "ssi.h"
+#include "hw/ssi.h"
 #include "ui/console.h"
 
 typedef struct {
index af1c07fa7c9dc42056ea5453c045476c699ce82d..db868d2ea69fc64be34f58127b82994729ed6d7b 100644 (file)
@@ -1,4 +1,6 @@
 obj-y = mc146818rtc.o
-obj-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
+obj-y += alpha_typhoon.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += dp264.o pci.o
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
new file mode 100644 (file)
index 0000000..13aaa57
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * QEMU Alpha DP264/CLIPPER hardware system emulator.
+ *
+ * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
+ * variants because CLIPPER doesn't have an SMC669 SuperIO controller
+ * that we need to emulate as well.
+ */
+
+#include "hw/hw.h"
+#include "elf.h"
+#include "hw/loader.h"
+#include "hw/boards.h"
+#include "hw/alpha_sys.h"
+#include "sysemu/sysemu.h"
+#include "hw/mc146818rtc.h"
+#include "hw/ide.h"
+#include "hw/i8254.h"
+#include "hw/serial.h"
+
+#define MAX_IDE_BUS 2
+
+static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
+{
+    if (((addr >> 41) & 3) == 2) {
+        addr &= 0xffffffffffull;
+    }
+    return addr;
+}
+
+/* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
+    (0) The dev_irq_n lines into the cpu, which we totally ignore,
+    (1) The DRIR lines in the typhoon chipset,
+    (2) The "vector" aka mangled interrupt number reported by SRM PALcode,
+    (3) The interrupt number assigned by the kernel.
+   The following function is concerned with (1) only.  */
+
+static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
+{
+    int slot = d->devfn >> 3;
+
+    assert(irq_num >= 0 && irq_num <= 3);
+
+    return (slot + 1) * 4 + irq_num;
+}
+
+static void clipper_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    AlphaCPU *cpus[4];
+    PCIBus *pci_bus;
+    ISABus *isa_bus;
+    qemu_irq rtc_irq;
+    long size, i;
+    const char *palcode_filename;
+    uint64_t palcode_entry, palcode_low, palcode_high;
+    uint64_t kernel_entry, kernel_low, kernel_high;
+
+    /* Create up to 4 cpus.  */
+    memset(cpus, 0, sizeof(cpus));
+    for (i = 0; i < smp_cpus; ++i) {
+        cpus[i] = cpu_alpha_init(cpu_model ? cpu_model : "ev67");
+    }
+
+    cpus[0]->env.trap_arg0 = ram_size;
+    cpus[0]->env.trap_arg1 = 0;
+    cpus[0]->env.trap_arg2 = smp_cpus;
+
+    /* Init the chipset.  */
+    pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus,
+                           clipper_pci_map_irq);
+
+    rtc_init(isa_bus, 1980, rtc_irq);
+    pit_init(isa_bus, 0x40, 0, NULL);
+    isa_create_simple(isa_bus, "i8042");
+
+    /* VGA setup.  Don't bother loading the bios.  */
+    pci_vga_init(pci_bus);
+
+    /* Serial code setup.  */
+    for (i = 0; i < MAX_SERIAL_PORTS; ++i) {
+        if (serial_hds[i]) {
+            serial_isa_init(isa_bus, i, serial_hds[i]);
+        }
+    }
+
+    /* Network setup.  e1000 is good enough, failing Tulip support.  */
+    for (i = 0; i < nb_nics; i++) {
+        pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
+    }
+
+    /* IDE disk setup.  */
+    {
+        DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+        ide_drive_get(hd, MAX_IDE_BUS);
+
+        pci_cmd646_ide_init(pci_bus, hd, 0);
+    }
+
+    /* Load PALcode.  Given that this is not "real" cpu palcode,
+       but one explicitly written for the emulation, we might as
+       well load it directly from and ELF image.  */
+    palcode_filename = (bios_name ? bios_name : "palcode-clipper");
+    palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename);
+    if (palcode_filename == NULL) {
+        hw_error("no palcode provided\n");
+        exit(1);
+    }
+    size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
+                    NULL, &palcode_entry, &palcode_low, &palcode_high,
+                    0, EM_ALPHA, 0);
+    if (size < 0) {
+        hw_error("could not load palcode '%s'\n", palcode_filename);
+        exit(1);
+    }
+
+    /* Start all cpus at the PALcode RESET entry point.  */
+    for (i = 0; i < smp_cpus; ++i) {
+        cpus[i]->env.pal_mode = 1;
+        cpus[i]->env.pc = palcode_entry;
+        cpus[i]->env.palbr = palcode_entry;
+    }
+
+    /* Load a kernel.  */
+    if (kernel_filename) {
+        uint64_t param_offset;
+
+        size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
+                        NULL, &kernel_entry, &kernel_low, &kernel_high,
+                        0, EM_ALPHA, 0);
+        if (size < 0) {
+            hw_error("could not load kernel '%s'\n", kernel_filename);
+            exit(1);
+        }
+
+        cpus[0]->env.trap_arg1 = kernel_entry;
+
+        param_offset = kernel_low - 0x6000;
+
+        if (kernel_cmdline) {
+            pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
+        }
+
+        if (initrd_filename) {
+            long initrd_base, initrd_size;
+
+            initrd_size = get_image_size(initrd_filename);
+            if (initrd_size < 0) {
+                hw_error("could not load initial ram disk '%s'\n",
+                         initrd_filename);
+                exit(1);
+            }
+
+            /* Put the initrd image as high in memory as possible.  */
+            initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
+            load_image_targphys(initrd_filename, initrd_base,
+                                ram_size - initrd_base);
+
+            stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL);
+            stq_phys(param_offset + 0x108, initrd_size);
+        }
+    }
+}
+
+static QEMUMachine clipper_machine = {
+    .name = "clipper",
+    .desc = "Alpha DP264/CLIPPER",
+    .init = clipper_init,
+    .max_cpus = 4,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void clipper_machine_init(void)
+{
+    qemu_register_machine(&clipper_machine);
+}
+
+machine_init(clipper_machine_init);
diff --git a/hw/alpha/pci.c b/hw/alpha/pci.c
new file mode 100644 (file)
index 0000000..8462868
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * QEMU Alpha PCI support functions.
+ *
+ * Some of this isn't very Alpha specific at all.
+ *
+ * ??? Sparse memory access not implemented.
+ */
+
+#include "config.h"
+#include "hw/alpha_sys.h"
+#include "qemu/log.h"
+#include "sysemu/sysemu.h"
+
+
+/* PCI IO reads/writes, to byte-word addressable memory.  */
+/* ??? Doesn't handle multiple PCI busses.  */
+
+static uint64_t bw_io_read(void *opaque, hwaddr addr, unsigned size)
+{
+    switch (size) {
+    case 1:
+        return cpu_inb(addr);
+    case 2:
+        return cpu_inw(addr);
+    case 4:
+        return cpu_inl(addr);
+    }
+    abort();
+}
+
+static void bw_io_write(void *opaque, hwaddr addr,
+                        uint64_t val, unsigned size)
+{
+    switch (size) {
+    case 1:
+        cpu_outb(addr, val);
+        break;
+    case 2:
+        cpu_outw(addr, val);
+        break;
+    case 4:
+        cpu_outl(addr, val);
+        break;
+    default:
+        abort();
+    }
+}
+
+const MemoryRegionOps alpha_pci_bw_io_ops = {
+    .read = bw_io_read,
+    .write = bw_io_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+/* PCI config space reads/writes, to byte-word addressable memory.  */
+static uint64_t bw_conf1_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    PCIBus *b = opaque;
+    return pci_data_read(b, addr, size);
+}
+
+static void bw_conf1_write(void *opaque, hwaddr addr,
+                           uint64_t val, unsigned size)
+{
+    PCIBus *b = opaque;
+    pci_data_write(b, addr, val, size);
+}
+
+const MemoryRegionOps alpha_pci_conf1_ops = {
+    .read = bw_conf1_read,
+    .write = bw_conf1_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+/* PCI/EISA Interrupt Acknowledge Cycle.  */
+
+static uint64_t iack_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return pic_read_irq(isa_pic);
+}
+
+static void special_write(void *opaque, hwaddr addr,
+                          uint64_t val, unsigned size)
+{
+    qemu_log("pci: special write cycle");
+}
+
+const MemoryRegionOps alpha_pci_iack_ops = {
+    .read = iack_read,
+    .write = special_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
deleted file mode 100644 (file)
index 1cd549c..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * QEMU Alpha DP264/CLIPPER hardware system emulator.
- *
- * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
- * variants because CLIPPER doesn't have an SMC669 SuperIO controller
- * that we need to emulate as well.
- */
-
-#include "hw.h"
-#include "elf.h"
-#include "loader.h"
-#include "boards.h"
-#include "alpha_sys.h"
-#include "sysemu/sysemu.h"
-#include "mc146818rtc.h"
-#include "ide.h"
-#include "i8254.h"
-#include "serial.h"
-
-#define MAX_IDE_BUS 2
-
-static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
-{
-    if (((addr >> 41) & 3) == 2) {
-        addr &= 0xffffffffffull;
-    }
-    return addr;
-}
-
-/* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
-    (0) The dev_irq_n lines into the cpu, which we totally ignore,
-    (1) The DRIR lines in the typhoon chipset,
-    (2) The "vector" aka mangled interrupt number reported by SRM PALcode,
-    (3) The interrupt number assigned by the kernel.
-   The following function is concerned with (1) only.  */
-
-static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
-{
-    int slot = d->devfn >> 3;
-
-    assert(irq_num >= 0 && irq_num <= 3);
-
-    return (slot + 1) * 4 + irq_num;
-}
-
-static void clipper_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    AlphaCPU *cpus[4];
-    PCIBus *pci_bus;
-    ISABus *isa_bus;
-    qemu_irq rtc_irq;
-    long size, i;
-    const char *palcode_filename;
-    uint64_t palcode_entry, palcode_low, palcode_high;
-    uint64_t kernel_entry, kernel_low, kernel_high;
-
-    /* Create up to 4 cpus.  */
-    memset(cpus, 0, sizeof(cpus));
-    for (i = 0; i < smp_cpus; ++i) {
-        cpus[i] = cpu_alpha_init(cpu_model ? cpu_model : "ev67");
-    }
-
-    cpus[0]->env.trap_arg0 = ram_size;
-    cpus[0]->env.trap_arg1 = 0;
-    cpus[0]->env.trap_arg2 = smp_cpus;
-
-    /* Init the chipset.  */
-    pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus,
-                           clipper_pci_map_irq);
-
-    rtc_init(isa_bus, 1980, rtc_irq);
-    pit_init(isa_bus, 0x40, 0, NULL);
-    isa_create_simple(isa_bus, "i8042");
-
-    /* VGA setup.  Don't bother loading the bios.  */
-    pci_vga_init(pci_bus);
-
-    /* Serial code setup.  */
-    for (i = 0; i < MAX_SERIAL_PORTS; ++i) {
-        if (serial_hds[i]) {
-            serial_isa_init(isa_bus, i, serial_hds[i]);
-        }
-    }
-
-    /* Network setup.  e1000 is good enough, failing Tulip support.  */
-    for (i = 0; i < nb_nics; i++) {
-        pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
-    }
-
-    /* IDE disk setup.  */
-    {
-        DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-        ide_drive_get(hd, MAX_IDE_BUS);
-
-        pci_cmd646_ide_init(pci_bus, hd, 0);
-    }
-
-    /* Load PALcode.  Given that this is not "real" cpu palcode,
-       but one explicitly written for the emulation, we might as
-       well load it directly from and ELF image.  */
-    palcode_filename = (bios_name ? bios_name : "palcode-clipper");
-    palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename);
-    if (palcode_filename == NULL) {
-        hw_error("no palcode provided\n");
-        exit(1);
-    }
-    size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
-                    NULL, &palcode_entry, &palcode_low, &palcode_high,
-                    0, EM_ALPHA, 0);
-    if (size < 0) {
-        hw_error("could not load palcode '%s'\n", palcode_filename);
-        exit(1);
-    }
-
-    /* Start all cpus at the PALcode RESET entry point.  */
-    for (i = 0; i < smp_cpus; ++i) {
-        cpus[i]->env.pal_mode = 1;
-        cpus[i]->env.pc = palcode_entry;
-        cpus[i]->env.palbr = palcode_entry;
-    }
-
-    /* Load a kernel.  */
-    if (kernel_filename) {
-        uint64_t param_offset;
-
-        size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
-                        NULL, &kernel_entry, &kernel_low, &kernel_high,
-                        0, EM_ALPHA, 0);
-        if (size < 0) {
-            hw_error("could not load kernel '%s'\n", kernel_filename);
-            exit(1);
-        }
-
-        cpus[0]->env.trap_arg1 = kernel_entry;
-
-        param_offset = kernel_low - 0x6000;
-
-        if (kernel_cmdline) {
-            pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
-        }
-
-        if (initrd_filename) {
-            long initrd_base, initrd_size;
-
-            initrd_size = get_image_size(initrd_filename);
-            if (initrd_size < 0) {
-                hw_error("could not load initial ram disk '%s'\n",
-                         initrd_filename);
-                exit(1);
-            }
-
-            /* Put the initrd image as high in memory as possible.  */
-            initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
-            load_image_targphys(initrd_filename, initrd_base,
-                                ram_size - initrd_base);
-
-            stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL);
-            stq_phys(param_offset + 0x108, initrd_size);
-        }
-    }
-}
-
-static QEMUMachine clipper_machine = {
-    .name = "clipper",
-    .desc = "Alpha DP264/CLIPPER",
-    .init = clipper_init,
-    .max_cpus = 4,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void clipper_machine_init(void)
-{
-    qemu_register_machine(&clipper_machine);
-}
-
-machine_init(clipper_machine_init);
diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c
deleted file mode 100644 (file)
index 7327d48..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * QEMU Alpha PCI support functions.
- *
- * Some of this isn't very Alpha specific at all.
- *
- * ??? Sparse memory access not implemented.
- */
-
-#include "config.h"
-#include "alpha_sys.h"
-#include "qemu/log.h"
-#include "sysemu/sysemu.h"
-
-
-/* PCI IO reads/writes, to byte-word addressable memory.  */
-/* ??? Doesn't handle multiple PCI busses.  */
-
-static uint64_t bw_io_read(void *opaque, hwaddr addr, unsigned size)
-{
-    switch (size) {
-    case 1:
-        return cpu_inb(addr);
-    case 2:
-        return cpu_inw(addr);
-    case 4:
-        return cpu_inl(addr);
-    }
-    abort();
-}
-
-static void bw_io_write(void *opaque, hwaddr addr,
-                        uint64_t val, unsigned size)
-{
-    switch (size) {
-    case 1:
-        cpu_outb(addr, val);
-        break;
-    case 2:
-        cpu_outw(addr, val);
-        break;
-    case 4:
-        cpu_outl(addr, val);
-        break;
-    default:
-        abort();
-    }
-}
-
-const MemoryRegionOps alpha_pci_bw_io_ops = {
-    .read = bw_io_read,
-    .write = bw_io_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 4,
-    },
-};
-
-/* PCI config space reads/writes, to byte-word addressable memory.  */
-static uint64_t bw_conf1_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    PCIBus *b = opaque;
-    return pci_data_read(b, addr, size);
-}
-
-static void bw_conf1_write(void *opaque, hwaddr addr,
-                           uint64_t val, unsigned size)
-{
-    PCIBus *b = opaque;
-    pci_data_write(b, addr, val, size);
-}
-
-const MemoryRegionOps alpha_pci_conf1_ops = {
-    .read = bw_conf1_read,
-    .write = bw_conf1_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 4,
-    },
-};
-
-/* PCI/EISA Interrupt Acknowledge Cycle.  */
-
-static uint64_t iack_read(void *opaque, hwaddr addr, unsigned size)
-{
-    return pic_read_irq(isa_pic);
-}
-
-static void special_write(void *opaque, hwaddr addr,
-                          uint64_t val, unsigned size)
-{
-    qemu_log("pci: special write cycle");
-}
-
-const MemoryRegionOps alpha_pci_iack_ops = {
-    .read = iack_read,
-    .write = special_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-    .impl = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
index 233a71ecdbdccaa858c8e83af7b9a61cd045c2c7..b4ebd2a9cc68cf897e9d69f40ee19250c7a798d0 100644 (file)
@@ -3,11 +3,11 @@
 #ifndef HW_ALPHA_H
 #define HW_ALPHA_H 1
 
-#include "pci/pci.h"
-#include "pci/pci_host.h"
-#include "ide.h"
-#include "pc.h"
-#include "irq.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/ide.h"
+#include "hw/pc.h"
+#include "hw/irq.h"
 
 
 PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4],
index bf9aabfc08405300129072d1426bc006fb2bd9ac..95571ffc5dbad4902bc5ab9500380b7f5cbd8ab3 100644 (file)
@@ -8,10 +8,10 @@
 
 #include "cpu.h"
 #include "exec/exec-all.h"
-#include "hw.h"
-#include "devices.h"
+#include "hw/hw.h"
+#include "hw/devices.h"
 #include "sysemu/sysemu.h"
-#include "alpha_sys.h"
+#include "hw/alpha_sys.h"
 #include "exec/address-spaces.h"
 
 
diff --git a/hw/an5206.c b/hw/an5206.c
deleted file mode 100644 (file)
index 924be81..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Arnewsh 5206 ColdFire system emulation.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-
-#include "hw.h"
-#include "mcf.h"
-#include "boards.h"
-#include "loader.h"
-#include "elf.h"
-#include "exec/address-spaces.h"
-
-#define KERNEL_LOAD_ADDR 0x10000
-#define AN5206_MBAR_ADDR 0x10000000
-#define AN5206_RAMBAR_ADDR 0x20000000
-
-/* Board init.  */
-
-static void an5206_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    M68kCPU *cpu;
-    CPUM68KState *env;
-    int kernel_size;
-    uint64_t elf_entry;
-    hwaddr entry;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-
-    if (!cpu_model) {
-        cpu_model = "m5206";
-    }
-    cpu = cpu_m68k_init(cpu_model);
-    if (!cpu) {
-        hw_error("Unable to find m68k CPU definition\n");
-    }
-    env = &cpu->env;
-
-    /* Initialize CPU registers.  */
-    env->vbr = 0;
-    /* TODO: allow changing MBAR and RAMBAR.  */
-    env->mbar = AN5206_MBAR_ADDR | 1;
-    env->rambar0 = AN5206_RAMBAR_ADDR | 1;
-
-    /* DRAM at address zero */
-    memory_region_init_ram(ram, "an5206.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, 0, ram);
-
-    /* Internal SRAM.  */
-    memory_region_init_ram(sram, "an5206.sram", 512);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram);
-
-    mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, cpu);
-
-    /* Load kernel.  */
-    if (!kernel_filename) {
-        fprintf(stderr, "Kernel image must be specified\n");
-        exit(1);
-    }
-
-    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                           NULL, NULL, 1, ELF_MACHINE, 0);
-    entry = elf_entry;
-    if (kernel_size < 0) {
-        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
-    }
-    if (kernel_size < 0) {
-        kernel_size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
-                                          ram_size - KERNEL_LOAD_ADDR);
-        entry = KERNEL_LOAD_ADDR;
-    }
-    if (kernel_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
-        exit(1);
-    }
-
-    env->pc = entry;
-}
-
-static QEMUMachine an5206_machine = {
-    .name = "an5206",
-    .desc = "Arnewsh 5206",
-    .init = an5206_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void an5206_machine_init(void)
-{
-    qemu_register_machine(&an5206_machine);
-}
-
-machine_init(an5206_machine_init);
index 7eb0c2bbcb7e68bf8845efa7e28f8a41e52b43c8..7992d6f6fd8fba7a8b943f71bbad15a8ec735e07 100644 (file)
    Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
    the secondary PCI bridge.  */
 
-#include "sysbus.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
-#include "pci/pci_bridge.h"
-#include "pci/pci_bus.h"
-#include "apb_pci.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/apb_pci.h"
 #include "sysemu/sysemu.h"
 #include "exec/address-spaces.h"
 
index fd14b73023db0fd8cd126a6052685ee2fa21edef..8eddba06e5500970b7ae4fe1af897a5e8707daf8 100644 (file)
--- a/hw/apic.c
+++ b/hw/apic.c
  * License along with this library; if not, see <http://www.gnu.org/licenses/>
  */
 #include "qemu/thread.h"
-#include "apic_internal.h"
-#include "apic.h"
-#include "ioapic.h"
-#include "pci/msi.h"
+#include "hw/apic_internal.h"
+#include "hw/apic.h"
+#include "hw/ioapic.h"
+#include "hw/pci/msi.h"
 #include "qemu/host-utils.h"
 #include "trace.h"
-#include "pc.h"
-#include "apic-msidef.h"
+#include "hw/pc.h"
+#include "hw/apic-msidef.h"
 
 #define MAX_APIC_WORDS 8
 
index d8c981050950436af7acea6c6bcc63c38fcdf853..d0c261602c63ac5c7fce68f29dfd753e90d1a8ff 100644 (file)
@@ -17,8 +17,8 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>
  */
-#include "apic.h"
-#include "apic_internal.h"
+#include "hw/apic.h"
+#include "hw/apic_internal.h"
 #include "trace.h"
 #include "sysemu/kvm.h"
 
index 9265e52cd604a79c7b5eaf3c1990f79a82f61d36..578241f861c19684c8205618e882a69c4c456c31 100644 (file)
@@ -21,7 +21,7 @@
 #define QEMU_APIC_INTERNAL_H
 
 #include "exec/memory.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 
 /* APIC Local Vector Table */
index 2e1b1372d24baeccb94d30318b57a8bfa39cc8db..e2846f99c844969e528ea56bdc5db81e9d8975c8 100644 (file)
--- a/hw/apm.c
+++ b/hw/apm.c
@@ -20,9 +20,9 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "apm.h"
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/apm.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 
 //#define DEBUG
 
index 9abb47f99ff208d1695a338c794248f01a26268d..3edea5f623a93ed9583898a5480b678286192a3c 100644 (file)
--- a/hw/apm.h
+++ b/hw/apm.h
@@ -3,7 +3,7 @@
 
 #include <stdint.h>
 #include "qemu-common.h"
-#include "hw.h"
+#include "hw/hw.h"
 #include "exec/memory.h"
 
 typedef void (*apm_ctrl_changed_t)(uint32_t val, void *arg);
index 5a8c4ff2d26e9558c20c30d529f2930d0336011c..44b9bacd88aa4c7dc3e0055bca4657a500b5490a 100644 (file)
@@ -30,8 +30,8 @@
  *
  */
 
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 #include "ui/console.h"
 #include "qemu/timer.h"
 
index 0e7df6098ad2088b7eb09b89b491ed12d6ecd134..2d9c69dfce2b208825f1e7b0391df2c5d081ed26 100644 (file)
@@ -1,37 +1,37 @@
-obj-y = integratorcp.o versatilepb.o arm_pic.o
-obj-y += arm_boot.o
-obj-y += xilinx_zynq.o zynq_slcr.o
+obj-y += zynq_slcr.o
 obj-y += xilinx_spips.o
 obj-y += arm_gic.o arm_gic_common.o
 obj-y += a9scu.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 += realview_gic.o arm_sysctl.o arm11mpcore.o a9mpcore.o
+obj-y += exynos4210_gic.o exynos4210_combiner.o
+obj-y += 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 += 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 += armv7m_nvic.o stellaris_enet.o
+obj-y += 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 \
+obj-y += zaurus.o ide/microdrive.o tc6393xb.o
+obj-y += 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 \
+obj-y += 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 += tsc210x.o
+obj-y += blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
+obj-y += mst_fpga.o
+obj-y += bitbang_i2c.o marvell_88w8618_audio.o
 obj-y += framebuffer.o
-obj-y += 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-$(CONFIG_KVM) += kvm/arm_gic.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
+obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
+obj-y += omap_sx1.o palm.o pic_cpu.o realview.o spitz.o stellaris.o
+obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
+
+obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
+obj-y += omap1.o omap2.o
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
new file mode 100644 (file)
index 0000000..1d5bb59
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * ARMV7M System emulation.
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/loader.h"
+#include "elf.h"
+
+/* Bitbanded IO.  Each word corresponds to a single bit.  */
+
+/* Get the byte address of the real memory for a bitband access.  */
+static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
+{
+    uint32_t res;
+
+    res = *(uint32_t *)opaque;
+    res |= (addr & 0x1ffffff) >> 5;
+    return res;
+
+}
+
+static uint32_t bitband_readb(void *opaque, hwaddr offset)
+{
+    uint8_t v;
+    cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
+    return (v & (1 << ((offset >> 2) & 7))) != 0;
+}
+
+static void bitband_writeb(void *opaque, hwaddr offset,
+                           uint32_t value)
+{
+    uint32_t addr;
+    uint8_t mask;
+    uint8_t v;
+    addr = bitband_addr(opaque, offset);
+    mask = (1 << ((offset >> 2) & 7));
+    cpu_physical_memory_read(addr, &v, 1);
+    if (value & 1)
+        v |= mask;
+    else
+        v &= ~mask;
+    cpu_physical_memory_write(addr, &v, 1);
+}
+
+static uint32_t bitband_readw(void *opaque, hwaddr offset)
+{
+    uint32_t addr;
+    uint16_t mask;
+    uint16_t v;
+    addr = bitband_addr(opaque, offset) & ~1;
+    mask = (1 << ((offset >> 2) & 15));
+    mask = tswap16(mask);
+    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
+    return (v & mask) != 0;
+}
+
+static void bitband_writew(void *opaque, hwaddr offset,
+                           uint32_t value)
+{
+    uint32_t addr;
+    uint16_t mask;
+    uint16_t v;
+    addr = bitband_addr(opaque, offset) & ~1;
+    mask = (1 << ((offset >> 2) & 15));
+    mask = tswap16(mask);
+    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
+    if (value & 1)
+        v |= mask;
+    else
+        v &= ~mask;
+    cpu_physical_memory_write(addr, (uint8_t *)&v, 2);
+}
+
+static uint32_t bitband_readl(void *opaque, hwaddr offset)
+{
+    uint32_t addr;
+    uint32_t mask;
+    uint32_t v;
+    addr = bitband_addr(opaque, offset) & ~3;
+    mask = (1 << ((offset >> 2) & 31));
+    mask = tswap32(mask);
+    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
+    return (v & mask) != 0;
+}
+
+static void bitband_writel(void *opaque, hwaddr offset,
+                           uint32_t value)
+{
+    uint32_t addr;
+    uint32_t mask;
+    uint32_t v;
+    addr = bitband_addr(opaque, offset) & ~3;
+    mask = (1 << ((offset >> 2) & 31));
+    mask = tswap32(mask);
+    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
+    if (value & 1)
+        v |= mask;
+    else
+        v &= ~mask;
+    cpu_physical_memory_write(addr, (uint8_t *)&v, 4);
+}
+
+static const MemoryRegionOps bitband_ops = {
+    .old_mmio = {
+        .read = { bitband_readb, bitband_readw, bitband_readl, },
+        .write = { bitband_writeb, bitband_writew, bitband_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t base;
+} BitBandState;
+
+static int bitband_init(SysBusDevice *dev)
+{
+    BitBandState *s = FROM_SYSBUS(BitBandState, dev);
+
+    memory_region_init_io(&s->iomem, &bitband_ops, &s->base, "bitband",
+                          0x02000000);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static void armv7m_bitband_init(void)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "ARM,bitband-memory");
+    qdev_prop_set_uint32(dev, "base", 0x20000000);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
+
+    dev = qdev_create(NULL, "ARM,bitband-memory");
+    qdev_prop_set_uint32(dev, "base", 0x40000000);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
+}
+
+/* Board init.  */
+
+static void armv7m_reset(void *opaque)
+{
+    ARMCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+/* Init CPU and memory for a v7-M based board.
+   flash_size and sram_size are in kb.
+   Returns the NVIC array.  */
+
+qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
+                      int flash_size, int sram_size,
+                      const char *kernel_filename, const char *cpu_model)
+{
+    ARMCPU *cpu;
+    CPUARMState *env;
+    DeviceState *nvic;
+    /* FIXME: make this local state.  */
+    static qemu_irq pic[64];
+    qemu_irq *cpu_pic;
+    int image_size;
+    uint64_t entry;
+    uint64_t lowaddr;
+    int i;
+    int big_endian;
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    MemoryRegion *hack = g_new(MemoryRegion, 1);
+
+    flash_size *= 1024;
+    sram_size *= 1024;
+
+    if (cpu_model == NULL) {
+       cpu_model = "cortex-m3";
+    }
+    cpu = cpu_arm_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+#if 0
+    /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
+       We don't have proper commandline options, so allocate half of memory
+       as SRAM, up to a maximum of 32Mb, and the rest as code.  */
+    if (ram_size > (512 + 32) * 1024 * 1024)
+        ram_size = (512 + 32) * 1024 * 1024;
+    sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
+    if (sram_size > 32 * 1024 * 1024)
+        sram_size = 32 * 1024 * 1024;
+    code_size = ram_size - sram_size;
+#endif
+
+    /* Flash programming is done via the SCU, so pretend it is ROM.  */
+    memory_region_init_ram(flash, "armv7m.flash", flash_size);
+    vmstate_register_ram_global(flash);
+    memory_region_set_readonly(flash, true);
+    memory_region_add_subregion(address_space_mem, 0, flash);
+    memory_region_init_ram(sram, "armv7m.sram", sram_size);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(address_space_mem, 0x20000000, sram);
+    armv7m_bitband_init();
+
+    nvic = qdev_create(NULL, "armv7m_nvic");
+    env->nvic = nvic;
+    qdev_init_nofail(nvic);
+    cpu_pic = arm_pic_init_cpu(cpu);
+    sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
+    for (i = 0; i < 64; i++) {
+        pic[i] = qdev_get_gpio_in(nvic, i);
+    }
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    big_endian = 1;
+#else
+    big_endian = 0;
+#endif
+
+    if (!kernel_filename) {
+        fprintf(stderr, "Guest image must be specified (using -kernel)\n");
+        exit(1);
+    }
+
+    image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
+                          NULL, big_endian, ELF_MACHINE, 1);
+    if (image_size < 0) {
+        image_size = load_image_targphys(kernel_filename, 0, flash_size);
+       lowaddr = 0;
+    }
+    if (image_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                kernel_filename);
+        exit(1);
+    }
+
+    /* Hack to map an additional page of ram at the top of the address
+       space.  This stops qemu complaining about executing code outside RAM
+       when returning from an exception.  */
+    memory_region_init_ram(hack, "armv7m.hack", 0x1000);
+    vmstate_register_ram_global(hack);
+    memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
+
+    qemu_register_reset(armv7m_reset, cpu);
+    return pic;
+}
+
+static Property bitband_properties[] = {
+    DEFINE_PROP_UINT32("base", BitBandState, base, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void bitband_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = bitband_init;
+    dc->props = bitband_properties;
+}
+
+static const TypeInfo bitband_info = {
+    .name          = "ARM,bitband-memory",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(BitBandState),
+    .class_init    = bitband_class_init,
+};
+
+static void armv7m_register_types(void)
+{
+    type_register_static(&bitband_info);
+}
+
+type_init(armv7m_register_types)
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
new file mode 100644 (file)
index 0000000..43253fd
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ * ARM kernel loader.
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "config.h"
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "sysemu/device_tree.h"
+#include "qemu/config-file.h"
+
+#define KERNEL_ARGS_ADDR 0x100
+#define KERNEL_LOAD_ADDR 0x00010000
+
+/* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
+static uint32_t bootloader[] = {
+  0xe3a00000, /* mov     r0, #0 */
+  0xe59f1004, /* ldr     r1, [pc, #4] */
+  0xe59f2004, /* ldr     r2, [pc, #4] */
+  0xe59ff004, /* ldr     pc, [pc, #4] */
+  0, /* Board ID */
+  0, /* Address of kernel args.  Set by integratorcp_init.  */
+  0  /* Kernel entry point.  Set by integratorcp_init.  */
+};
+
+/* Handling for secondary CPU boot in a multicore system.
+ * Unlike the uniprocessor/primary CPU boot, this is platform
+ * dependent. The default code here is based on the secondary
+ * CPU boot protocol used on realview/vexpress boards, with
+ * some parameterisation to increase its flexibility.
+ * QEMU platform models for which this code is not appropriate
+ * should override write_secondary_boot and secondary_cpu_reset_hook
+ * instead.
+ *
+ * This code enables the interrupt controllers for the secondary
+ * CPUs and then puts all the secondary CPUs into a loop waiting
+ * for an interprocessor interrupt and polling a configurable
+ * location for the kernel secondary CPU entry point.
+ */
+#define DSB_INSN 0xf57ff04f
+#define CP15_DSB_INSN 0xee070f9a /* mcr cp15, 0, r0, c7, c10, 4 */
+
+static uint32_t smpboot[] = {
+  0xe59f2028, /* ldr r2, gic_cpu_if */
+  0xe59f0028, /* ldr r0, startaddr */
+  0xe3a01001, /* mov r1, #1 */
+  0xe5821000, /* str r1, [r2] - set GICC_CTLR.Enable */
+  0xe3a010ff, /* mov r1, #0xff */
+  0xe5821004, /* str r1, [r2, 4] - set GIC_PMR.Priority to 0xff */
+  DSB_INSN,   /* dsb */
+  0xe320f003, /* wfi */
+  0xe5901000, /* ldr     r1, [r0] */
+  0xe1110001, /* tst     r1, r1 */
+  0x0afffffb, /* beq     <wfi> */
+  0xe12fff11, /* bx      r1 */
+  0,          /* gic_cpu_if: base address of GIC CPU interface */
+  0           /* bootreg: Boot register address is held here */
+};
+
+static void default_write_secondary(ARMCPU *cpu,
+                                    const struct arm_boot_info *info)
+{
+    int n;
+    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++) {
+        /* Replace DSB with the pre-v7 DSB if necessary. */
+        if (!arm_feature(&cpu->env, ARM_FEATURE_V7) &&
+            smpboot[n] == DSB_INSN) {
+            smpboot[n] = CP15_DSB_INSN;
+        }
+        smpboot[n] = tswap32(smpboot[n]);
+    }
+    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+                       info->smp_loader_start);
+}
+
+static void default_reset_secondary(ARMCPU *cpu,
+                                    const struct arm_boot_info *info)
+{
+    CPUARMState *env = &cpu->env;
+
+    stl_phys_notdirty(info->smp_bootreg_addr, 0);
+    env->regs[15] = info->smp_loader_start;
+}
+
+#define WRITE_WORD(p, value) do { \
+    stl_phys_notdirty(p, value);  \
+    p += 4;                       \
+} while (0)
+
+static void set_kernel_args(const struct arm_boot_info *info)
+{
+    int initrd_size = info->initrd_size;
+    hwaddr base = info->loader_start;
+    hwaddr p;
+
+    p = base + KERNEL_ARGS_ADDR;
+    /* ATAG_CORE */
+    WRITE_WORD(p, 5);
+    WRITE_WORD(p, 0x54410001);
+    WRITE_WORD(p, 1);
+    WRITE_WORD(p, 0x1000);
+    WRITE_WORD(p, 0);
+    /* ATAG_MEM */
+    /* TODO: handle multiple chips on one ATAG list */
+    WRITE_WORD(p, 4);
+    WRITE_WORD(p, 0x54410002);
+    WRITE_WORD(p, info->ram_size);
+    WRITE_WORD(p, info->loader_start);
+    if (initrd_size) {
+        /* ATAG_INITRD2 */
+        WRITE_WORD(p, 4);
+        WRITE_WORD(p, 0x54420005);
+        WRITE_WORD(p, info->initrd_start);
+        WRITE_WORD(p, initrd_size);
+    }
+    if (info->kernel_cmdline && *info->kernel_cmdline) {
+        /* ATAG_CMDLINE */
+        int cmdline_size;
+
+        cmdline_size = strlen(info->kernel_cmdline);
+        cpu_physical_memory_write(p + 8, (void *)info->kernel_cmdline,
+                                  cmdline_size + 1);
+        cmdline_size = (cmdline_size >> 2) + 1;
+        WRITE_WORD(p, cmdline_size + 2);
+        WRITE_WORD(p, 0x54410009);
+        p += cmdline_size * 4;
+    }
+    if (info->atag_board) {
+        /* ATAG_BOARD */
+        int atag_board_len;
+        uint8_t atag_board_buf[0x1000];
+
+        atag_board_len = (info->atag_board(info, atag_board_buf) + 3) & ~3;
+        WRITE_WORD(p, (atag_board_len + 8) >> 2);
+        WRITE_WORD(p, 0x414f4d50);
+        cpu_physical_memory_write(p, atag_board_buf, atag_board_len);
+        p += atag_board_len;
+    }
+    /* ATAG_END */
+    WRITE_WORD(p, 0);
+    WRITE_WORD(p, 0);
+}
+
+static void set_kernel_args_old(const struct arm_boot_info *info)
+{
+    hwaddr p;
+    const char *s;
+    int initrd_size = info->initrd_size;
+    hwaddr base = info->loader_start;
+
+    /* see linux/include/asm-arm/setup.h */
+    p = base + KERNEL_ARGS_ADDR;
+    /* page_size */
+    WRITE_WORD(p, 4096);
+    /* nr_pages */
+    WRITE_WORD(p, info->ram_size / 4096);
+    /* ramdisk_size */
+    WRITE_WORD(p, 0);
+#define FLAG_READONLY  1
+#define FLAG_RDLOAD    4
+#define FLAG_RDPROMPT  8
+    /* flags */
+    WRITE_WORD(p, FLAG_READONLY | FLAG_RDLOAD | FLAG_RDPROMPT);
+    /* rootdev */
+    WRITE_WORD(p, (31 << 8) | 0);      /* /dev/mtdblock0 */
+    /* video_num_cols */
+    WRITE_WORD(p, 0);
+    /* video_num_rows */
+    WRITE_WORD(p, 0);
+    /* video_x */
+    WRITE_WORD(p, 0);
+    /* video_y */
+    WRITE_WORD(p, 0);
+    /* memc_control_reg */
+    WRITE_WORD(p, 0);
+    /* unsigned char sounddefault */
+    /* unsigned char adfsdrives */
+    /* unsigned char bytes_per_char_h */
+    /* unsigned char bytes_per_char_v */
+    WRITE_WORD(p, 0);
+    /* pages_in_bank[4] */
+    WRITE_WORD(p, 0);
+    WRITE_WORD(p, 0);
+    WRITE_WORD(p, 0);
+    WRITE_WORD(p, 0);
+    /* pages_in_vram */
+    WRITE_WORD(p, 0);
+    /* initrd_start */
+    if (initrd_size) {
+        WRITE_WORD(p, info->initrd_start);
+    } else {
+        WRITE_WORD(p, 0);
+    }
+    /* initrd_size */
+    WRITE_WORD(p, initrd_size);
+    /* rd_start */
+    WRITE_WORD(p, 0);
+    /* system_rev */
+    WRITE_WORD(p, 0);
+    /* system_serial_low */
+    WRITE_WORD(p, 0);
+    /* system_serial_high */
+    WRITE_WORD(p, 0);
+    /* mem_fclk_21285 */
+    WRITE_WORD(p, 0);
+    /* zero unused fields */
+    while (p < base + KERNEL_ARGS_ADDR + 256 + 1024) {
+        WRITE_WORD(p, 0);
+    }
+    s = info->kernel_cmdline;
+    if (s) {
+        cpu_physical_memory_write(p, (void *)s, strlen(s) + 1);
+    } else {
+        WRITE_WORD(p, 0);
+    }
+}
+
+static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
+{
+#ifdef CONFIG_FDT
+    uint32_t *mem_reg_property;
+    uint32_t mem_reg_propsize;
+    void *fdt = NULL;
+    char *filename;
+    int size, rc;
+    uint32_t acells, scells, hival;
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
+    if (!filename) {
+        fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
+        return -1;
+    }
+
+    fdt = load_device_tree(filename, &size);
+    if (!fdt) {
+        fprintf(stderr, "Couldn't open dtb file %s\n", filename);
+        g_free(filename);
+        return -1;
+    }
+    g_free(filename);
+
+    acells = qemu_devtree_getprop_cell(fdt, "/", "#address-cells");
+    scells = qemu_devtree_getprop_cell(fdt, "/", "#size-cells");
+    if (acells == 0 || scells == 0) {
+        fprintf(stderr, "dtb file invalid (#address-cells or #size-cells 0)\n");
+        return -1;
+    }
+
+    mem_reg_propsize = acells + scells;
+    mem_reg_property = g_new0(uint32_t, mem_reg_propsize);
+    mem_reg_property[acells - 1] = cpu_to_be32(binfo->loader_start);
+    hival = cpu_to_be32(binfo->loader_start >> 32);
+    if (acells > 1) {
+        mem_reg_property[acells - 2] = hival;
+    } else if (hival != 0) {
+        fprintf(stderr, "qemu: dtb file not compatible with "
+                "RAM start address > 4GB\n");
+        exit(1);
+    }
+    mem_reg_property[acells + scells - 1] = cpu_to_be32(binfo->ram_size);
+    hival = cpu_to_be32(binfo->ram_size >> 32);
+    if (scells > 1) {
+        mem_reg_property[acells + scells - 2] = hival;
+    } else if (hival != 0) {
+        fprintf(stderr, "qemu: dtb file not compatible with "
+                "RAM size > 4GB\n");
+        exit(1);
+    }
+
+    rc = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
+                              mem_reg_propsize * sizeof(uint32_t));
+    if (rc < 0) {
+        fprintf(stderr, "couldn't set /memory/reg\n");
+    }
+
+    if (binfo->kernel_cmdline && *binfo->kernel_cmdline) {
+        rc = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
+                                          binfo->kernel_cmdline);
+        if (rc < 0) {
+            fprintf(stderr, "couldn't set /chosen/bootargs\n");
+        }
+    }
+
+    if (binfo->initrd_size) {
+        rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                binfo->initrd_start);
+        if (rc < 0) {
+            fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+        }
+
+        rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                    binfo->initrd_start + binfo->initrd_size);
+        if (rc < 0) {
+            fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
+        }
+    }
+
+    cpu_physical_memory_write(addr, fdt, size);
+
+    return 0;
+
+#else
+    fprintf(stderr, "Device tree requested, "
+                "but qemu was compiled without fdt support\n");
+    return -1;
+#endif
+}
+
+static void do_cpu_reset(void *opaque)
+{
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
+    const struct arm_boot_info *info = env->boot_info;
+
+    cpu_reset(CPU(cpu));
+    if (info) {
+        if (!info->is_linux) {
+            /* Jump to the entry point.  */
+            env->regs[15] = info->entry & 0xfffffffe;
+            env->thumb = info->entry & 1;
+        } else {
+            if (env == first_cpu) {
+                env->regs[15] = info->loader_start;
+                if (!info->dtb_filename) {
+                    if (old_param) {
+                        set_kernel_args_old(info);
+                    } else {
+                        set_kernel_args(info);
+                    }
+                }
+            } else {
+                info->secondary_cpu_reset_hook(cpu, info);
+            }
+        }
+    }
+}
+
+void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
+{
+    CPUARMState *env = &cpu->env;
+    int kernel_size;
+    int initrd_size;
+    int n;
+    int is_linux = 0;
+    uint64_t elf_entry;
+    hwaddr entry;
+    int big_endian;
+    QemuOpts *machine_opts;
+
+    /* Load the kernel.  */
+    if (!info->kernel_filename) {
+        fprintf(stderr, "Kernel image must be specified\n");
+        exit(1);
+    }
+
+    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+    if (machine_opts) {
+        info->dtb_filename = qemu_opt_get(machine_opts, "dtb");
+    } else {
+        info->dtb_filename = NULL;
+    }
+
+    if (!info->secondary_cpu_reset_hook) {
+        info->secondary_cpu_reset_hook = default_reset_secondary;
+    }
+    if (!info->write_secondary_boot) {
+        info->write_secondary_boot = default_write_secondary;
+    }
+
+    if (info->nb_cpus == 0)
+        info->nb_cpus = 1;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    big_endian = 1;
+#else
+    big_endian = 0;
+#endif
+
+    /* We want to put the initrd far enough into RAM that when the
+     * kernel is uncompressed it will not clobber the initrd. However
+     * on boards without much RAM we must ensure that we still leave
+     * enough room for a decent sized initrd, and on boards with large
+     * amounts of RAM we must avoid the initrd being so far up in RAM
+     * that it is outside lowmem and inaccessible to the kernel.
+     * So for boards with less  than 256MB of RAM we put the initrd
+     * halfway into RAM, and for boards with 256MB of RAM or more we put
+     * the initrd at 128MB.
+     */
+    info->initrd_start = info->loader_start +
+        MIN(info->ram_size / 2, 128 * 1024 * 1024);
+
+    /* Assume that raw images are linux kernels, and ELF images are not.  */
+    kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
+                           NULL, NULL, big_endian, ELF_MACHINE, 1);
+    entry = elf_entry;
+    if (kernel_size < 0) {
+        kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
+                                  &is_linux);
+    }
+    if (kernel_size < 0) {
+        entry = info->loader_start + KERNEL_LOAD_ADDR;
+        kernel_size = load_image_targphys(info->kernel_filename, entry,
+                                          info->ram_size - KERNEL_LOAD_ADDR);
+        is_linux = 1;
+    }
+    if (kernel_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                info->kernel_filename);
+        exit(1);
+    }
+    info->entry = entry;
+    if (is_linux) {
+        if (info->initrd_filename) {
+            initrd_size = load_image_targphys(info->initrd_filename,
+                                              info->initrd_start,
+                                              info->ram_size -
+                                              info->initrd_start);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initrd '%s'\n",
+                        info->initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_size = 0;
+        }
+        info->initrd_size = initrd_size;
+
+        bootloader[4] = info->board_id;
+
+        /* for device tree boot, we pass the DTB directly in r2. Otherwise
+         * we point to the kernel args.
+         */
+        if (info->dtb_filename) {
+            /* Place the DTB after the initrd in memory. Note that some
+             * kernels will trash anything in the 4K page the initrd
+             * ends in, so make sure the DTB isn't caught up in that.
+             */
+            hwaddr dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size,
+                                             4096);
+            if (load_dtb(dtb_start, info)) {
+                exit(1);
+            }
+            bootloader[5] = dtb_start;
+        } else {
+            bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
+            if (info->ram_size >= (1ULL << 32)) {
+                fprintf(stderr, "qemu: RAM size must be less than 4GB to boot"
+                        " Linux kernel using ATAGS (try passing a device tree"
+                        " using -dtb)\n");
+                exit(1);
+            }
+        }
+        bootloader[6] = entry;
+        for (n = 0; n < sizeof(bootloader) / 4; n++) {
+            bootloader[n] = tswap32(bootloader[n]);
+        }
+        rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
+                           info->loader_start);
+        if (info->nb_cpus > 1) {
+            info->write_secondary_boot(cpu, info);
+        }
+    }
+    info->is_linux = is_linux;
+
+    for (; env; env = env->next_cpu) {
+        cpu = arm_env_get_cpu(env);
+        env->boot_info = info;
+        qemu_register_reset(do_cpu_reset, cpu);
+    }
+}
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
new file mode 100644 (file)
index 0000000..17fddc8
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * SA-1110-based Sharp Zaurus SL-5500 platform.
+ *
+ * Copyright (C) 2011 Dmitry Eremin-Solenikov
+ *
+ * This code is licensed under GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/boards.h"
+#include "hw/devices.h"
+#include "hw/strongarm.h"
+#include "hw/arm-misc.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+static struct arm_boot_info collie_binfo = {
+    .loader_start = SA_SDCS0,
+    .ram_size = 0x20000000,
+};
+
+static void collie_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    StrongARMState *s;
+    DriveInfo *dinfo;
+    MemoryRegion *sysmem = get_system_memory();
+
+    if (!cpu_model) {
+        cpu_model = "sa1110";
+    }
+
+    s = sa1110_init(sysmem, collie_binfo.ram_size, cpu_model);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
+                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+
+    dinfo = drive_get(IF_PFLASH, 0, 1);
+    pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000,
+                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+
+    sysbus_create_simple("scoop", 0x40800000, NULL);
+
+    collie_binfo.kernel_filename = kernel_filename;
+    collie_binfo.kernel_cmdline = kernel_cmdline;
+    collie_binfo.initrd_filename = initrd_filename;
+    collie_binfo.board_id = 0x208;
+    arm_load_kernel(s->cpu, &collie_binfo);
+}
+
+static QEMUMachine collie_machine = {
+    .name = "collie",
+    .desc = "Collie PDA (SA-1110)",
+    .init = collie_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void collie_machine_init(void)
+{
+    qemu_register_machine(&collie_machine);
+}
+
+machine_init(collie_machine_init)
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
new file mode 100644 (file)
index 0000000..4592514
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ *  Samsung exynos4210 SoC emulation
+ *
+ *  Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *    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 "hw/boards.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/loader.h"
+#include "hw/exynos4210.h"
+#include "hw/usb/hcd-ehci.h"
+
+#define EXYNOS4210_CHIPID_ADDR         0x10000000
+
+/* PWM */
+#define EXYNOS4210_PWM_BASE_ADDR       0x139D0000
+
+/* RTC */
+#define EXYNOS4210_RTC_BASE_ADDR       0x10070000
+
+/* MCT */
+#define EXYNOS4210_MCT_BASE_ADDR       0x10050000
+
+/* 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
+
+/* 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
+
+/* PMU SFR base address */
+#define EXYNOS4210_PMU_BASE_ADDR            0x10020000
+
+/* Display controllers (FIMD) */
+#define EXYNOS4210_FIMD0_BASE_ADDR          0x11C00000
+
+/* EHCI */
+#define EXYNOS4210_EHCI_BASE_ADDR           0x12580000
+
+static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
+                                    0x09, 0x00, 0x00, 0x00 };
+
+void exynos4210_write_secondary(ARMCPU *cpu,
+        const struct arm_boot_info *info)
+{
+    int n;
+    uint32_t smpboot[] = {
+        0xe59f3034, /* ldr r3, External gic_cpu_if */
+        0xe59f2034, /* ldr r2, Internal gic_cpu_if */
+        0xe59f0034, /* ldr r0, startaddr */
+        0xe3a01001, /* mov r1, #1 */
+        0xe5821000, /* str r1, [r2] */
+        0xe5831000, /* str r1, [r3] */
+        0xe3a010ff, /* mov r1, #0xff */
+        0xe5821004, /* str r1, [r2, #4] */
+        0xe5831004, /* str r1, [r3, #4] */
+        0xf57ff04f, /* dsb */
+        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 *exynos4210_init(MemoryRegion *system_mem,
+        unsigned long ram_size)
+{
+    qemu_irq cpu_irq[EXYNOS4210_NCPUS];
+    int i, n;
+    Exynos4210State *s = g_new(Exynos4210State, 1);
+    qemu_irq *irqp;
+    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++) {
+        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 */
+        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 */
+    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 = SYS_BUS_DEVICE(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 = SYS_BUS_DEVICE(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][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 = SYS_BUS_DEVICE(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++) {
+        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 = SYS_BUS_DEVICE(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 = SYS_BUS_DEVICE(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);
+    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);
+    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);
+
+   /* 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("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
+
+    /* PWM */
+    sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
+                          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(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 = SYS_BUS_DEVICE(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 = SYS_BUS_DEVICE(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, 0)]);
+
+    exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
+                           EXYNOS4210_UART1_FIFO_SIZE, 1, NULL,
+                  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, 2)]);
+
+    exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
+                           EXYNOS4210_UART3_FIFO_SIZE, 3, NULL,
+                  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);
+
+    sysbus_create_simple(TYPE_EXYNOS4210_EHCI, EXYNOS4210_EHCI_BASE_ADDR,
+            s->irq_table[exynos4210_get_irq(28, 3)]);
+
+    return s;
+}
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
new file mode 100644 (file)
index 0000000..473da34
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ *  Samsung exynos4 SoC based boards emulation
+ *
+ *  Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *    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 "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "net/net.h"
+#include "hw/arm-misc.h"
+#include "exec/address-spaces.h"
+#include "hw/exynos4210.h"
+#include "hw/boards.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
+
+#define SMDK_LAN9118_BASE_ADDR      0x05000000
+
+typedef enum Exynos4BoardType {
+    EXYNOS4_BOARD_NURI,
+    EXYNOS4_BOARD_SMDKC210,
+    EXYNOS4_NUM_OF_BOARDS
+} Exynos4BoardType;
+
+static int exynos4_board_id[EXYNOS4_NUM_OF_BOARDS] = {
+    [EXYNOS4_BOARD_NURI]     = 0xD33,
+    [EXYNOS4_BOARD_SMDKC210] = 0xB16,
+};
+
+static int exynos4_board_smp_bootreg_addr[EXYNOS4_NUM_OF_BOARDS] = {
+    [EXYNOS4_BOARD_NURI]     = EXYNOS4210_SECOND_CPU_BOOTREG,
+    [EXYNOS4_BOARD_SMDKC210] = EXYNOS4210_SECOND_CPU_BOOTREG,
+};
+
+static unsigned long exynos4_board_ram_size[EXYNOS4_NUM_OF_BOARDS] = {
+    [EXYNOS4_BOARD_NURI]     = 0x40000000,
+    [EXYNOS4_BOARD_SMDKC210] = 0x40000000,
+};
+
+static struct arm_boot_info exynos4_board_binfo = {
+    .loader_start     = EXYNOS4210_BASE_BOOT_ADDR,
+    .smp_loader_start = EXYNOS4210_SMP_BOOT_ADDR,
+    .nb_cpus          = EXYNOS4210_NCPUS,
+    .write_secondary_boot = exynos4210_write_secondary,
+};
+
+static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS];
+
+static void lan9215_init(uint32_t base, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    /* This should be a 9215 but the 9118 is close enough */
+    if (nd_table[0].used) {
+        qemu_check_nic_model(&nd_table[0], "lan9118");
+        dev = qdev_create(NULL, "lan9118");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_prop_set_uint32(dev, "mode_16bit", 1);
+        qdev_init_nofail(dev);
+        s = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(s, 0, base);
+        sysbus_connect_irq(s, 0, irq);
+    }
+}
+
+static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
+                                                   Exynos4BoardType board_type)
+{
+    if (smp_cpus != EXYNOS4210_NCPUS) {
+        fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus"
+                " value.\n",
+                exynos4_machines[board_type].name,
+                exynos4_machines[board_type].max_cpus);
+    }
+
+    exynos4_board_binfo.ram_size = exynos4_board_ram_size[board_type];
+    exynos4_board_binfo.board_id = exynos4_board_id[board_type];
+    exynos4_board_binfo.smp_bootreg_addr =
+            exynos4_board_smp_bootreg_addr[board_type];
+    exynos4_board_binfo.kernel_filename = args->kernel_filename;
+    exynos4_board_binfo.initrd_filename = args->initrd_filename;
+    exynos4_board_binfo.kernel_cmdline = args->kernel_cmdline;
+    exynos4_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",
+            exynos4_board_ram_size[board_type] / 1048576,
+            exynos4_board_ram_size[board_type],
+            args->kernel_filename,
+            args->kernel_cmdline,
+            args->initrd_filename);
+
+    return exynos4210_init(get_system_memory(),
+            exynos4_board_ram_size[board_type]);
+}
+
+static void nuri_init(QEMUMachineInitArgs *args)
+{
+    exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI);
+
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
+}
+
+static void smdkc210_init(QEMUMachineInitArgs *args)
+{
+    Exynos4210State *s = exynos4_boards_init_common(args,
+                                                    EXYNOS4_BOARD_SMDKC210);
+
+    lan9215_init(SMDK_LAN9118_BASE_ADDR,
+            qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
+}
+
+static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS] = {
+    [EXYNOS4_BOARD_NURI] = {
+        .name = "nuri",
+        .desc = "Samsung NURI board (Exynos4210)",
+        .init = nuri_init,
+        .max_cpus = EXYNOS4210_NCPUS,
+        DEFAULT_MACHINE_OPTIONS,
+    },
+    [EXYNOS4_BOARD_SMDKC210] = {
+        .name = "smdkc210",
+        .desc = "Samsung SMDKC210 board (Exynos4210)",
+        .init = smdkc210_init,
+        .max_cpus = EXYNOS4210_NCPUS,
+        DEFAULT_MACHINE_OPTIONS,
+    },
+};
+
+static void exynos4_machine_init(void)
+{
+    qemu_register_machine(&exynos4_machines[EXYNOS4_BOARD_NURI]);
+    qemu_register_machine(&exynos4_machines[EXYNOS4_BOARD_SMDKC210]);
+}
+
+machine_init(exynos4_machine_init);
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
new file mode 100644 (file)
index 0000000..8859b73
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Gumstix Platforms
+ *
+ * Copyright (c) 2007 by Thorsten Zitterell <info@bitmux.org>
+ *
+ * Code based on spitz platform by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+/* 
+ * Example usage:
+ * 
+ * connex:
+ * =======
+ * create image:
+ * # dd of=flash bs=1k count=16k if=/dev/zero
+ * # dd of=flash bs=1k conv=notrunc if=u-boot.bin
+ * # dd of=flash bs=1k conv=notrunc seek=256 if=rootfs.arm_nofpu.jffs2
+ * start it:
+ * # qemu-system-arm -M connex -pflash flash -monitor null -nographic
+ *
+ * verdex:
+ * =======
+ * create image:
+ * # dd of=flash bs=1k count=32k if=/dev/zero
+ * # dd of=flash bs=1k conv=notrunc if=u-boot.bin
+ * # dd of=flash bs=1k conv=notrunc seek=256 if=rootfs.arm_nofpu.jffs2
+ * # dd of=flash bs=1k conv=notrunc seek=31744 if=uImage
+ * start it:
+ * # qemu-system-arm -M verdex -pflash flash -monitor null -nographic -m 289
+ */
+
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "net/net.h"
+#include "hw/flash.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+static const int sector_len = 128 * 1024;
+
+static void connex_init(QEMUMachineInitArgs *args)
+{
+    PXA2xxState *cpu;
+    DriveInfo *dinfo;
+    int be;
+    MemoryRegion *address_space_mem = get_system_memory();
+
+    uint32_t connex_rom = 0x01000000;
+    uint32_t connex_ram = 0x04000000;
+
+    cpu = pxa255_init(address_space_mem, connex_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "A flash image must be given with the "
+                "'pflash' parameter\n");
+        exit(1);
+    }
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
+                               dinfo->bdrv, sector_len, connex_rom / sector_len,
+                               2, 0, 0, 0, 0, be)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+        exit(1);
+    }
+
+    /* Interrupt line of NIC is connected to GPIO line 36 */
+    smc91c111_init(&nd_table[0], 0x04000300,
+                    qdev_get_gpio_in(cpu->gpio, 36));
+}
+
+static void verdex_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    PXA2xxState *cpu;
+    DriveInfo *dinfo;
+    int be;
+    MemoryRegion *address_space_mem = get_system_memory();
+
+    uint32_t verdex_rom = 0x02000000;
+    uint32_t verdex_ram = 0x10000000;
+
+    cpu = pxa270_init(address_space_mem, verdex_ram, cpu_model ?: "pxa270-c0");
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "A flash image must be given with the "
+                "'pflash' parameter\n");
+        exit(1);
+    }
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
+                               dinfo->bdrv, sector_len, verdex_rom / sector_len,
+                               2, 0, 0, 0, 0, be)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+        exit(1);
+    }
+
+    /* Interrupt line of NIC is connected to GPIO line 99 */
+    smc91c111_init(&nd_table[0], 0x04000300,
+                    qdev_get_gpio_in(cpu->gpio, 99));
+}
+
+static QEMUMachine connex_machine = {
+    .name = "connex",
+    .desc = "Gumstix Connex (PXA255)",
+    .init = connex_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine verdex_machine = {
+    .name = "verdex",
+    .desc = "Gumstix Verdex (PXA270)",
+    .init = verdex_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void gumstix_machine_init(void)
+{
+    qemu_register_machine(&connex_machine);
+    qemu_register_machine(&verdex_machine);
+}
+
+machine_init(gumstix_machine_init);
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
new file mode 100644 (file)
index 0000000..a622224
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/loader.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/sysbus.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define SMP_BOOT_ADDR 0x100
+#define SMP_BOOT_REG  0x40
+#define GIC_BASE_ADDR 0xfff10000
+
+#define NIRQ_GIC      160
+
+/* Board init.  */
+
+static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
+{
+    int n;
+    uint32_t smpboot[] = {
+        0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
+        0xe210000f, /* ands r0, r0, #0x0f */
+        0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
+        0xe0830200, /* add r0, r3, r0, lsl #4 */
+        0xe59f2024, /* ldr r2, privbase */
+        0xe3a01001, /* mov r1, #1 */
+        0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */
+        0xe3a010ff, /* mov r1, #0xff */
+        0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */
+        0xf57ff04f, /* dsb */
+        0xe320f003, /* wfi */
+        0xe5901000, /* ldr     r1, [r0] */
+        0xe1110001, /* tst     r1, r1 */
+        0x0afffffb, /* beq     <wfi> */
+        0xe12fff11, /* bx      r1 */
+        GIC_BASE_ADDR      /* privbase: gic address.  */
+    };
+    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+        smpboot[n] = tswap32(smpboot[n]);
+    }
+    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
+}
+
+static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
+{
+    CPUARMState *env = &cpu->env;
+
+    switch (info->nb_cpus) {
+    case 4:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x30, 0);
+    case 3:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x20, 0);
+    case 2:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x10, 0);
+        env->regs[15] = SMP_BOOT_ADDR;
+        break;
+    default:
+        break;
+    }
+}
+
+#define NUM_REGS      0x200
+static void hb_regs_write(void *opaque, hwaddr offset,
+                          uint64_t value, unsigned size)
+{
+    uint32_t *regs = opaque;
+
+    if (offset == 0xf00) {
+        if (value == 1 || value == 2) {
+            qemu_system_reset_request();
+        } else if (value == 3) {
+            qemu_system_shutdown_request();
+        }
+    }
+
+    regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, hwaddr offset,
+                             unsigned size)
+{
+    uint32_t *regs = opaque;
+    uint32_t value = regs[offset/4];
+
+    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+        value |= 0x30000000;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+    .read = hb_regs_read,
+    .write = hb_regs_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion *iomem;
+    uint32_t regs[NUM_REGS];
+} HighbankRegsState;
+
+static VMStateDescription vmstate_highbank_regs = {
+    .name = "highbank-regs",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static void highbank_regs_reset(DeviceState *dev)
+{
+    SysBusDevice *sys_dev = SYS_BUS_DEVICE(dev);
+    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, sys_dev);
+
+    s->regs[0x40] = 0x05F20121;
+    s->regs[0x41] = 0x2;
+    s->regs[0x42] = 0x05F30121;
+    s->regs[0x43] = 0x05F40121;
+}
+
+static int highbank_regs_init(SysBusDevice *dev)
+{
+    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev);
+
+    s->iomem = g_new(MemoryRegion, 1);
+    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
+                          0x1000);
+    sysbus_init_mmio(dev, s->iomem);
+
+    return 0;
+}
+
+static void highbank_regs_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    sbc->init = highbank_regs_init;
+    dc->desc = "Calxeda Highbank registers";
+    dc->vmsd = &vmstate_highbank_regs;
+    dc->reset = highbank_regs_reset;
+}
+
+static const TypeInfo highbank_regs_info = {
+    .name          = "highbank-regs",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(HighbankRegsState),
+    .class_init    = highbank_regs_class_init,
+};
+
+static void highbank_regs_register_types(void)
+{
+    type_register_static(&highbank_regs_info);
+}
+
+type_init(highbank_regs_register_types)
+
+static struct arm_boot_info highbank_binfo;
+
+/* ram_size must be set to match the upper bound of memory in the
+ * device tree (linux/arch/arm/boot/dts/highbank.dts), which is
+ * normally 0xff900000 or -m 4089. When running this board on a
+ * 32-bit host, set the reg value of memory to 0xf7ff00000 in the
+ * device tree and pass -m 2047 to QEMU.
+ */
+static void highbank_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[128];
+    int n;
+    qemu_irq cpu_irq[4];
+    MemoryRegion *sysram;
+    MemoryRegion *dram;
+    MemoryRegion *sysmem;
+    char *sysboot_filename;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        ARMCPU *cpu;
+        cpu = cpu_arm_init(cpu_model);
+        if (cpu == NULL) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+
+        /* This will become a QOM property eventually */
+        cpu->reset_cbar = GIC_BASE_ADDR;
+        irqp = arm_pic_init_cpu(cpu);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+
+    sysmem = get_system_memory();
+    dram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, dram);
+
+    sysram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+    if (bios_name != NULL) {
+        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (sysboot_filename != NULL) {
+            uint32_t filesize = get_image_size(sysboot_filename);
+            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
+                hw_error("Unable to load %s\n", bios_name);
+            }
+        } else {
+           hw_error("Unable to find %s\n", bios_name);
+        }
+    }
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, GIC_BASE_ADDR);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 128; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    dev = qdev_create(NULL, "l2x0");
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+    dev = qdev_create(NULL, "sp804");
+    qdev_prop_set_uint32(dev, "freq0", 150000000);
+    qdev_prop_set_uint32(dev, "freq1", 150000000);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff34000);
+    sysbus_connect_irq(busdev, 0, pic[18]);
+    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+    dev = qdev_create(NULL, "highbank-regs");
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff3c000);
+
+    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+    if (nd_table[0].used) {
+        qemu_check_nic_model(&nd_table[0], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff50000);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[77]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[78]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[79]);
+
+        qemu_check_nic_model(&nd_table[1], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[1]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff51000);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[80]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[81]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[82]);
+    }
+
+    highbank_binfo.ram_size = ram_size;
+    highbank_binfo.kernel_filename = kernel_filename;
+    highbank_binfo.kernel_cmdline = kernel_cmdline;
+    highbank_binfo.initrd_filename = initrd_filename;
+    /* highbank requires a dtb in order to boot, and the dtb will override
+     * the board ID. The following value is ignored, so set it to -1 to be
+     * clear that the value is meaningless.
+     */
+    highbank_binfo.board_id = -1;
+    highbank_binfo.nb_cpus = smp_cpus;
+    highbank_binfo.loader_start = 0;
+    highbank_binfo.write_secondary_boot = hb_write_secondary;
+    highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+    .name = "highbank",
+    .desc = "Calxeda Highbank (ECX-1000)",
+    .init = highbank_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void highbank_machine_init(void)
+{
+    qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
new file mode 100644 (file)
index 0000000..e0ba327
--- /dev/null
@@ -0,0 +1,566 @@
+/*
+ * ARM Integrator CP System emulation.
+ *
+ * Copyright (c) 2005-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL
+ */
+
+#include "hw/sysbus.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/arm-misc.h"
+#include "net/net.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t memsz;
+    MemoryRegion flash;
+    uint32_t cm_osc;
+    uint32_t cm_ctrl;
+    uint32_t cm_lock;
+    uint32_t cm_auxosc;
+    uint32_t cm_sdram;
+    uint32_t cm_init;
+    uint32_t cm_flags;
+    uint32_t cm_nvflags;
+    uint32_t int_level;
+    uint32_t irq_enabled;
+    uint32_t fiq_enabled;
+} integratorcm_state;
+
+static uint8_t integrator_spd[128] = {
+   128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
+   0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
+};
+
+static uint64_t integratorcm_read(void *opaque, hwaddr offset,
+                                  unsigned size)
+{
+    integratorcm_state *s = (integratorcm_state *)opaque;
+    if (offset >= 0x100 && offset < 0x200) {
+        /* CM_SPD */
+        if (offset >= 0x180)
+            return 0;
+        return integrator_spd[offset >> 2];
+    }
+    switch (offset >> 2) {
+    case 0: /* CM_ID */
+        return 0x411a3001;
+    case 1: /* CM_PROC */
+        return 0;
+    case 2: /* CM_OSC */
+        return s->cm_osc;
+    case 3: /* CM_CTRL */
+        return s->cm_ctrl;
+    case 4: /* CM_STAT */
+        return 0x00100000;
+    case 5: /* CM_LOCK */
+        if (s->cm_lock == 0xa05f) {
+            return 0x1a05f;
+        } else {
+            return s->cm_lock;
+        }
+    case 6: /* CM_LMBUSCNT */
+        /* ??? High frequency timer.  */
+        hw_error("integratorcm_read: CM_LMBUSCNT");
+    case 7: /* CM_AUXOSC */
+        return s->cm_auxosc;
+    case 8: /* CM_SDRAM */
+        return s->cm_sdram;
+    case 9: /* CM_INIT */
+        return s->cm_init;
+    case 10: /* CM_REFCT */
+        /* ??? High frequency timer.  */
+        hw_error("integratorcm_read: CM_REFCT");
+    case 12: /* CM_FLAGS */
+        return s->cm_flags;
+    case 14: /* CM_NVFLAGS */
+        return s->cm_nvflags;
+    case 16: /* CM_IRQ_STAT */
+        return s->int_level & s->irq_enabled;
+    case 17: /* CM_IRQ_RSTAT */
+        return s->int_level;
+    case 18: /* CM_IRQ_ENSET */
+        return s->irq_enabled;
+    case 20: /* CM_SOFT_INTSET */
+        return s->int_level & 1;
+    case 24: /* CM_FIQ_STAT */
+        return s->int_level & s->fiq_enabled;
+    case 25: /* CM_FIQ_RSTAT */
+        return s->int_level;
+    case 26: /* CM_FIQ_ENSET */
+        return s->fiq_enabled;
+    case 32: /* CM_VOLTAGE_CTL0 */
+    case 33: /* CM_VOLTAGE_CTL1 */
+    case 34: /* CM_VOLTAGE_CTL2 */
+    case 35: /* CM_VOLTAGE_CTL3 */
+        /* ??? Voltage control unimplemented.  */
+        return 0;
+    default:
+        hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
+                 (int)offset);
+        return 0;
+    }
+}
+
+static void integratorcm_do_remap(integratorcm_state *s)
+{
+    /* Sync memory region state with CM_CTRL REMAP bit:
+     * bit 0 => flash at address 0; bit 1 => RAM
+     */
+    memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
+}
+
+static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
+{
+    if (value & 8) {
+        qemu_system_reset_request();
+    }
+    if ((s->cm_ctrl ^ value) & 1) {
+        /* (value & 1) != 0 means the green "MISC LED" is lit.
+         * We don't have any nice place to display LEDs. printf is a bad
+         * idea because Linux uses the LED as a heartbeat and the output
+         * will swamp anything else on the terminal.
+         */
+    }
+    /* Note that the RESET bit [3] always reads as zero */
+    s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
+    integratorcm_do_remap(s);
+}
+
+static void integratorcm_update(integratorcm_state *s)
+{
+    /* ??? The CPU irq/fiq is raised when either the core module or base PIC
+       are active.  */
+    if (s->int_level & (s->irq_enabled | s->fiq_enabled))
+        hw_error("Core module interrupt\n");
+}
+
+static void integratorcm_write(void *opaque, hwaddr offset,
+                               uint64_t value, unsigned size)
+{
+    integratorcm_state *s = (integratorcm_state *)opaque;
+    switch (offset >> 2) {
+    case 2: /* CM_OSC */
+        if (s->cm_lock == 0xa05f)
+            s->cm_osc = value;
+        break;
+    case 3: /* CM_CTRL */
+        integratorcm_set_ctrl(s, value);
+        break;
+    case 5: /* CM_LOCK */
+        s->cm_lock = value & 0xffff;
+        break;
+    case 7: /* CM_AUXOSC */
+        if (s->cm_lock == 0xa05f)
+            s->cm_auxosc = value;
+        break;
+    case 8: /* CM_SDRAM */
+        s->cm_sdram = value;
+        break;
+    case 9: /* CM_INIT */
+        /* ??? This can change the memory bus frequency.  */
+        s->cm_init = value;
+        break;
+    case 12: /* CM_FLAGSS */
+        s->cm_flags |= value;
+        break;
+    case 13: /* CM_FLAGSC */
+        s->cm_flags &= ~value;
+        break;
+    case 14: /* CM_NVFLAGSS */
+        s->cm_nvflags |= value;
+        break;
+    case 15: /* CM_NVFLAGSS */
+        s->cm_nvflags &= ~value;
+        break;
+    case 18: /* CM_IRQ_ENSET */
+        s->irq_enabled |= value;
+        integratorcm_update(s);
+        break;
+    case 19: /* CM_IRQ_ENCLR */
+        s->irq_enabled &= ~value;
+        integratorcm_update(s);
+        break;
+    case 20: /* CM_SOFT_INTSET */
+        s->int_level |= (value & 1);
+        integratorcm_update(s);
+        break;
+    case 21: /* CM_SOFT_INTCLR */
+        s->int_level &= ~(value & 1);
+        integratorcm_update(s);
+        break;
+    case 26: /* CM_FIQ_ENSET */
+        s->fiq_enabled |= value;
+        integratorcm_update(s);
+        break;
+    case 27: /* CM_FIQ_ENCLR */
+        s->fiq_enabled &= ~value;
+        integratorcm_update(s);
+        break;
+    case 32: /* CM_VOLTAGE_CTL0 */
+    case 33: /* CM_VOLTAGE_CTL1 */
+    case 34: /* CM_VOLTAGE_CTL2 */
+    case 35: /* CM_VOLTAGE_CTL3 */
+        /* ??? Voltage control unimplemented.  */
+        break;
+    default:
+        hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
+                 (int)offset);
+        break;
+    }
+}
+
+/* Integrator/CM control registers.  */
+
+static const MemoryRegionOps integratorcm_ops = {
+    .read = integratorcm_read,
+    .write = integratorcm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int integratorcm_init(SysBusDevice *dev)
+{
+    integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
+
+    s->cm_osc = 0x01000048;
+    /* ??? What should the high bits of this value be?  */
+    s->cm_auxosc = 0x0007feff;
+    s->cm_sdram = 0x00011122;
+    if (s->memsz >= 256) {
+        integrator_spd[31] = 64;
+        s->cm_sdram |= 0x10;
+    } else if (s->memsz >= 128) {
+        integrator_spd[31] = 32;
+        s->cm_sdram |= 0x0c;
+    } else if (s->memsz >= 64) {
+        integrator_spd[31] = 16;
+        s->cm_sdram |= 0x08;
+    } else if (s->memsz >= 32) {
+        integrator_spd[31] = 4;
+        s->cm_sdram |= 0x04;
+    } else {
+        integrator_spd[31] = 2;
+    }
+    memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
+    s->cm_init = 0x00000112;
+    memory_region_init_ram(&s->flash, "integrator.flash", 0x100000);
+    vmstate_register_ram_global(&s->flash);
+
+    memory_region_init_io(&s->iomem, &integratorcm_ops, s,
+                          "integratorcm", 0x00800000);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    integratorcm_do_remap(s);
+    /* ??? Save/restore.  */
+    return 0;
+}
+
+/* Integrator/CP hardware emulation.  */
+/* Primary interrupt controller.  */
+
+typedef struct icp_pic_state
+{
+  SysBusDevice busdev;
+  MemoryRegion iomem;
+  uint32_t level;
+  uint32_t irq_enabled;
+  uint32_t fiq_enabled;
+  qemu_irq parent_irq;
+  qemu_irq parent_fiq;
+} icp_pic_state;
+
+static void icp_pic_update(icp_pic_state *s)
+{
+    uint32_t flags;
+
+    flags = (s->level & s->irq_enabled);
+    qemu_set_irq(s->parent_irq, flags != 0);
+    flags = (s->level & s->fiq_enabled);
+    qemu_set_irq(s->parent_fiq, flags != 0);
+}
+
+static void icp_pic_set_irq(void *opaque, int irq, int level)
+{
+    icp_pic_state *s = (icp_pic_state *)opaque;
+    if (level)
+        s->level |= 1 << irq;
+    else
+        s->level &= ~(1 << irq);
+    icp_pic_update(s);
+}
+
+static uint64_t icp_pic_read(void *opaque, hwaddr offset,
+                             unsigned size)
+{
+    icp_pic_state *s = (icp_pic_state *)opaque;
+
+    switch (offset >> 2) {
+    case 0: /* IRQ_STATUS */
+        return s->level & s->irq_enabled;
+    case 1: /* IRQ_RAWSTAT */
+        return s->level;
+    case 2: /* IRQ_ENABLESET */
+        return s->irq_enabled;
+    case 4: /* INT_SOFTSET */
+        return s->level & 1;
+    case 8: /* FRQ_STATUS */
+        return s->level & s->fiq_enabled;
+    case 9: /* FRQ_RAWSTAT */
+        return s->level;
+    case 10: /* FRQ_ENABLESET */
+        return s->fiq_enabled;
+    case 3: /* IRQ_ENABLECLR */
+    case 5: /* INT_SOFTCLR */
+    case 11: /* FRQ_ENABLECLR */
+    default:
+        printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void icp_pic_write(void *opaque, hwaddr offset,
+                          uint64_t value, unsigned size)
+{
+    icp_pic_state *s = (icp_pic_state *)opaque;
+
+    switch (offset >> 2) {
+    case 2: /* IRQ_ENABLESET */
+        s->irq_enabled |= value;
+        break;
+    case 3: /* IRQ_ENABLECLR */
+        s->irq_enabled &= ~value;
+        break;
+    case 4: /* INT_SOFTSET */
+        if (value & 1)
+            icp_pic_set_irq(s, 0, 1);
+        break;
+    case 5: /* INT_SOFTCLR */
+        if (value & 1)
+            icp_pic_set_irq(s, 0, 0);
+        break;
+    case 10: /* FRQ_ENABLESET */
+        s->fiq_enabled |= value;
+        break;
+    case 11: /* FRQ_ENABLECLR */
+        s->fiq_enabled &= ~value;
+        break;
+    case 0: /* IRQ_STATUS */
+    case 1: /* IRQ_RAWSTAT */
+    case 8: /* FRQ_STATUS */
+    case 9: /* FRQ_RAWSTAT */
+    default:
+        printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
+        return;
+    }
+    icp_pic_update(s);
+}
+
+static const MemoryRegionOps icp_pic_ops = {
+    .read = icp_pic_read,
+    .write = icp_pic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int icp_pic_init(SysBusDevice *dev)
+{
+    icp_pic_state *s = FROM_SYSBUS(icp_pic_state, dev);
+
+    qdev_init_gpio_in(&dev->qdev, icp_pic_set_irq, 32);
+    sysbus_init_irq(dev, &s->parent_irq);
+    sysbus_init_irq(dev, &s->parent_fiq);
+    memory_region_init_io(&s->iomem, &icp_pic_ops, s, "icp-pic", 0x00800000);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+/* CP control registers.  */
+
+static uint64_t icp_control_read(void *opaque, hwaddr offset,
+                                 unsigned size)
+{
+    switch (offset >> 2) {
+    case 0: /* CP_IDFIELD */
+        return 0x41034003;
+    case 1: /* CP_FLASHPROG */
+        return 0;
+    case 2: /* CP_INTREG */
+        return 0;
+    case 3: /* CP_DECODE */
+        return 0x11;
+    default:
+        hw_error("icp_control_read: Bad offset %x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void icp_control_write(void *opaque, hwaddr offset,
+                          uint64_t value, unsigned size)
+{
+    switch (offset >> 2) {
+    case 1: /* CP_FLASHPROG */
+    case 2: /* CP_INTREG */
+    case 3: /* CP_DECODE */
+        /* Nothing interesting implemented yet.  */
+        break;
+    default:
+        hw_error("icp_control_write: Bad offset %x\n", (int)offset);
+    }
+}
+
+static const MemoryRegionOps icp_control_ops = {
+    .read = icp_control_read,
+    .write = icp_control_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void icp_control_init(hwaddr base)
+{
+    MemoryRegion *io;
+
+    io = (MemoryRegion *)g_malloc0(sizeof(MemoryRegion));
+    memory_region_init_io(io, &icp_control_ops, NULL,
+                          "control", 0x00800000);
+    memory_region_add_subregion(get_system_memory(), base, io);
+    /* ??? Save/restore.  */
+}
+
+
+/* Board init.  */
+
+static struct arm_boot_info integrator_binfo = {
+    .loader_start = 0x0,
+    .board_id = 0x113,
+};
+
+static void integratorcp_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    ARMCPU *cpu;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
+    qemu_irq pic[32];
+    qemu_irq *cpu_pic;
+    DeviceState *dev;
+    int i;
+
+    if (!cpu_model) {
+        cpu_model = "arm926";
+    }
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+
+    memory_region_init_ram(ram, "integrator.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
+    /* ??? RAM should repeat to fill physical memory space.  */
+    /* SDRAM at address zero*/
+    memory_region_add_subregion(address_space_mem, 0, ram);
+    /* And again at address 0x80000000 */
+    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
+    memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
+
+    dev = qdev_create(NULL, "integrator_core");
+    qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
+
+    cpu_pic = arm_pic_init_cpu(cpu);
+    dev = sysbus_create_varargs("integrator_pic", 0x14000000,
+                                cpu_pic[ARM_PIC_CPU_IRQ],
+                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+    for (i = 0; i < 32; i++) {
+        pic[i] = qdev_get_gpio_in(dev, i);
+    }
+    sysbus_create_simple("integrator_pic", 0xca000000, pic[26]);
+    sysbus_create_varargs("integrator_pit", 0x13000000,
+                          pic[5], pic[6], pic[7], NULL);
+    sysbus_create_simple("pl031", 0x15000000, pic[8]);
+    sysbus_create_simple("pl011", 0x16000000, pic[1]);
+    sysbus_create_simple("pl011", 0x17000000, pic[2]);
+    icp_control_init(0xcb000000);
+    sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
+    sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
+    sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
+    if (nd_table[0].used)
+        smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
+
+    sysbus_create_simple("pl110", 0xc0000000, pic[22]);
+
+    integrator_binfo.ram_size = ram_size;
+    integrator_binfo.kernel_filename = kernel_filename;
+    integrator_binfo.kernel_cmdline = kernel_cmdline;
+    integrator_binfo.initrd_filename = initrd_filename;
+    arm_load_kernel(cpu, &integrator_binfo);
+}
+
+static QEMUMachine integratorcp_machine = {
+    .name = "integratorcp",
+    .desc = "ARM Integrator/CP (ARM926EJ-S)",
+    .init = integratorcp_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void integratorcp_machine_init(void)
+{
+    qemu_register_machine(&integratorcp_machine);
+}
+
+machine_init(integratorcp_machine_init);
+
+static Property core_properties[] = {
+    DEFINE_PROP_UINT32("memsz", integratorcm_state, memsz, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void core_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = integratorcm_init;
+    dc->props = core_properties;
+}
+
+static const TypeInfo core_info = {
+    .name          = "integrator_core",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(integratorcm_state),
+    .class_init    = core_class_init,
+};
+
+static void icp_pic_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = icp_pic_init;
+}
+
+static const TypeInfo icp_pic_info = {
+    .name          = "integrator_pic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(icp_pic_state),
+    .class_init    = icp_pic_class_init,
+};
+
+static void integratorcp_register_types(void)
+{
+    type_register_static(&icp_pic_info);
+    type_register_static(&core_info);
+}
+
+type_init(integratorcp_register_types)
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
new file mode 100644 (file)
index 0000000..ec50a31
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * KZM Board System emulation.
+ *
+ * Copyright (c) 2008 OKL and 2011 NICTA
+ * Written by Hans at OK-Labs
+ * Updated by Peter Chubb.
+ *
+ * This code is licensed under the GPL, version 2 or later.
+ * See the file `COPYING' in the top level directory.
+ *
+ * It (partially) emulates a Kyoto Microcomputer
+ * KZM-ARM11-01 evaluation board, with a Freescale
+ * i.MX31 SoC
+ */
+
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/serial.h"
+#include "hw/imx.h"
+
+    /* Memory map for Kzm Emulation Baseboard:
+     * 0x00000000-0x00003fff 16k secure ROM       IGNORED
+     * 0x00004000-0x00407fff Reserved             IGNORED
+     * 0x00404000-0x00407fff ROM                  IGNORED
+     * 0x00408000-0x0fffffff Reserved             IGNORED
+     * 0x10000000-0x1fffbfff RAM aliasing         IGNORED
+     * 0x1fffc000-0x1fffffff RAM                  EMULATED
+     * 0x20000000-0x2fffffff Reserved             IGNORED
+     * 0x30000000-0x7fffffff I.MX31 Internal Register Space
+     *   0x43f00000 IO_AREA0
+     *   0x43f90000 UART1                         EMULATED
+     *   0x43f94000 UART2                         EMULATED
+     *   0x68000000 AVIC                          EMULATED
+     *   0x53f80000 CCM                           EMULATED
+     *   0x53f94000 PIT 1                         EMULATED
+     *   0x53f98000 PIT 2                         EMULATED
+     *   0x53f90000 GPT                           EMULATED
+     * 0x80000000-0x87ffffff RAM                  EMULATED
+     * 0x88000000-0x8fffffff RAM Aliasing         EMULATED
+     * 0xa0000000-0xafffffff NAND Flash           IGNORED
+     * 0xb0000000-0xb3ffffff Unavailable          IGNORED
+     * 0xb4000000-0xb4000fff 8-bit free space     IGNORED
+     * 0xb4001000-0xb400100f Board control        IGNORED
+     *  0xb4001003           DIP switch
+     * 0xb4001010-0xb400101f 7-segment LED        IGNORED
+     * 0xb4001020-0xb400102f LED                  IGNORED
+     * 0xb4001030-0xb400103f LED                  IGNORED
+     * 0xb4001040-0xb400104f FPGA, UART           EMULATED
+     * 0xb4001050-0xb400105f FPGA, UART           EMULATED
+     * 0xb4001060-0xb40fffff FPGA                 IGNORED
+     * 0xb6000000-0xb61fffff LAN controller       EMULATED
+     * 0xb6200000-0xb62fffff FPGA NAND Controller IGNORED
+     * 0xb6300000-0xb7ffffff Free                 IGNORED
+     * 0xb8000000-0xb8004fff Memory control registers IGNORED
+     * 0xc0000000-0xc3ffffff PCMCIA/CF            IGNORED
+     * 0xc4000000-0xffffffff Reserved             IGNORED
+     */
+
+#define KZM_RAMADDRESS (0x80000000)
+#define KZM_FPGA       (0xb4001040)
+
+static struct arm_boot_info kzm_binfo = {
+    .loader_start = KZM_RAMADDRESS,
+    .board_id = 1722,
+};
+
+static void kzm_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    ARMCPU *cpu;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
+    qemu_irq *cpu_pic;
+    DeviceState *dev;
+    DeviceState *ccm;
+
+    if (!cpu_model) {
+        cpu_model = "arm1136";
+    }
+
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+
+    /* On a real system, the first 16k is a `secure boot rom' */
+
+    memory_region_init_ram(ram, "kzm.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram);
+
+    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
+    memory_region_add_subregion(address_space_mem, 0x88000000, ram_alias);
+
+    memory_region_init_ram(sram, "kzm.sram", 0x4000);
+    memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram);
+
+    cpu_pic = arm_pic_init_cpu(cpu);
+    dev = sysbus_create_varargs("imx_avic", 0x68000000,
+                                cpu_pic[ARM_PIC_CPU_IRQ],
+                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+
+
+    imx_serial_create(0, 0x43f90000, qdev_get_gpio_in(dev, 45));
+    imx_serial_create(1, 0x43f94000, qdev_get_gpio_in(dev, 32));
+
+    ccm = sysbus_create_simple("imx_ccm", 0x53f80000, NULL);
+
+    imx_timerp_create(0x53f94000, qdev_get_gpio_in(dev, 28), ccm);
+    imx_timerp_create(0x53f98000, qdev_get_gpio_in(dev, 27), ccm);
+    imx_timerg_create(0x53f90000, qdev_get_gpio_in(dev, 29), ccm);
+
+    if (nd_table[0].used) {
+        lan9118_init(&nd_table[0], 0xb6000000, qdev_get_gpio_in(dev, 52));
+    }
+
+    if (serial_hds[2]) { /* touchscreen */
+        serial_mm_init(address_space_mem, KZM_FPGA+0x10, 0,
+                       qdev_get_gpio_in(dev, 52),
+                       14745600, serial_hds[2],
+                       DEVICE_NATIVE_ENDIAN);
+    }
+
+    kzm_binfo.ram_size = ram_size;
+    kzm_binfo.kernel_filename = kernel_filename;
+    kzm_binfo.kernel_cmdline = kernel_cmdline;
+    kzm_binfo.initrd_filename = initrd_filename;
+    kzm_binfo.nb_cpus = 1;
+    arm_load_kernel(cpu, &kzm_binfo);
+}
+
+static QEMUMachine kzm_machine = {
+    .name = "kzm",
+    .desc = "ARM KZM Emulation Baseboard (ARM1136)",
+    .init = kzm_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void kzm_machine_init(void)
+{
+    qemu_register_machine(&kzm_machine);
+}
+
+machine_init(kzm_machine_init)
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
new file mode 100644 (file)
index 0000000..aea908f
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * PXA270-based Intel Mainstone platforms.
+ *
+ * Copyright (c) 2007 by Armin Kuster <akuster@kama-aina.net> or
+ *                                    <akuster@mvista.com>
+ *
+ * Code based on spitz platform by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
+#include "net/net.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+/* Device addresses */
+#define MST_FPGA_PHYS  0x08000000
+#define MST_ETH_PHYS   0x10000300
+#define MST_FLASH_0            0x00000000
+#define MST_FLASH_1            0x04000000
+
+/* IRQ definitions */
+#define MMC_IRQ       0
+#define USIM_IRQ      1
+#define USBC_IRQ      2
+#define ETHERNET_IRQ  3
+#define AC97_IRQ      4
+#define PEN_IRQ       5
+#define MSINS_IRQ     6
+#define EXBRD_IRQ     7
+#define S0_CD_IRQ     9
+#define S0_STSCHG_IRQ 10
+#define S0_IRQ        11
+#define S1_CD_IRQ     13
+#define S1_STSCHG_IRQ 14
+#define S1_IRQ        15
+
+static struct keymap map[0xE0] = {
+    [0 ... 0xDF] = { -1, -1 },
+    [0x1e] = {0,0}, /* a */
+    [0x30] = {0,1}, /* b */
+    [0x2e] = {0,2}, /* c */
+    [0x20] = {0,3}, /* d */
+    [0x12] = {0,4}, /* e */
+    [0x21] = {0,5}, /* f */
+    [0x22] = {1,0}, /* g */
+    [0x23] = {1,1}, /* h */
+    [0x17] = {1,2}, /* i */
+    [0x24] = {1,3}, /* j */
+    [0x25] = {1,4}, /* k */
+    [0x26] = {1,5}, /* l */
+    [0x32] = {2,0}, /* m */
+    [0x31] = {2,1}, /* n */
+    [0x18] = {2,2}, /* o */
+    [0x19] = {2,3}, /* p */
+    [0x10] = {2,4}, /* q */
+    [0x13] = {2,5}, /* r */
+    [0x1f] = {3,0}, /* s */
+    [0x14] = {3,1}, /* t */
+    [0x16] = {3,2}, /* u */
+    [0x2f] = {3,3}, /* v */
+    [0x11] = {3,4}, /* w */
+    [0x2d] = {3,5}, /* x */
+    [0x15] = {4,2}, /* y */
+    [0x2c] = {4,3}, /* z */
+    [0xc7] = {5,0}, /* Home */
+    [0x2a] = {5,1}, /* shift */
+    [0x39] = {5,2}, /* space */
+    [0x39] = {5,3}, /* space */
+    [0x1c] = {5,5}, /*  enter */
+    [0xc8] = {6,0}, /* up */
+    [0xd0] = {6,1}, /* down */
+    [0xcb] = {6,2}, /* left */
+    [0xcd] = {6,3}, /* right */
+};
+
+enum mainstone_model_e { mainstone };
+
+#define MAINSTONE_RAM  0x04000000
+#define MAINSTONE_ROM  0x00800000
+#define MAINSTONE_FLASH        0x02000000
+
+static struct arm_boot_info mainstone_binfo = {
+    .loader_start = PXA2XX_SDRAM_BASE,
+    .ram_size = 0x04000000,
+};
+
+static void mainstone_common_init(MemoryRegion *address_space_mem,
+                                  QEMUMachineInitArgs *args,
+                                  enum mainstone_model_e model, int arm_id)
+{
+    uint32_t sector_len = 256 * 1024;
+    hwaddr mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
+    PXA2xxState *mpu;
+    DeviceState *mst_irq;
+    DriveInfo *dinfo;
+    int i;
+    int be;
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    const char *cpu_model = args->cpu_model;
+
+    if (!cpu_model)
+        cpu_model = "pxa270-c5";
+
+    /* Setup CPU & memory */
+    mpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model);
+    memory_region_init_ram(rom, "mainstone.rom", MAINSTONE_ROM);
+    vmstate_register_ram_global(rom);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(address_space_mem, 0, rom);
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    /* There are two 32MiB flash devices on the board */
+    for (i = 0; i < 2; i ++) {
+        dinfo = drive_get(IF_PFLASH, 0, i);
+        if (!dinfo) {
+            fprintf(stderr, "Two flash images must be given with the "
+                    "'pflash' parameter\n");
+            exit(1);
+        }
+
+        if (!pflash_cfi01_register(mainstone_flash_base[i], NULL,
+                                   i ? "mainstone.flash1" : "mainstone.flash0",
+                                   MAINSTONE_FLASH,
+                                   dinfo->bdrv, sector_len,
+                                   MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
+                                   be)) {
+            fprintf(stderr, "qemu: Error registering flash memory.\n");
+            exit(1);
+        }
+    }
+
+    mst_irq = sysbus_create_simple("mainstone-fpga", MST_FPGA_PHYS,
+                    qdev_get_gpio_in(mpu->gpio, 0));
+
+    /* setup keypad */
+    printf("map addr %p\n", &map);
+    pxa27x_register_keypad(mpu->kp, map, 0xe0);
+
+    /* MMC/SD host */
+    pxa2xx_mmci_handlers(mpu->mmc, NULL, qdev_get_gpio_in(mst_irq, MMC_IRQ));
+
+    pxa2xx_pcmcia_set_irq_cb(mpu->pcmcia[0],
+            qdev_get_gpio_in(mst_irq, S0_IRQ),
+            qdev_get_gpio_in(mst_irq, S0_CD_IRQ));
+    pxa2xx_pcmcia_set_irq_cb(mpu->pcmcia[1],
+            qdev_get_gpio_in(mst_irq, S1_IRQ),
+            qdev_get_gpio_in(mst_irq, S1_CD_IRQ));
+
+    smc91c111_init(&nd_table[0], MST_ETH_PHYS,
+                    qdev_get_gpio_in(mst_irq, ETHERNET_IRQ));
+
+    mainstone_binfo.kernel_filename = args->kernel_filename;
+    mainstone_binfo.kernel_cmdline = args->kernel_cmdline;
+    mainstone_binfo.initrd_filename = args->initrd_filename;
+    mainstone_binfo.board_id = arm_id;
+    arm_load_kernel(mpu->cpu, &mainstone_binfo);
+}
+
+static void mainstone_init(QEMUMachineInitArgs *args)
+{
+    mainstone_common_init(get_system_memory(), args, mainstone, 0x196);
+}
+
+static QEMUMachine mainstone2_machine = {
+    .name = "mainstone",
+    .desc = "Mainstone II (PXA27x)",
+    .init = mainstone_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mainstone_machine_init(void)
+{
+    qemu_register_machine(&mainstone2_machine);
+}
+
+machine_init(mainstone_machine_init);
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
new file mode 100644 (file)
index 0000000..a37dbd7
--- /dev/null
@@ -0,0 +1,1697 @@
+/*
+ * Marvell MV88W8618 / Freecom MusicPal emulation.
+ *
+ * Copyright (c) 2008 Jan Kiszka
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/serial.h"
+#include "qemu/timer.h"
+#include "hw/ptimer.h"
+#include "block/block.h"
+#include "hw/flash.h"
+#include "ui/console.h"
+#include "hw/i2c.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+#include "ui/pixel_ops.h"
+
+#define MP_MISC_BASE            0x80002000
+#define MP_MISC_SIZE            0x00001000
+
+#define MP_ETH_BASE             0x80008000
+#define MP_ETH_SIZE             0x00001000
+
+#define MP_WLAN_BASE            0x8000C000
+#define MP_WLAN_SIZE            0x00000800
+
+#define MP_UART1_BASE           0x8000C840
+#define MP_UART2_BASE           0x8000C940
+
+#define MP_GPIO_BASE            0x8000D000
+#define MP_GPIO_SIZE            0x00001000
+
+#define MP_FLASHCFG_BASE        0x90006000
+#define MP_FLASHCFG_SIZE        0x00001000
+
+#define MP_AUDIO_BASE           0x90007000
+
+#define MP_PIC_BASE             0x90008000
+#define MP_PIC_SIZE             0x00001000
+
+#define MP_PIT_BASE             0x90009000
+#define MP_PIT_SIZE             0x00001000
+
+#define MP_LCD_BASE             0x9000c000
+#define MP_LCD_SIZE             0x00001000
+
+#define MP_SRAM_BASE            0xC0000000
+#define MP_SRAM_SIZE            0x00020000
+
+#define MP_RAM_DEFAULT_SIZE     32*1024*1024
+#define MP_FLASH_SIZE_MAX       32*1024*1024
+
+#define MP_TIMER1_IRQ           4
+#define MP_TIMER2_IRQ           5
+#define MP_TIMER3_IRQ           6
+#define MP_TIMER4_IRQ           7
+#define MP_EHCI_IRQ             8
+#define MP_ETH_IRQ              9
+#define MP_UART1_IRQ            11
+#define MP_UART2_IRQ            11
+#define MP_GPIO_IRQ             12
+#define MP_RTC_IRQ              28
+#define MP_AUDIO_IRQ            30
+
+/* Wolfson 8750 I2C address */
+#define MP_WM_ADDR              0x1A
+
+/* Ethernet register offsets */
+#define MP_ETH_SMIR             0x010
+#define MP_ETH_PCXR             0x408
+#define MP_ETH_SDCMR            0x448
+#define MP_ETH_ICR              0x450
+#define MP_ETH_IMR              0x458
+#define MP_ETH_FRDP0            0x480
+#define MP_ETH_FRDP1            0x484
+#define MP_ETH_FRDP2            0x488
+#define MP_ETH_FRDP3            0x48C
+#define MP_ETH_CRDP0            0x4A0
+#define MP_ETH_CRDP1            0x4A4
+#define MP_ETH_CRDP2            0x4A8
+#define MP_ETH_CRDP3            0x4AC
+#define MP_ETH_CTDP0            0x4E0
+#define MP_ETH_CTDP1            0x4E4
+#define MP_ETH_CTDP2            0x4E8
+#define MP_ETH_CTDP3            0x4EC
+
+/* MII PHY access */
+#define MP_ETH_SMIR_DATA        0x0000FFFF
+#define MP_ETH_SMIR_ADDR        0x03FF0000
+#define MP_ETH_SMIR_OPCODE      (1 << 26) /* Read value */
+#define MP_ETH_SMIR_RDVALID     (1 << 27)
+
+/* PHY registers */
+#define MP_ETH_PHY1_BMSR        0x00210000
+#define MP_ETH_PHY1_PHYSID1     0x00410000
+#define MP_ETH_PHY1_PHYSID2     0x00610000
+
+#define MP_PHY_BMSR_LINK        0x0004
+#define MP_PHY_BMSR_AUTONEG     0x0008
+
+#define MP_PHY_88E3015          0x01410E20
+
+/* TX descriptor status */
+#define MP_ETH_TX_OWN           (1 << 31)
+
+/* RX descriptor status */
+#define MP_ETH_RX_OWN           (1 << 31)
+
+/* Interrupt cause/mask bits */
+#define MP_ETH_IRQ_RX_BIT       0
+#define MP_ETH_IRQ_RX           (1 << MP_ETH_IRQ_RX_BIT)
+#define MP_ETH_IRQ_TXHI_BIT     2
+#define MP_ETH_IRQ_TXLO_BIT     3
+
+/* Port config bits */
+#define MP_ETH_PCXR_2BSM_BIT    28 /* 2-byte incoming suffix */
+
+/* SDMA command bits */
+#define MP_ETH_CMD_TXHI         (1 << 23)
+#define MP_ETH_CMD_TXLO         (1 << 22)
+
+typedef struct mv88w8618_tx_desc {
+    uint32_t cmdstat;
+    uint16_t res;
+    uint16_t bytes;
+    uint32_t buffer;
+    uint32_t next;
+} mv88w8618_tx_desc;
+
+typedef struct mv88w8618_rx_desc {
+    uint32_t cmdstat;
+    uint16_t bytes;
+    uint16_t buffer_size;
+    uint32_t buffer;
+    uint32_t next;
+} mv88w8618_rx_desc;
+
+typedef struct mv88w8618_eth_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq irq;
+    uint32_t smir;
+    uint32_t icr;
+    uint32_t imr;
+    int mmio_index;
+    uint32_t vlan_header;
+    uint32_t tx_queue[2];
+    uint32_t rx_queue[4];
+    uint32_t frx_queue[4];
+    uint32_t cur_rx[4];
+    NICState *nic;
+    NICConf conf;
+} mv88w8618_eth_state;
+
+static void eth_rx_desc_put(uint32_t addr, mv88w8618_rx_desc *desc)
+{
+    cpu_to_le32s(&desc->cmdstat);
+    cpu_to_le16s(&desc->bytes);
+    cpu_to_le16s(&desc->buffer_size);
+    cpu_to_le32s(&desc->buffer);
+    cpu_to_le32s(&desc->next);
+    cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
+}
+
+static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc)
+{
+    cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
+    le32_to_cpus(&desc->cmdstat);
+    le16_to_cpus(&desc->bytes);
+    le16_to_cpus(&desc->buffer_size);
+    le32_to_cpus(&desc->buffer);
+    le32_to_cpus(&desc->next);
+}
+
+static int eth_can_receive(NetClientState *nc)
+{
+    return 1;
+}
+
+static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
+{
+    mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
+    uint32_t desc_addr;
+    mv88w8618_rx_desc desc;
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        desc_addr = s->cur_rx[i];
+        if (!desc_addr) {
+            continue;
+        }
+        do {
+            eth_rx_desc_get(desc_addr, &desc);
+            if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) {
+                cpu_physical_memory_write(desc.buffer + s->vlan_header,
+                                          buf, size);
+                desc.bytes = size + s->vlan_header;
+                desc.cmdstat &= ~MP_ETH_RX_OWN;
+                s->cur_rx[i] = desc.next;
+
+                s->icr |= MP_ETH_IRQ_RX;
+                if (s->icr & s->imr) {
+                    qemu_irq_raise(s->irq);
+                }
+                eth_rx_desc_put(desc_addr, &desc);
+                return size;
+            }
+            desc_addr = desc.next;
+        } while (desc_addr != s->rx_queue[i]);
+    }
+    return size;
+}
+
+static void eth_tx_desc_put(uint32_t addr, mv88w8618_tx_desc *desc)
+{
+    cpu_to_le32s(&desc->cmdstat);
+    cpu_to_le16s(&desc->res);
+    cpu_to_le16s(&desc->bytes);
+    cpu_to_le32s(&desc->buffer);
+    cpu_to_le32s(&desc->next);
+    cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
+}
+
+static void eth_tx_desc_get(uint32_t addr, mv88w8618_tx_desc *desc)
+{
+    cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
+    le32_to_cpus(&desc->cmdstat);
+    le16_to_cpus(&desc->res);
+    le16_to_cpus(&desc->bytes);
+    le32_to_cpus(&desc->buffer);
+    le32_to_cpus(&desc->next);
+}
+
+static void eth_send(mv88w8618_eth_state *s, int queue_index)
+{
+    uint32_t desc_addr = s->tx_queue[queue_index];
+    mv88w8618_tx_desc desc;
+    uint32_t next_desc;
+    uint8_t buf[2048];
+    int len;
+
+    do {
+        eth_tx_desc_get(desc_addr, &desc);
+        next_desc = desc.next;
+        if (desc.cmdstat & MP_ETH_TX_OWN) {
+            len = desc.bytes;
+            if (len < 2048) {
+                cpu_physical_memory_read(desc.buffer, buf, len);
+                qemu_send_packet(qemu_get_queue(s->nic), buf, len);
+            }
+            desc.cmdstat &= ~MP_ETH_TX_OWN;
+            s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);
+            eth_tx_desc_put(desc_addr, &desc);
+        }
+        desc_addr = next_desc;
+    } while (desc_addr != s->tx_queue[queue_index]);
+}
+
+static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    mv88w8618_eth_state *s = opaque;
+
+    switch (offset) {
+    case MP_ETH_SMIR:
+        if (s->smir & MP_ETH_SMIR_OPCODE) {
+            switch (s->smir & MP_ETH_SMIR_ADDR) {
+            case MP_ETH_PHY1_BMSR:
+                return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG |
+                       MP_ETH_SMIR_RDVALID;
+            case MP_ETH_PHY1_PHYSID1:
+                return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID;
+            case MP_ETH_PHY1_PHYSID2:
+                return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID;
+            default:
+                return MP_ETH_SMIR_RDVALID;
+            }
+        }
+        return 0;
+
+    case MP_ETH_ICR:
+        return s->icr;
+
+    case MP_ETH_IMR:
+        return s->imr;
+
+    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
+        return s->frx_queue[(offset - MP_ETH_FRDP0)/4];
+
+    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
+        return s->rx_queue[(offset - MP_ETH_CRDP0)/4];
+
+    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
+        return s->tx_queue[(offset - MP_ETH_CTDP0)/4];
+
+    default:
+        return 0;
+    }
+}
+
+static void mv88w8618_eth_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    mv88w8618_eth_state *s = opaque;
+
+    switch (offset) {
+    case MP_ETH_SMIR:
+        s->smir = value;
+        break;
+
+    case MP_ETH_PCXR:
+        s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2;
+        break;
+
+    case MP_ETH_SDCMR:
+        if (value & MP_ETH_CMD_TXHI) {
+            eth_send(s, 1);
+        }
+        if (value & MP_ETH_CMD_TXLO) {
+            eth_send(s, 0);
+        }
+        if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr) {
+            qemu_irq_raise(s->irq);
+        }
+        break;
+
+    case MP_ETH_ICR:
+        s->icr &= value;
+        break;
+
+    case MP_ETH_IMR:
+        s->imr = value;
+        if (s->icr & s->imr) {
+            qemu_irq_raise(s->irq);
+        }
+        break;
+
+    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
+        s->frx_queue[(offset - MP_ETH_FRDP0)/4] = value;
+        break;
+
+    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
+        s->rx_queue[(offset - MP_ETH_CRDP0)/4] =
+            s->cur_rx[(offset - MP_ETH_CRDP0)/4] = value;
+        break;
+
+    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
+        s->tx_queue[(offset - MP_ETH_CTDP0)/4] = value;
+        break;
+    }
+}
+
+static const MemoryRegionOps mv88w8618_eth_ops = {
+    .read = mv88w8618_eth_read,
+    .write = mv88w8618_eth_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void eth_cleanup(NetClientState *nc)
+{
+    mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
+
+    s->nic = NULL;
+}
+
+static NetClientInfo net_mv88w8618_info = {
+    .type = NET_CLIENT_OPTIONS_KIND_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_receive,
+    .receive = eth_receive,
+    .cleanup = eth_cleanup,
+};
+
+static int mv88w8618_eth_init(SysBusDevice *dev)
+{
+    mv88w8618_eth_state *s = FROM_SYSBUS(mv88w8618_eth_state, dev);
+
+    sysbus_init_irq(dev, &s->irq);
+    s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf,
+                          object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+    memory_region_init_io(&s->iomem, &mv88w8618_eth_ops, s, "mv88w8618-eth",
+                          MP_ETH_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static const VMStateDescription mv88w8618_eth_vmsd = {
+    .name = "mv88w8618_eth",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(smir, mv88w8618_eth_state),
+        VMSTATE_UINT32(icr, mv88w8618_eth_state),
+        VMSTATE_UINT32(imr, mv88w8618_eth_state),
+        VMSTATE_UINT32(vlan_header, mv88w8618_eth_state),
+        VMSTATE_UINT32_ARRAY(tx_queue, mv88w8618_eth_state, 2),
+        VMSTATE_UINT32_ARRAY(rx_queue, mv88w8618_eth_state, 4),
+        VMSTATE_UINT32_ARRAY(frx_queue, mv88w8618_eth_state, 4),
+        VMSTATE_UINT32_ARRAY(cur_rx, mv88w8618_eth_state, 4),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property mv88w8618_eth_properties[] = {
+    DEFINE_NIC_PROPERTIES(mv88w8618_eth_state, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mv88w8618_eth_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mv88w8618_eth_init;
+    dc->vmsd = &mv88w8618_eth_vmsd;
+    dc->props = mv88w8618_eth_properties;
+}
+
+static const TypeInfo mv88w8618_eth_info = {
+    .name          = "mv88w8618_eth",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(mv88w8618_eth_state),
+    .class_init    = mv88w8618_eth_class_init,
+};
+
+/* LCD register offsets */
+#define MP_LCD_IRQCTRL          0x180
+#define MP_LCD_IRQSTAT          0x184
+#define MP_LCD_SPICTRL          0x1ac
+#define MP_LCD_INST             0x1bc
+#define MP_LCD_DATA             0x1c0
+
+/* Mode magics */
+#define MP_LCD_SPI_DATA         0x00100011
+#define MP_LCD_SPI_CMD          0x00104011
+#define MP_LCD_SPI_INVALID      0x00000000
+
+/* Commmands */
+#define MP_LCD_INST_SETPAGE0    0xB0
+/* ... */
+#define MP_LCD_INST_SETPAGE7    0xB7
+
+#define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */
+
+typedef struct musicpal_lcd_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t brightness;
+    uint32_t mode;
+    uint32_t irqctrl;
+    uint32_t page;
+    uint32_t page_off;
+    DisplayState *ds;
+    uint8_t video_ram[128*64/8];
+} musicpal_lcd_state;
+
+static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
+{
+    switch (s->brightness) {
+    case 7:
+        return col;
+    case 0:
+        return 0;
+    default:
+        return (col * s->brightness) / 7;
+    }
+}
+
+#define SET_LCD_PIXEL(depth, type) \
+static inline void glue(set_lcd_pixel, depth) \
+        (musicpal_lcd_state *s, int x, int y, type col) \
+{ \
+    int dx, dy; \
+    type *pixel = &((type *) ds_get_data(s->ds))[(y * 128 * 3 + x) * 3]; \
+\
+    for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
+        for (dx = 0; dx < 3; dx++, pixel++) \
+            *pixel = col; \
+}
+SET_LCD_PIXEL(8, uint8_t)
+SET_LCD_PIXEL(16, uint16_t)
+SET_LCD_PIXEL(32, uint32_t)
+
+static void lcd_refresh(void *opaque)
+{
+    musicpal_lcd_state *s = opaque;
+    int x, y, col;
+
+    switch (ds_get_bits_per_pixel(s->ds)) {
+    case 0:
+        return;
+#define LCD_REFRESH(depth, func) \
+    case depth: \
+        col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
+                   scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
+                   scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
+        for (x = 0; x < 128; x++) { \
+            for (y = 0; y < 64; y++) { \
+                if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
+                    glue(set_lcd_pixel, depth)(s, x, y, col); \
+                } else { \
+                    glue(set_lcd_pixel, depth)(s, x, y, 0); \
+                } \
+            } \
+        } \
+        break;
+    LCD_REFRESH(8, rgb_to_pixel8)
+    LCD_REFRESH(16, rgb_to_pixel16)
+    LCD_REFRESH(32, (is_surface_bgr(s->ds->surface) ?
+                     rgb_to_pixel32bgr : rgb_to_pixel32))
+    default:
+        hw_error("unsupported colour depth %i\n",
+                  ds_get_bits_per_pixel(s->ds));
+    }
+
+    dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3);
+}
+
+static void lcd_invalidate(void *opaque)
+{
+}
+
+static void musicpal_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
+{
+    musicpal_lcd_state *s = opaque;
+    s->brightness &= ~(1 << irq);
+    s->brightness |= level << irq;
+}
+
+static uint64_t musicpal_lcd_read(void *opaque, hwaddr offset,
+                                  unsigned size)
+{
+    musicpal_lcd_state *s = opaque;
+
+    switch (offset) {
+    case MP_LCD_IRQCTRL:
+        return s->irqctrl;
+
+    default:
+        return 0;
+    }
+}
+
+static void musicpal_lcd_write(void *opaque, hwaddr offset,
+                               uint64_t value, unsigned size)
+{
+    musicpal_lcd_state *s = opaque;
+
+    switch (offset) {
+    case MP_LCD_IRQCTRL:
+        s->irqctrl = value;
+        break;
+
+    case MP_LCD_SPICTRL:
+        if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
+            s->mode = value;
+        } else {
+            s->mode = MP_LCD_SPI_INVALID;
+        }
+        break;
+
+    case MP_LCD_INST:
+        if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
+            s->page = value - MP_LCD_INST_SETPAGE0;
+            s->page_off = 0;
+        }
+        break;
+
+    case MP_LCD_DATA:
+        if (s->mode == MP_LCD_SPI_CMD) {
+            if (value >= MP_LCD_INST_SETPAGE0 &&
+                value <= MP_LCD_INST_SETPAGE7) {
+                s->page = value - MP_LCD_INST_SETPAGE0;
+                s->page_off = 0;
+            }
+        } else if (s->mode == MP_LCD_SPI_DATA) {
+            s->video_ram[s->page*128 + s->page_off] = value;
+            s->page_off = (s->page_off + 1) & 127;
+        }
+        break;
+    }
+}
+
+static const MemoryRegionOps musicpal_lcd_ops = {
+    .read = musicpal_lcd_read,
+    .write = musicpal_lcd_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int musicpal_lcd_init(SysBusDevice *dev)
+{
+    musicpal_lcd_state *s = FROM_SYSBUS(musicpal_lcd_state, dev);
+
+    s->brightness = 7;
+
+    memory_region_init_io(&s->iomem, &musicpal_lcd_ops, s,
+                          "musicpal-lcd", MP_LCD_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    s->ds = graphic_console_init(lcd_refresh, lcd_invalidate,
+                                 NULL, NULL, s);
+    qemu_console_resize(s->ds, 128*3, 64*3);
+
+    qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3);
+
+    return 0;
+}
+
+static const VMStateDescription musicpal_lcd_vmsd = {
+    .name = "musicpal_lcd",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(brightness, musicpal_lcd_state),
+        VMSTATE_UINT32(mode, musicpal_lcd_state),
+        VMSTATE_UINT32(irqctrl, musicpal_lcd_state),
+        VMSTATE_UINT32(page, musicpal_lcd_state),
+        VMSTATE_UINT32(page_off, musicpal_lcd_state),
+        VMSTATE_BUFFER(video_ram, musicpal_lcd_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void musicpal_lcd_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = musicpal_lcd_init;
+    dc->vmsd = &musicpal_lcd_vmsd;
+}
+
+static const TypeInfo musicpal_lcd_info = {
+    .name          = "musicpal_lcd",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(musicpal_lcd_state),
+    .class_init    = musicpal_lcd_class_init,
+};
+
+/* PIC register offsets */
+#define MP_PIC_STATUS           0x00
+#define MP_PIC_ENABLE_SET       0x08
+#define MP_PIC_ENABLE_CLR       0x0C
+
+typedef struct mv88w8618_pic_state
+{
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t level;
+    uint32_t enabled;
+    qemu_irq parent_irq;
+} mv88w8618_pic_state;
+
+static void mv88w8618_pic_update(mv88w8618_pic_state *s)
+{
+    qemu_set_irq(s->parent_irq, (s->level & s->enabled));
+}
+
+static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
+{
+    mv88w8618_pic_state *s = opaque;
+
+    if (level) {
+        s->level |= 1 << irq;
+    } else {
+        s->level &= ~(1 << irq);
+    }
+    mv88w8618_pic_update(s);
+}
+
+static uint64_t mv88w8618_pic_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    mv88w8618_pic_state *s = opaque;
+
+    switch (offset) {
+    case MP_PIC_STATUS:
+        return s->level & s->enabled;
+
+    default:
+        return 0;
+    }
+}
+
+static void mv88w8618_pic_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    mv88w8618_pic_state *s = opaque;
+
+    switch (offset) {
+    case MP_PIC_ENABLE_SET:
+        s->enabled |= value;
+        break;
+
+    case MP_PIC_ENABLE_CLR:
+        s->enabled &= ~value;
+        s->level &= ~value;
+        break;
+    }
+    mv88w8618_pic_update(s);
+}
+
+static void mv88w8618_pic_reset(DeviceState *d)
+{
+    mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state,
+                                         SYS_BUS_DEVICE(d));
+
+    s->level = 0;
+    s->enabled = 0;
+}
+
+static const MemoryRegionOps mv88w8618_pic_ops = {
+    .read = mv88w8618_pic_read,
+    .write = mv88w8618_pic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int mv88w8618_pic_init(SysBusDevice *dev)
+{
+    mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state, dev);
+
+    qdev_init_gpio_in(&dev->qdev, mv88w8618_pic_set_irq, 32);
+    sysbus_init_irq(dev, &s->parent_irq);
+    memory_region_init_io(&s->iomem, &mv88w8618_pic_ops, s,
+                          "musicpal-pic", MP_PIC_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static const VMStateDescription mv88w8618_pic_vmsd = {
+    .name = "mv88w8618_pic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(level, mv88w8618_pic_state),
+        VMSTATE_UINT32(enabled, mv88w8618_pic_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void mv88w8618_pic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mv88w8618_pic_init;
+    dc->reset = mv88w8618_pic_reset;
+    dc->vmsd = &mv88w8618_pic_vmsd;
+}
+
+static const TypeInfo mv88w8618_pic_info = {
+    .name          = "mv88w8618_pic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(mv88w8618_pic_state),
+    .class_init    = mv88w8618_pic_class_init,
+};
+
+/* PIT register offsets */
+#define MP_PIT_TIMER1_LENGTH    0x00
+/* ... */
+#define MP_PIT_TIMER4_LENGTH    0x0C
+#define MP_PIT_CONTROL          0x10
+#define MP_PIT_TIMER1_VALUE     0x14
+/* ... */
+#define MP_PIT_TIMER4_VALUE     0x20
+#define MP_BOARD_RESET          0x34
+
+/* Magic board reset value (probably some watchdog behind it) */
+#define MP_BOARD_RESET_MAGIC    0x10000
+
+typedef struct mv88w8618_timer_state {
+    ptimer_state *ptimer;
+    uint32_t limit;
+    int freq;
+    qemu_irq irq;
+} mv88w8618_timer_state;
+
+typedef struct mv88w8618_pit_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    mv88w8618_timer_state timer[4];
+} mv88w8618_pit_state;
+
+static void mv88w8618_timer_tick(void *opaque)
+{
+    mv88w8618_timer_state *s = opaque;
+
+    qemu_irq_raise(s->irq);
+}
+
+static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
+                                 uint32_t freq)
+{
+    QEMUBH *bh;
+
+    sysbus_init_irq(dev, &s->irq);
+    s->freq = freq;
+
+    bh = qemu_bh_new(mv88w8618_timer_tick, s);
+    s->ptimer = ptimer_init(bh);
+}
+
+static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    mv88w8618_pit_state *s = opaque;
+    mv88w8618_timer_state *t;
+
+    switch (offset) {
+    case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
+        t = &s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
+        return ptimer_get_count(t->ptimer);
+
+    default:
+        return 0;
+    }
+}
+
+static void mv88w8618_pit_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    mv88w8618_pit_state *s = opaque;
+    mv88w8618_timer_state *t;
+    int i;
+
+    switch (offset) {
+    case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
+        t = &s->timer[offset >> 2];
+        t->limit = value;
+        if (t->limit > 0) {
+            ptimer_set_limit(t->ptimer, t->limit, 1);
+        } else {
+            ptimer_stop(t->ptimer);
+        }
+        break;
+
+    case MP_PIT_CONTROL:
+        for (i = 0; i < 4; i++) {
+            t = &s->timer[i];
+            if (value & 0xf && t->limit > 0) {
+                ptimer_set_limit(t->ptimer, t->limit, 0);
+                ptimer_set_freq(t->ptimer, t->freq);
+                ptimer_run(t->ptimer, 0);
+            } else {
+                ptimer_stop(t->ptimer);
+            }
+            value >>= 4;
+        }
+        break;
+
+    case MP_BOARD_RESET:
+        if (value == MP_BOARD_RESET_MAGIC) {
+            qemu_system_reset_request();
+        }
+        break;
+    }
+}
+
+static void mv88w8618_pit_reset(DeviceState *d)
+{
+    mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state,
+                                         SYS_BUS_DEVICE(d));
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        ptimer_stop(s->timer[i].ptimer);
+        s->timer[i].limit = 0;
+    }
+}
+
+static const MemoryRegionOps mv88w8618_pit_ops = {
+    .read = mv88w8618_pit_read,
+    .write = mv88w8618_pit_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int mv88w8618_pit_init(SysBusDevice *dev)
+{
+    mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state, dev);
+    int i;
+
+    /* Letting them all run at 1 MHz is likely just a pragmatic
+     * simplification. */
+    for (i = 0; i < 4; i++) {
+        mv88w8618_timer_init(dev, &s->timer[i], 1000000);
+    }
+
+    memory_region_init_io(&s->iomem, &mv88w8618_pit_ops, s,
+                          "musicpal-pit", MP_PIT_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static const VMStateDescription mv88w8618_timer_vmsd = {
+    .name = "timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
+        VMSTATE_UINT32(limit, mv88w8618_timer_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription mv88w8618_pit_vmsd = {
+    .name = "mv88w8618_pit",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
+                             mv88w8618_timer_vmsd, mv88w8618_timer_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void mv88w8618_pit_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mv88w8618_pit_init;
+    dc->reset = mv88w8618_pit_reset;
+    dc->vmsd = &mv88w8618_pit_vmsd;
+}
+
+static const TypeInfo mv88w8618_pit_info = {
+    .name          = "mv88w8618_pit",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(mv88w8618_pit_state),
+    .class_init    = mv88w8618_pit_class_init,
+};
+
+/* Flash config register offsets */
+#define MP_FLASHCFG_CFGR0    0x04
+
+typedef struct mv88w8618_flashcfg_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t cfgr0;
+} mv88w8618_flashcfg_state;
+
+static uint64_t mv88w8618_flashcfg_read(void *opaque,
+                                        hwaddr offset,
+                                        unsigned size)
+{
+    mv88w8618_flashcfg_state *s = opaque;
+
+    switch (offset) {
+    case MP_FLASHCFG_CFGR0:
+        return s->cfgr0;
+
+    default:
+        return 0;
+    }
+}
+
+static void mv88w8618_flashcfg_write(void *opaque, hwaddr offset,
+                                     uint64_t value, unsigned size)
+{
+    mv88w8618_flashcfg_state *s = opaque;
+
+    switch (offset) {
+    case MP_FLASHCFG_CFGR0:
+        s->cfgr0 = value;
+        break;
+    }
+}
+
+static const MemoryRegionOps mv88w8618_flashcfg_ops = {
+    .read = mv88w8618_flashcfg_read,
+    .write = mv88w8618_flashcfg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int mv88w8618_flashcfg_init(SysBusDevice *dev)
+{
+    mv88w8618_flashcfg_state *s = FROM_SYSBUS(mv88w8618_flashcfg_state, dev);
+
+    s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
+    memory_region_init_io(&s->iomem, &mv88w8618_flashcfg_ops, s,
+                          "musicpal-flashcfg", MP_FLASHCFG_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static const VMStateDescription mv88w8618_flashcfg_vmsd = {
+    .name = "mv88w8618_flashcfg",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void mv88w8618_flashcfg_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mv88w8618_flashcfg_init;
+    dc->vmsd = &mv88w8618_flashcfg_vmsd;
+}
+
+static const TypeInfo mv88w8618_flashcfg_info = {
+    .name          = "mv88w8618_flashcfg",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(mv88w8618_flashcfg_state),
+    .class_init    = mv88w8618_flashcfg_class_init,
+};
+
+/* Misc register offsets */
+#define MP_MISC_BOARD_REVISION  0x18
+
+#define MP_BOARD_REVISION       0x31
+
+static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    switch (offset) {
+    case MP_MISC_BOARD_REVISION:
+        return MP_BOARD_REVISION;
+
+    default:
+        return 0;
+    }
+}
+
+static void musicpal_misc_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+}
+
+static const MemoryRegionOps musicpal_misc_ops = {
+    .read = musicpal_misc_read,
+    .write = musicpal_misc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void musicpal_misc_init(SysBusDevice *dev)
+{
+    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+
+    memory_region_init_io(iomem, &musicpal_misc_ops, NULL,
+                          "musicpal-misc", MP_MISC_SIZE);
+    sysbus_add_memory(dev, MP_MISC_BASE, iomem);
+}
+
+/* WLAN register offsets */
+#define MP_WLAN_MAGIC1          0x11c
+#define MP_WLAN_MAGIC2          0x124
+
+static uint64_t mv88w8618_wlan_read(void *opaque, hwaddr offset,
+                                    unsigned size)
+{
+    switch (offset) {
+    /* Workaround to allow loading the binary-only wlandrv.ko crap
+     * from the original Freecom firmware. */
+    case MP_WLAN_MAGIC1:
+        return ~3;
+    case MP_WLAN_MAGIC2:
+        return -1;
+
+    default:
+        return 0;
+    }
+}
+
+static void mv88w8618_wlan_write(void *opaque, hwaddr offset,
+                                 uint64_t value, unsigned size)
+{
+}
+
+static const MemoryRegionOps mv88w8618_wlan_ops = {
+    .read = mv88w8618_wlan_read,
+    .write =mv88w8618_wlan_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int mv88w8618_wlan_init(SysBusDevice *dev)
+{
+    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+
+    memory_region_init_io(iomem, &mv88w8618_wlan_ops, NULL,
+                          "musicpal-wlan", MP_WLAN_SIZE);
+    sysbus_init_mmio(dev, iomem);
+    return 0;
+}
+
+/* GPIO register offsets */
+#define MP_GPIO_OE_LO           0x008
+#define MP_GPIO_OUT_LO          0x00c
+#define MP_GPIO_IN_LO           0x010
+#define MP_GPIO_IER_LO          0x014
+#define MP_GPIO_IMR_LO          0x018
+#define MP_GPIO_ISR_LO          0x020
+#define MP_GPIO_OE_HI           0x508
+#define MP_GPIO_OUT_HI          0x50c
+#define MP_GPIO_IN_HI           0x510
+#define MP_GPIO_IER_HI          0x514
+#define MP_GPIO_IMR_HI          0x518
+#define MP_GPIO_ISR_HI          0x520
+
+/* GPIO bits & masks */
+#define MP_GPIO_LCD_BRIGHTNESS  0x00070000
+#define MP_GPIO_I2C_DATA_BIT    29
+#define MP_GPIO_I2C_CLOCK_BIT   30
+
+/* LCD brightness bits in GPIO_OE_HI */
+#define MP_OE_LCD_BRIGHTNESS    0x0007
+
+typedef struct musicpal_gpio_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t lcd_brightness;
+    uint32_t out_state;
+    uint32_t in_state;
+    uint32_t ier;
+    uint32_t imr;
+    uint32_t isr;
+    qemu_irq irq;
+    qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
+} musicpal_gpio_state;
+
+static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
+    int i;
+    uint32_t brightness;
+
+    /* compute brightness ratio */
+    switch (s->lcd_brightness) {
+    case 0x00000007:
+        brightness = 0;
+        break;
+
+    case 0x00020000:
+        brightness = 1;
+        break;
+
+    case 0x00020001:
+        brightness = 2;
+        break;
+
+    case 0x00040000:
+        brightness = 3;
+        break;
+
+    case 0x00010006:
+        brightness = 4;
+        break;
+
+    case 0x00020005:
+        brightness = 5;
+        break;
+
+    case 0x00040003:
+        brightness = 6;
+        break;
+
+    case 0x00030004:
+    default:
+        brightness = 7;
+    }
+
+    /* set lcd brightness GPIOs  */
+    for (i = 0; i <= 2; i++) {
+        qemu_set_irq(s->out[i], (brightness >> i) & 1);
+    }
+}
+
+static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
+{
+    musicpal_gpio_state *s = opaque;
+    uint32_t mask = 1 << pin;
+    uint32_t delta = level << pin;
+    uint32_t old = s->in_state & mask;
+
+    s->in_state &= ~mask;
+    s->in_state |= delta;
+
+    if ((old ^ delta) &&
+        ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
+        s->isr = mask;
+        qemu_irq_raise(s->irq);
+    }
+}
+
+static uint64_t musicpal_gpio_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    musicpal_gpio_state *s = opaque;
+
+    switch (offset) {
+    case MP_GPIO_OE_HI: /* used for LCD brightness control */
+        return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
+
+    case MP_GPIO_OUT_LO:
+        return s->out_state & 0xFFFF;
+    case MP_GPIO_OUT_HI:
+        return s->out_state >> 16;
+
+    case MP_GPIO_IN_LO:
+        return s->in_state & 0xFFFF;
+    case MP_GPIO_IN_HI:
+        return s->in_state >> 16;
+
+    case MP_GPIO_IER_LO:
+        return s->ier & 0xFFFF;
+    case MP_GPIO_IER_HI:
+        return s->ier >> 16;
+
+    case MP_GPIO_IMR_LO:
+        return s->imr & 0xFFFF;
+    case MP_GPIO_IMR_HI:
+        return s->imr >> 16;
+
+    case MP_GPIO_ISR_LO:
+        return s->isr & 0xFFFF;
+    case MP_GPIO_ISR_HI:
+        return s->isr >> 16;
+
+    default:
+        return 0;
+    }
+}
+
+static void musicpal_gpio_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    musicpal_gpio_state *s = opaque;
+    switch (offset) {
+    case MP_GPIO_OE_HI: /* used for LCD brightness control */
+        s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
+                         (value & MP_OE_LCD_BRIGHTNESS);
+        musicpal_gpio_brightness_update(s);
+        break;
+
+    case MP_GPIO_OUT_LO:
+        s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
+        break;
+    case MP_GPIO_OUT_HI:
+        s->out_state = (s->out_state & 0xFFFF) | (value << 16);
+        s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
+                            (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
+        musicpal_gpio_brightness_update(s);
+        qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
+        qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
+        break;
+
+    case MP_GPIO_IER_LO:
+        s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
+        break;
+    case MP_GPIO_IER_HI:
+        s->ier = (s->ier & 0xFFFF) | (value << 16);
+        break;
+
+    case MP_GPIO_IMR_LO:
+        s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
+        break;
+    case MP_GPIO_IMR_HI:
+        s->imr = (s->imr & 0xFFFF) | (value << 16);
+        break;
+    }
+}
+
+static const MemoryRegionOps musicpal_gpio_ops = {
+    .read = musicpal_gpio_read,
+    .write = musicpal_gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void musicpal_gpio_reset(DeviceState *d)
+{
+    musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state,
+                                         SYS_BUS_DEVICE(d));
+
+    s->lcd_brightness = 0;
+    s->out_state = 0;
+    s->in_state = 0xffffffff;
+    s->ier = 0;
+    s->imr = 0;
+    s->isr = 0;
+}
+
+static int musicpal_gpio_init(SysBusDevice *dev)
+{
+    musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state, dev);
+
+    sysbus_init_irq(dev, &s->irq);
+
+    memory_region_init_io(&s->iomem, &musicpal_gpio_ops, s,
+                          "musicpal-gpio", MP_GPIO_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
+
+    qdev_init_gpio_in(&dev->qdev, musicpal_gpio_pin_event, 32);
+
+    return 0;
+}
+
+static const VMStateDescription musicpal_gpio_vmsd = {
+    .name = "musicpal_gpio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
+        VMSTATE_UINT32(out_state, musicpal_gpio_state),
+        VMSTATE_UINT32(in_state, musicpal_gpio_state),
+        VMSTATE_UINT32(ier, musicpal_gpio_state),
+        VMSTATE_UINT32(imr, musicpal_gpio_state),
+        VMSTATE_UINT32(isr, musicpal_gpio_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void musicpal_gpio_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = musicpal_gpio_init;
+    dc->reset = musicpal_gpio_reset;
+    dc->vmsd = &musicpal_gpio_vmsd;
+}
+
+static const TypeInfo musicpal_gpio_info = {
+    .name          = "musicpal_gpio",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(musicpal_gpio_state),
+    .class_init    = musicpal_gpio_class_init,
+};
+
+/* Keyboard codes & masks */
+#define KEY_RELEASED            0x80
+#define KEY_CODE                0x7f
+
+#define KEYCODE_TAB             0x0f
+#define KEYCODE_ENTER           0x1c
+#define KEYCODE_F               0x21
+#define KEYCODE_M               0x32
+
+#define KEYCODE_EXTENDED        0xe0
+#define KEYCODE_UP              0x48
+#define KEYCODE_DOWN            0x50
+#define KEYCODE_LEFT            0x4b
+#define KEYCODE_RIGHT           0x4d
+
+#define MP_KEY_WHEEL_VOL       (1 << 0)
+#define MP_KEY_WHEEL_VOL_INV   (1 << 1)
+#define MP_KEY_WHEEL_NAV       (1 << 2)
+#define MP_KEY_WHEEL_NAV_INV   (1 << 3)
+#define MP_KEY_BTN_FAVORITS    (1 << 4)
+#define MP_KEY_BTN_MENU        (1 << 5)
+#define MP_KEY_BTN_VOLUME      (1 << 6)
+#define MP_KEY_BTN_NAVIGATION  (1 << 7)
+
+typedef struct musicpal_key_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t kbd_extended;
+    uint32_t pressed_keys;
+    qemu_irq out[8];
+} musicpal_key_state;
+
+static void musicpal_key_event(void *opaque, int keycode)
+{
+    musicpal_key_state *s = opaque;
+    uint32_t event = 0;
+    int i;
+
+    if (keycode == KEYCODE_EXTENDED) {
+        s->kbd_extended = 1;
+        return;
+    }
+
+    if (s->kbd_extended) {
+        switch (keycode & KEY_CODE) {
+        case KEYCODE_UP:
+            event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
+            break;
+
+        case KEYCODE_DOWN:
+            event = MP_KEY_WHEEL_NAV;
+            break;
+
+        case KEYCODE_LEFT:
+            event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
+            break;
+
+        case KEYCODE_RIGHT:
+            event = MP_KEY_WHEEL_VOL;
+            break;
+        }
+    } else {
+        switch (keycode & KEY_CODE) {
+        case KEYCODE_F:
+            event = MP_KEY_BTN_FAVORITS;
+            break;
+
+        case KEYCODE_TAB:
+            event = MP_KEY_BTN_VOLUME;
+            break;
+
+        case KEYCODE_ENTER:
+            event = MP_KEY_BTN_NAVIGATION;
+            break;
+
+        case KEYCODE_M:
+            event = MP_KEY_BTN_MENU;
+            break;
+        }
+        /* Do not repeat already pressed buttons */
+        if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
+            event = 0;
+        }
+    }
+
+    if (event) {
+        /* Raise GPIO pin first if repeating a key */
+        if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
+            for (i = 0; i <= 7; i++) {
+                if (event & (1 << i)) {
+                    qemu_set_irq(s->out[i], 1);
+                }
+            }
+        }
+        for (i = 0; i <= 7; i++) {
+            if (event & (1 << i)) {
+                qemu_set_irq(s->out[i], !!(keycode & KEY_RELEASED));
+            }
+        }
+        if (keycode & KEY_RELEASED) {
+            s->pressed_keys &= ~event;
+        } else {
+            s->pressed_keys |= event;
+        }
+    }
+
+    s->kbd_extended = 0;
+}
+
+static int musicpal_key_init(SysBusDevice *dev)
+{
+    musicpal_key_state *s = FROM_SYSBUS(musicpal_key_state, dev);
+
+    memory_region_init(&s->iomem, "dummy", 0);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    s->kbd_extended = 0;
+    s->pressed_keys = 0;
+
+    qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
+
+    qemu_add_kbd_event_handler(musicpal_key_event, s);
+
+    return 0;
+}
+
+static const VMStateDescription musicpal_key_vmsd = {
+    .name = "musicpal_key",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(kbd_extended, musicpal_key_state),
+        VMSTATE_UINT32(pressed_keys, musicpal_key_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void musicpal_key_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = musicpal_key_init;
+    dc->vmsd = &musicpal_key_vmsd;
+}
+
+static const TypeInfo musicpal_key_info = {
+    .name          = "musicpal_key",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(musicpal_key_state),
+    .class_init    = musicpal_key_class_init,
+};
+
+static struct arm_boot_info musicpal_binfo = {
+    .loader_start = 0x0,
+    .board_id = 0x20e,
+};
+
+static void musicpal_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    ARMCPU *cpu;
+    qemu_irq *cpu_pic;
+    qemu_irq pic[32];
+    DeviceState *dev;
+    DeviceState *i2c_dev;
+    DeviceState *lcd_dev;
+    DeviceState *key_dev;
+    DeviceState *wm8750_dev;
+    SysBusDevice *s;
+    i2c_bus *i2c;
+    int i;
+    unsigned long flash_size;
+    DriveInfo *dinfo;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+
+    if (!cpu_model) {
+        cpu_model = "arm926";
+    }
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    cpu_pic = arm_pic_init_cpu(cpu);
+
+    /* For now we use a fixed - the original - RAM size */
+    memory_region_init_ram(ram, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, 0, ram);
+
+    memory_region_init_ram(sram, "musicpal.sram", MP_SRAM_SIZE);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
+
+    dev = sysbus_create_simple("mv88w8618_pic", MP_PIC_BASE,
+                               cpu_pic[ARM_PIC_CPU_IRQ]);
+    for (i = 0; i < 32; i++) {
+        pic[i] = qdev_get_gpio_in(dev, i);
+    }
+    sysbus_create_varargs("mv88w8618_pit", MP_PIT_BASE, pic[MP_TIMER1_IRQ],
+                          pic[MP_TIMER2_IRQ], pic[MP_TIMER3_IRQ],
+                          pic[MP_TIMER4_IRQ], NULL);
+
+    if (serial_hds[0]) {
+        serial_mm_init(address_space_mem, MP_UART1_BASE, 2, pic[MP_UART1_IRQ],
+                       1825000, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+    }
+    if (serial_hds[1]) {
+        serial_mm_init(address_space_mem, MP_UART2_BASE, 2, pic[MP_UART2_IRQ],
+                       1825000, serial_hds[1], DEVICE_NATIVE_ENDIAN);
+    }
+
+    /* Register flash */
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (dinfo) {
+        flash_size = bdrv_getlength(dinfo->bdrv);
+        if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
+            flash_size != 32*1024*1024) {
+            fprintf(stderr, "Invalid flash image size\n");
+            exit(1);
+        }
+
+        /*
+         * The original U-Boot accesses the flash at 0xFE000000 instead of
+         * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
+         * image is smaller than 32 MB.
+         */
+#ifdef TARGET_WORDS_BIGENDIAN
+        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
+                              "musicpal.flash", flash_size,
+                              dinfo->bdrv, 0x10000,
+                              (flash_size + 0xffff) >> 16,
+                              MP_FLASH_SIZE_MAX / flash_size,
+                              2, 0x00BF, 0x236D, 0x0000, 0x0000,
+                              0x5555, 0x2AAA, 1);
+#else
+        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
+                              "musicpal.flash", flash_size,
+                              dinfo->bdrv, 0x10000,
+                              (flash_size + 0xffff) >> 16,
+                              MP_FLASH_SIZE_MAX / flash_size,
+                              2, 0x00BF, 0x236D, 0x0000, 0x0000,
+                              0x5555, 0x2AAA, 0);
+#endif
+
+    }
+    sysbus_create_simple("mv88w8618_flashcfg", MP_FLASHCFG_BASE, NULL);
+
+    qemu_check_nic_model(&nd_table[0], "mv88w8618");
+    dev = qdev_create(NULL, "mv88w8618_eth");
+    qdev_set_nic_properties(dev, &nd_table[0]);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[MP_ETH_IRQ]);
+
+    sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
+
+    musicpal_misc_init(SYS_BUS_DEVICE(dev));
+
+    dev = sysbus_create_simple("musicpal_gpio", MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
+    i2c_dev = sysbus_create_simple("gpio_i2c", -1, NULL);
+    i2c = (i2c_bus *)qdev_get_child_bus(i2c_dev, "i2c");
+
+    lcd_dev = sysbus_create_simple("musicpal_lcd", MP_LCD_BASE, NULL);
+    key_dev = sysbus_create_simple("musicpal_key", -1, NULL);
+
+    /* I2C read data */
+    qdev_connect_gpio_out(i2c_dev, 0,
+                          qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
+    /* I2C data */
+    qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
+    /* I2C clock */
+    qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
+
+    for (i = 0; i < 3; i++) {
+        qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
+    }
+    for (i = 0; i < 4; i++) {
+        qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
+    }
+    for (i = 4; i < 8; i++) {
+        qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
+    }
+
+    wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
+    dev = qdev_create(NULL, "mv88w8618_audio");
+    s = SYS_BUS_DEVICE(dev);
+    qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
+    sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
+
+    musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
+    musicpal_binfo.kernel_filename = kernel_filename;
+    musicpal_binfo.kernel_cmdline = kernel_cmdline;
+    musicpal_binfo.initrd_filename = initrd_filename;
+    arm_load_kernel(cpu, &musicpal_binfo);
+}
+
+static QEMUMachine musicpal_machine = {
+    .name = "musicpal",
+    .desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)",
+    .init = musicpal_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void musicpal_machine_init(void)
+{
+    qemu_register_machine(&musicpal_machine);
+}
+
+machine_init(musicpal_machine_init);
+
+static void mv88w8618_wlan_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = mv88w8618_wlan_init;
+}
+
+static const TypeInfo mv88w8618_wlan_info = {
+    .name          = "mv88w8618_wlan",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SysBusDevice),
+    .class_init    = mv88w8618_wlan_class_init,
+};
+
+static void musicpal_register_types(void)
+{
+    type_register_static(&mv88w8618_pic_info);
+    type_register_static(&mv88w8618_pit_info);
+    type_register_static(&mv88w8618_flashcfg_info);
+    type_register_static(&mv88w8618_eth_info);
+    type_register_static(&mv88w8618_wlan_info);
+    type_register_static(&musicpal_lcd_info);
+    type_register_static(&musicpal_gpio_info);
+    type_register_static(&musicpal_key_info);
+}
+
+type_init(musicpal_register_types)
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
new file mode 100644 (file)
index 0000000..c5bf9f9
--- /dev/null
@@ -0,0 +1,1430 @@
+/*
+ * Nokia N-series internet tablets.
+ *
+ * Copyright (C) 2007 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * 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 "qemu-common.h"
+#include "sysemu/sysemu.h"
+#include "hw/omap.h"
+#include "hw/arm-misc.h"
+#include "hw/irq.h"
+#include "ui/console.h"
+#include "hw/boards.h"
+#include "hw/i2c.h"
+#include "hw/devices.h"
+#include "hw/flash.h"
+#include "hw/hw.h"
+#include "hw/bt.h"
+#include "hw/loader.h"
+#include "sysemu/blockdev.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+/* Nokia N8x0 support */
+struct n800_s {
+    struct omap_mpu_state_s *mpu;
+
+    struct rfbi_chip_s blizzard;
+    struct {
+        void *opaque;
+        uint32_t (*txrx)(void *opaque, uint32_t value, int len);
+        uWireSlave *chip;
+    } ts;
+
+    int keymap[0x80];
+    DeviceState *kbd;
+
+    DeviceState *usb;
+    void *retu;
+    void *tahvo;
+    DeviceState *nand;
+};
+
+/* GPIO pins */
+#define N8X0_TUSB_ENABLE_GPIO          0
+#define N800_MMC2_WP_GPIO              8
+#define N800_UNKNOWN_GPIO0             9       /* out */
+#define N810_MMC2_VIOSD_GPIO           9
+#define N810_HEADSET_AMP_GPIO          10
+#define N800_CAM_TURN_GPIO             12
+#define N810_GPS_RESET_GPIO            12
+#define N800_BLIZZARD_POWERDOWN_GPIO   15
+#define N800_MMC1_WP_GPIO              23
+#define N810_MMC2_VSD_GPIO             23
+#define N8X0_ONENAND_GPIO              26
+#define N810_BLIZZARD_RESET_GPIO       30
+#define N800_UNKNOWN_GPIO2             53      /* out */
+#define N8X0_TUSB_INT_GPIO             58
+#define N8X0_BT_WKUP_GPIO              61
+#define N8X0_STI_GPIO                  62
+#define N8X0_CBUS_SEL_GPIO             64
+#define N8X0_CBUS_DAT_GPIO             65
+#define N8X0_CBUS_CLK_GPIO             66
+#define N8X0_WLAN_IRQ_GPIO             87
+#define N8X0_BT_RESET_GPIO             92
+#define N8X0_TEA5761_CS_GPIO           93
+#define N800_UNKNOWN_GPIO              94
+#define N810_TSC_RESET_GPIO            94
+#define N800_CAM_ACT_GPIO              95
+#define N810_GPS_WAKEUP_GPIO           95
+#define N8X0_MMC_CS_GPIO               96
+#define N8X0_WLAN_PWR_GPIO             97
+#define N8X0_BT_HOST_WKUP_GPIO         98
+#define N810_SPEAKER_AMP_GPIO          101
+#define N810_KB_LOCK_GPIO              102
+#define N800_TSC_TS_GPIO               103
+#define N810_TSC_TS_GPIO               106
+#define N8X0_HEADPHONE_GPIO            107
+#define N8X0_RETU_GPIO                 108
+#define N800_TSC_KP_IRQ_GPIO           109
+#define N810_KEYBOARD_GPIO             109
+#define N800_BAT_COVER_GPIO            110
+#define N810_SLIDE_GPIO                        110
+#define N8X0_TAHVO_GPIO                        111
+#define N800_UNKNOWN_GPIO4             112     /* out */
+#define N810_SLEEPX_LED_GPIO           112
+#define N800_TSC_RESET_GPIO            118     /* ? */
+#define N810_AIC33_RESET_GPIO          118
+#define N800_TSC_UNKNOWN_GPIO          119     /* out */
+#define N8X0_TMP105_GPIO               125
+
+/* Config */
+#define BT_UART                                0
+#define XLDR_LL_UART                   1
+
+/* Addresses on the I2C bus 0 */
+#define N810_TLV320AIC33_ADDR          0x18    /* Audio CODEC */
+#define N8X0_TCM825x_ADDR              0x29    /* Camera */
+#define N810_LP5521_ADDR               0x32    /* LEDs */
+#define N810_TSL2563_ADDR              0x3d    /* Light sensor */
+#define N810_LM8323_ADDR               0x45    /* Keyboard */
+/* Addresses on the I2C bus 1 */
+#define N8X0_TMP105_ADDR               0x48    /* Temperature sensor */
+#define N8X0_MENELAUS_ADDR             0x72    /* Power management */
+
+/* Chipselects on GPMC NOR interface */
+#define N8X0_ONENAND_CS                        0
+#define N8X0_USB_ASYNC_CS              1
+#define N8X0_USB_SYNC_CS               4
+
+#define N8X0_BD_ADDR                   0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81
+
+static void n800_mmc_cs_cb(void *opaque, int line, int level)
+{
+    /* TODO: this seems to actually be connected to the menelaus, to
+     * which also both MMC slots connect.  */
+    omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
+
+    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
+}
+
+static void n8x0_gpio_setup(struct n800_s *s)
+{
+    qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->mpu->mmc, 1);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
+
+    qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO));
+}
+
+#define MAEMO_CAL_HEADER(...)                          \
+    'C',  'o',  'n',  'F',  0x02, 0x00, 0x04, 0x00,    \
+    __VA_ARGS__,                                       \
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+static const uint8_t n8x0_cal_wlan_mac[] = {
+    MAEMO_CAL_HEADER('w', 'l', 'a', 'n', '-', 'm', 'a', 'c')
+    0x1c, 0x00, 0x00, 0x00, 0x47, 0xd6, 0x69, 0xb3,
+    0x30, 0x08, 0xa0, 0x83, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+    0x89, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
+    0x5d, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
+};
+
+static const uint8_t n8x0_cal_bt_id[] = {
+    MAEMO_CAL_HEADER('b', 't', '-', 'i', 'd', 0, 0, 0)
+    0x0a, 0x00, 0x00, 0x00, 0xa3, 0x4b, 0xf6, 0x96,
+    0xa8, 0xeb, 0xb2, 0x41, 0x00, 0x00, 0x00, 0x00,
+    N8X0_BD_ADDR,
+};
+
+static void n8x0_nand_setup(struct n800_s *s)
+{
+    char *otp_region;
+    DriveInfo *dinfo;
+
+    s->nand = qdev_create(NULL, "onenand");
+    qdev_prop_set_uint16(s->nand, "manufacturer_id", NAND_MFR_SAMSUNG);
+    /* Either 0x40 or 0x48 are OK for the device ID */
+    qdev_prop_set_uint16(s->nand, "device_id", 0x48);
+    qdev_prop_set_uint16(s->nand, "version_id", 0);
+    qdev_prop_set_int32(s->nand, "shift", 1);
+    dinfo = drive_get(IF_MTD, 0, 0);
+    if (dinfo && dinfo->bdrv) {
+        qdev_prop_set_drive_nofail(s->nand, "drive", dinfo->bdrv);
+    }
+    qdev_init_nofail(s->nand);
+    sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
+                       qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO));
+    omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS,
+                     sysbus_mmio_get_region(SYS_BUS_DEVICE(s->nand), 0));
+    otp_region = onenand_raw_otp(s->nand);
+
+    memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
+    memcpy(otp_region + 0x800, n8x0_cal_bt_id, sizeof(n8x0_cal_bt_id));
+    /* XXX: in theory should also update the OOB for both pages */
+}
+
+static qemu_irq n8x0_system_powerdown;
+
+static void n8x0_powerdown_req(Notifier *n, void *opaque)
+{
+    qemu_irq_raise(n8x0_system_powerdown);
+}
+
+static Notifier n8x0_system_powerdown_notifier = {
+    .notify = n8x0_powerdown_req
+};
+
+static void n8x0_i2c_setup(struct n800_s *s)
+{
+    DeviceState *dev;
+    qemu_irq tmp_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TMP105_GPIO);
+    i2c_bus *i2c = omap_i2c_bus(s->mpu->i2c[0]);
+
+    /* Attach a menelaus PM chip */
+    dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR);
+    qdev_connect_gpio_out(dev, 3,
+                          qdev_get_gpio_in(s->mpu->ih[0],
+                                           OMAP_INT_24XX_SYS_NIRQ));
+
+    n8x0_system_powerdown = qdev_get_gpio_in(dev, 3);
+    qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier);
+
+    /* Attach a TMP105 PM chip (A0 wired to ground) */
+    dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
+    qdev_connect_gpio_out(dev, 0, tmp_irq);
+}
+
+/* Touchscreen and keypad controller */
+static MouseTransformInfo n800_pointercal = {
+    .x = 800,
+    .y = 480,
+    .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 },
+};
+
+static MouseTransformInfo n810_pointercal = {
+    .x = 800,
+    .y = 480,
+    .a = { 15041, 148, -4731056, 171, -10238, 35933380, 65536 },
+};
+
+#define RETU_KEYCODE   61      /* F3 */
+
+static void n800_key_event(void *opaque, int keycode)
+{
+    struct n800_s *s = (struct n800_s *) opaque;
+    int code = s->keymap[keycode & 0x7f];
+
+    if (code == -1) {
+        if ((keycode & 0x7f) == RETU_KEYCODE)
+            retu_key_event(s->retu, !(keycode & 0x80));
+        return;
+    }
+
+    tsc210x_key_event(s->ts.chip, code, !(keycode & 0x80));
+}
+
+static const int n800_keys[16] = {
+    -1,
+    72,        /* Up */
+    63,        /* Home (F5) */
+    -1,
+    75,        /* Left */
+    28,        /* Enter */
+    77,        /* Right */
+    -1,
+     1,        /* Cycle (ESC) */
+    80,        /* Down */
+    62,        /* Menu (F4) */
+    -1,
+    66,        /* Zoom- (F8) */
+    64,        /* FullScreen (F6) */
+    65,        /* Zoom+ (F7) */
+    -1,
+};
+
+static void n800_tsc_kbd_setup(struct n800_s *s)
+{
+    int i;
+
+    /* XXX: are the three pins inverted inside the chip between the
+     * tsc and the cpu (N4111)?  */
+    qemu_irq penirq = NULL;    /* NC */
+    qemu_irq kbirq = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_KP_IRQ_GPIO);
+    qemu_irq dav = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_TS_GPIO);
+
+    s->ts.chip = tsc2301_init(penirq, kbirq, dav);
+    s->ts.opaque = s->ts.chip->opaque;
+    s->ts.txrx = tsc210x_txrx;
+
+    for (i = 0; i < 0x80; i ++)
+        s->keymap[i] = -1;
+    for (i = 0; i < 0x10; i ++)
+        if (n800_keys[i] >= 0)
+            s->keymap[n800_keys[i]] = i;
+
+    qemu_add_kbd_event_handler(n800_key_event, s);
+
+    tsc210x_set_transform(s->ts.chip, &n800_pointercal);
+}
+
+static void n810_tsc_setup(struct n800_s *s)
+{
+    qemu_irq pintdav = qdev_get_gpio_in(s->mpu->gpio, N810_TSC_TS_GPIO);
+
+    s->ts.opaque = tsc2005_init(pintdav);
+    s->ts.txrx = tsc2005_txrx;
+
+    tsc2005_set_transform(s->ts.opaque, &n810_pointercal);
+}
+
+/* N810 Keyboard controller */
+static void n810_key_event(void *opaque, int keycode)
+{
+    struct n800_s *s = (struct n800_s *) opaque;
+    int code = s->keymap[keycode & 0x7f];
+
+    if (code == -1) {
+        if ((keycode & 0x7f) == RETU_KEYCODE)
+            retu_key_event(s->retu, !(keycode & 0x80));
+        return;
+    }
+
+    lm832x_key_event(s->kbd, code, !(keycode & 0x80));
+}
+
+#define M      0
+
+static int n810_keys[0x80] = {
+    [0x01] = 16,       /* Q */
+    [0x02] = 37,       /* K */
+    [0x03] = 24,       /* O */
+    [0x04] = 25,       /* P */
+    [0x05] = 14,       /* Backspace */
+    [0x06] = 30,       /* A */
+    [0x07] = 31,       /* S */
+    [0x08] = 32,       /* D */
+    [0x09] = 33,       /* F */
+    [0x0a] = 34,       /* G */
+    [0x0b] = 35,       /* H */
+    [0x0c] = 36,       /* J */
+
+    [0x11] = 17,       /* W */
+    [0x12] = 62,       /* Menu (F4) */
+    [0x13] = 38,       /* L */
+    [0x14] = 40,       /* ' (Apostrophe) */
+    [0x16] = 44,       /* Z */
+    [0x17] = 45,       /* X */
+    [0x18] = 46,       /* C */
+    [0x19] = 47,       /* V */
+    [0x1a] = 48,       /* B */
+    [0x1b] = 49,       /* N */
+    [0x1c] = 42,       /* Shift (Left shift) */
+    [0x1f] = 65,       /* Zoom+ (F7) */
+
+    [0x21] = 18,       /* E */
+    [0x22] = 39,       /* ; (Semicolon) */
+    [0x23] = 12,       /* - (Minus) */
+    [0x24] = 13,       /* = (Equal) */
+    [0x2b] = 56,       /* Fn (Left Alt) */
+    [0x2c] = 50,       /* M */
+    [0x2f] = 66,       /* Zoom- (F8) */
+
+    [0x31] = 19,       /* R */
+    [0x32] = 29 | M,   /* Right Ctrl */
+    [0x34] = 57,       /* Space */
+    [0x35] = 51,       /* , (Comma) */
+    [0x37] = 72 | M,   /* Up */
+    [0x3c] = 82 | M,   /* Compose (Insert) */
+    [0x3f] = 64,       /* FullScreen (F6) */
+
+    [0x41] = 20,       /* T */
+    [0x44] = 52,       /* . (Dot) */
+    [0x46] = 77 | M,   /* Right */
+    [0x4f] = 63,       /* Home (F5) */
+    [0x51] = 21,       /* Y */
+    [0x53] = 80 | M,   /* Down */
+    [0x55] = 28,       /* Enter */
+    [0x5f] =  1,       /* Cycle (ESC) */
+
+    [0x61] = 22,       /* U */
+    [0x64] = 75 | M,   /* Left */
+
+    [0x71] = 23,       /* I */
+#if 0
+    [0x75] = 28 | M,   /* KP Enter (KP Enter) */
+#else
+    [0x75] = 15,       /* KP Enter (Tab) */
+#endif
+};
+
+#undef M
+
+static void n810_kbd_setup(struct n800_s *s)
+{
+    qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
+    int i;
+
+    for (i = 0; i < 0x80; i ++)
+        s->keymap[i] = -1;
+    for (i = 0; i < 0x80; i ++)
+        if (n810_keys[i] > 0)
+            s->keymap[n810_keys[i]] = i;
+
+    qemu_add_kbd_event_handler(n810_key_event, s);
+
+    /* Attach the LM8322 keyboard to the I2C bus,
+     * should happen in n8x0_i2c_setup and s->kbd be initialised here.  */
+    s->kbd = i2c_create_slave(omap_i2c_bus(s->mpu->i2c[0]),
+                           "lm8323", N810_LM8323_ADDR);
+    qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
+}
+
+/* LCD MIPI DBI-C controller (URAL) */
+struct mipid_s {
+    int resp[4];
+    int param[4];
+    int p;
+    int pm;
+    int cmd;
+
+    int sleep;
+    int booster;
+    int te;
+    int selfcheck;
+    int partial;
+    int normal;
+    int vscr;
+    int invert;
+    int onoff;
+    int gamma;
+    uint32_t id;
+};
+
+static void mipid_reset(struct mipid_s *s)
+{
+    if (!s->sleep)
+        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
+
+    s->pm = 0;
+    s->cmd = 0;
+
+    s->sleep = 1;
+    s->booster = 0;
+    s->selfcheck =
+            (1 << 7) | /* Register loading OK.  */
+            (1 << 5) | /* The chip is attached.  */
+            (1 << 4);  /* Display glass still in one piece.  */
+    s->te = 0;
+    s->partial = 0;
+    s->normal = 1;
+    s->vscr = 0;
+    s->invert = 0;
+    s->onoff = 1;
+    s->gamma = 0;
+}
+
+static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
+{
+    struct mipid_s *s = (struct mipid_s *) opaque;
+    uint8_t ret;
+
+    if (len > 9)
+        hw_error("%s: FIXME: bad SPI word width %i\n", __FUNCTION__, len);
+
+    if (s->p >= ARRAY_SIZE(s->resp))
+        ret = 0;
+    else
+        ret = s->resp[s->p ++];
+    if (s->pm --> 0)
+        s->param[s->pm] = cmd;
+    else
+        s->cmd = cmd;
+
+    switch (s->cmd) {
+    case 0x00: /* NOP */
+        break;
+
+    case 0x01: /* SWRESET */
+        mipid_reset(s);
+        break;
+
+    case 0x02: /* BSTROFF */
+        s->booster = 0;
+        break;
+    case 0x03: /* BSTRON */
+        s->booster = 1;
+        break;
+
+    case 0x04: /* RDDID */
+        s->p = 0;
+        s->resp[0] = (s->id >> 16) & 0xff;
+        s->resp[1] = (s->id >>  8) & 0xff;
+        s->resp[2] = (s->id >>  0) & 0xff;
+        break;
+
+    case 0x06: /* RD_RED */
+    case 0x07: /* RD_GREEN */
+        /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so
+         * for the bootloader one needs to change this.  */
+    case 0x08: /* RD_BLUE */
+        s->p = 0;
+        /* TODO: return first pixel components */
+        s->resp[0] = 0x01;
+        break;
+
+    case 0x09: /* RDDST */
+        s->p = 0;
+        s->resp[0] = s->booster << 7;
+        s->resp[1] = (5 << 4) | (s->partial << 2) |
+                (s->sleep << 1) | s->normal;
+        s->resp[2] = (s->vscr << 7) | (s->invert << 5) |
+                (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2);
+        s->resp[3] = s->gamma << 6;
+        break;
+
+    case 0x0a: /* RDDPM */
+        s->p = 0;
+        s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) |
+                (s->partial << 5) | (s->sleep << 6) | (s->booster << 7);
+        break;
+    case 0x0b: /* RDDMADCTR */
+        s->p = 0;
+        s->resp[0] = 0;
+        break;
+    case 0x0c: /* RDDCOLMOD */
+        s->p = 0;
+        s->resp[0] = 5;        /* 65K colours */
+        break;
+    case 0x0d: /* RDDIM */
+        s->p = 0;
+        s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma;
+        break;
+    case 0x0e: /* RDDSM */
+        s->p = 0;
+        s->resp[0] = s->te << 7;
+        break;
+    case 0x0f: /* RDDSDR */
+        s->p = 0;
+        s->resp[0] = s->selfcheck;
+        break;
+
+    case 0x10: /* SLPIN */
+        s->sleep = 1;
+        break;
+    case 0x11: /* SLPOUT */
+        s->sleep = 0;
+        s->selfcheck ^= 1 << 6;        /* POFF self-diagnosis Ok */
+        break;
+
+    case 0x12: /* PTLON */
+        s->partial = 1;
+        s->normal = 0;
+        s->vscr = 0;
+        break;
+    case 0x13: /* NORON */
+        s->partial = 0;
+        s->normal = 1;
+        s->vscr = 0;
+        break;
+
+    case 0x20: /* INVOFF */
+        s->invert = 0;
+        break;
+    case 0x21: /* INVON */
+        s->invert = 1;
+        break;
+
+    case 0x22: /* APOFF */
+    case 0x23: /* APON */
+        goto bad_cmd;
+
+    case 0x25: /* WRCNTR */
+        if (s->pm < 0)
+            s->pm = 1;
+        goto bad_cmd;
+
+    case 0x26: /* GAMSET */
+        if (!s->pm)
+            s->gamma = ffs(s->param[0] & 0xf) - 1;
+        else if (s->pm < 0)
+            s->pm = 1;
+        break;
+
+    case 0x28: /* DISPOFF */
+        s->onoff = 0;
+        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
+        break;
+    case 0x29: /* DISPON */
+        s->onoff = 1;
+        fprintf(stderr, "%s: Display on\n", __FUNCTION__);
+        break;
+
+    case 0x2a: /* CASET */
+    case 0x2b: /* RASET */
+    case 0x2c: /* RAMWR */
+    case 0x2d: /* RGBSET */
+    case 0x2e: /* RAMRD */
+    case 0x30: /* PTLAR */
+    case 0x33: /* SCRLAR */
+        goto bad_cmd;
+
+    case 0x34: /* TEOFF */
+        s->te = 0;
+        break;
+    case 0x35: /* TEON */
+        if (!s->pm)
+            s->te = 1;
+        else if (s->pm < 0)
+            s->pm = 1;
+        break;
+
+    case 0x36: /* MADCTR */
+        goto bad_cmd;
+
+    case 0x37: /* VSCSAD */
+        s->partial = 0;
+        s->normal = 0;
+        s->vscr = 1;
+        break;
+
+    case 0x38: /* IDMOFF */
+    case 0x39: /* IDMON */
+    case 0x3a: /* COLMOD */
+        goto bad_cmd;
+
+    case 0xb0: /* CLKINT / DISCTL */
+    case 0xb1: /* CLKEXT */
+        if (s->pm < 0)
+            s->pm = 2;
+        break;
+
+    case 0xb4: /* FRMSEL */
+        break;
+
+    case 0xb5: /* FRM8SEL */
+    case 0xb6: /* TMPRNG / INIESC */
+    case 0xb7: /* TMPHIS / NOP2 */
+    case 0xb8: /* TMPREAD / MADCTL */
+    case 0xba: /* DISTCTR */
+    case 0xbb: /* EPVOL */
+        goto bad_cmd;
+
+    case 0xbd: /* Unknown */
+        s->p = 0;
+        s->resp[0] = 0;
+        s->resp[1] = 1;
+        break;
+
+    case 0xc2: /* IFMOD */
+        if (s->pm < 0)
+            s->pm = 2;
+        break;
+
+    case 0xc6: /* PWRCTL */
+    case 0xc7: /* PPWRCTL */
+    case 0xd0: /* EPWROUT */
+    case 0xd1: /* EPWRIN */
+    case 0xd4: /* RDEV */
+    case 0xd5: /* RDRR */
+        goto bad_cmd;
+
+    case 0xda: /* RDID1 */
+        s->p = 0;
+        s->resp[0] = (s->id >> 16) & 0xff;
+        break;
+    case 0xdb: /* RDID2 */
+        s->p = 0;
+        s->resp[0] = (s->id >>  8) & 0xff;
+        break;
+    case 0xdc: /* RDID3 */
+        s->p = 0;
+        s->resp[0] = (s->id >>  0) & 0xff;
+        break;
+
+    default:
+    bad_cmd:
+        fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd);
+        break;
+    }
+
+    return ret;
+}
+
+static void *mipid_init(void)
+{
+    struct mipid_s *s = (struct mipid_s *) g_malloc0(sizeof(*s));
+
+    s->id = 0x838f03;
+    mipid_reset(s);
+
+    return s;
+}
+
+static void n8x0_spi_setup(struct n800_s *s)
+{
+    void *tsc = s->ts.opaque;
+    void *mipid = mipid_init();
+
+    omap_mcspi_attach(s->mpu->mcspi[0], s->ts.txrx, tsc, 0);
+    omap_mcspi_attach(s->mpu->mcspi[0], mipid_txrx, mipid, 1);
+}
+
+/* This task is normally performed by the bootloader.  If we're loading
+ * a kernel directly, we need to enable the Blizzard ourselves.  */
+static void n800_dss_init(struct rfbi_chip_s *chip)
+{
+    uint8_t *fb_blank;
+
+    chip->write(chip->opaque, 0, 0x2a);                /* LCD Width register */
+    chip->write(chip->opaque, 1, 0x64);
+    chip->write(chip->opaque, 0, 0x2c);                /* LCD HNDP register */
+    chip->write(chip->opaque, 1, 0x1e);
+    chip->write(chip->opaque, 0, 0x2e);                /* LCD Height 0 register */
+    chip->write(chip->opaque, 1, 0xe0);
+    chip->write(chip->opaque, 0, 0x30);                /* LCD Height 1 register */
+    chip->write(chip->opaque, 1, 0x01);
+    chip->write(chip->opaque, 0, 0x32);                /* LCD VNDP register */
+    chip->write(chip->opaque, 1, 0x06);
+    chip->write(chip->opaque, 0, 0x68);                /* Display Mode register */
+    chip->write(chip->opaque, 1, 1);           /* Enable bit */
+
+    chip->write(chip->opaque, 0, 0x6c);        
+    chip->write(chip->opaque, 1, 0x00);                /* Input X Start Position */
+    chip->write(chip->opaque, 1, 0x00);                /* Input X Start Position */
+    chip->write(chip->opaque, 1, 0x00);                /* Input Y Start Position */
+    chip->write(chip->opaque, 1, 0x00);                /* Input Y Start Position */
+    chip->write(chip->opaque, 1, 0x1f);                /* Input X End Position */
+    chip->write(chip->opaque, 1, 0x03);                /* Input X End Position */
+    chip->write(chip->opaque, 1, 0xdf);                /* Input Y End Position */
+    chip->write(chip->opaque, 1, 0x01);                /* Input Y End Position */
+    chip->write(chip->opaque, 1, 0x00);                /* Output X Start Position */
+    chip->write(chip->opaque, 1, 0x00);                /* Output X Start Position */
+    chip->write(chip->opaque, 1, 0x00);                /* Output Y Start Position */
+    chip->write(chip->opaque, 1, 0x00);                /* Output Y Start Position */
+    chip->write(chip->opaque, 1, 0x1f);                /* Output X End Position */
+    chip->write(chip->opaque, 1, 0x03);                /* Output X End Position */
+    chip->write(chip->opaque, 1, 0xdf);                /* Output Y End Position */
+    chip->write(chip->opaque, 1, 0x01);                /* Output Y End Position */
+    chip->write(chip->opaque, 1, 0x01);                /* Input Data Format */
+    chip->write(chip->opaque, 1, 0x01);                /* Data Source Select */
+
+    fb_blank = memset(g_malloc(800 * 480 * 2), 0xff, 800 * 480 * 2);
+    /* Display Memory Data Port */
+    chip->block(chip->opaque, 1, fb_blank, 800 * 480 * 2, 800);
+    g_free(fb_blank);
+}
+
+static void n8x0_dss_setup(struct n800_s *s)
+{
+    s->blizzard.opaque = s1d13745_init(NULL);
+    s->blizzard.block = s1d13745_write_block;
+    s->blizzard.write = s1d13745_write;
+    s->blizzard.read = s1d13745_read;
+
+    omap_rfbi_attach(s->mpu->dss, 0, &s->blizzard);
+}
+
+static void n8x0_cbus_setup(struct n800_s *s)
+{
+    qemu_irq dat_out = qdev_get_gpio_in(s->mpu->gpio, N8X0_CBUS_DAT_GPIO);
+    qemu_irq retu_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_RETU_GPIO);
+    qemu_irq tahvo_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TAHVO_GPIO);
+
+    CBus *cbus = cbus_init(dat_out);
+
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
+
+    cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
+    cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
+}
+
+static void n8x0_uart_setup(struct n800_s *s)
+{
+    CharDriverState *radio = uart_hci_init(
+                    qdev_get_gpio_in(s->mpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
+
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO,
+                    csrhci_pins_get(radio)[csrhci_pin_reset]);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_WKUP_GPIO,
+                    csrhci_pins_get(radio)[csrhci_pin_wakeup]);
+
+    omap_uart_attach(s->mpu->uart[BT_UART], radio);
+}
+
+static void n8x0_usb_setup(struct n800_s *s)
+{
+    SysBusDevice *dev;
+    s->usb = qdev_create(NULL, "tusb6010");
+    dev = SYS_BUS_DEVICE(s->usb);
+    qdev_init_nofail(s->usb);
+    sysbus_connect_irq(dev, 0,
+                       qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO));
+    /* Using the NOR interface */
+    omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_ASYNC_CS,
+                     sysbus_mmio_get_region(dev, 0));
+    omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_SYNC_CS,
+                     sysbus_mmio_get_region(dev, 1));
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_TUSB_ENABLE_GPIO,
+                          qdev_get_gpio_in(s->usb, 0)); /* tusb_pwr */
+}
+
+/* Setup done before the main bootloader starts by some early setup code
+ * - used when we want to run the main bootloader in emulation.  This
+ * isn't documented.  */
+static uint32_t n800_pinout[104] = {
+    0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0,
+    0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808,
+    0x08080808, 0x180800c4, 0x00b80000, 0x08080808,
+    0x080800bc, 0x00cc0808, 0x08081818, 0x18180128,
+    0x01241800, 0x18181818, 0x000000f0, 0x01300000,
+    0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b,
+    0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080,
+    0x007c0000, 0x00000000, 0x00000088, 0x00840000,
+    0x00000000, 0x00000094, 0x00980300, 0x0f180003,
+    0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c,
+    0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008,
+    0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f,
+    0x181800f4, 0x00f81818, 0x00000018, 0x000000fc,
+    0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008,
+    0x00000000, 0x00000038, 0x00340000, 0x00000000,
+    0x1a080070, 0x00641a1a, 0x08080808, 0x08080060,
+    0x005c0808, 0x08080808, 0x08080058, 0x00540808,
+    0x08080808, 0x0808006c, 0x00680808, 0x08080808,
+    0x000000a8, 0x00b00000, 0x08080808, 0x000000a0,
+    0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808,
+    0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff,
+    0x000000ac, 0x01040800, 0x08080b0f, 0x18180100,
+    0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a,
+    0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00,
+    0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118,
+    0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b,
+};
+
+static void n800_setup_nolo_tags(void *sram_base)
+{
+    int i;
+    uint32_t *p = sram_base + 0x8000;
+    uint32_t *v = sram_base + 0xa000;
+
+    memset(p, 0, 0x3000);
+
+    strcpy((void *) (p + 0), "QEMU N800");
+
+    strcpy((void *) (p + 8), "F5");
+
+    stl_raw(p + 10, 0x04f70000);
+    strcpy((void *) (p + 9), "RX-34");
+
+    /* RAM size in MB? */
+    stl_raw(p + 12, 0x80);
+
+    /* Pointer to the list of tags */
+    stl_raw(p + 13, OMAP2_SRAM_BASE + 0x9000);
+
+    /* The NOLO tags start here */
+    p = sram_base + 0x9000;
+#define ADD_TAG(tag, len)                              \
+    stw_raw((uint16_t *) p + 0, tag);                  \
+    stw_raw((uint16_t *) p + 1, len); p ++;            \
+    stl_raw(p ++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
+
+    /* OMAP STI console? Pin out settings? */
+    ADD_TAG(0x6e01, 414);
+    for (i = 0; i < ARRAY_SIZE(n800_pinout); i ++)
+        stl_raw(v ++, n800_pinout[i]);
+
+    /* Kernel memsize? */
+    ADD_TAG(0x6e05, 1);
+    stl_raw(v ++, 2);
+
+    /* NOLO serial console */
+    ADD_TAG(0x6e02, 4);
+    stl_raw(v ++, XLDR_LL_UART);       /* UART number (1 - 3) */
+
+#if 0
+    /* CBUS settings (Retu/AVilma) */
+    ADD_TAG(0x6e03, 6);
+    stw_raw((uint16_t *) v + 0, 65);   /* CBUS GPIO0 */
+    stw_raw((uint16_t *) v + 1, 66);   /* CBUS GPIO1 */
+    stw_raw((uint16_t *) v + 2, 64);   /* CBUS GPIO2 */
+    v += 2;
+#endif
+
+    /* Nokia ASIC BB5 (Retu/Tahvo) */
+    ADD_TAG(0x6e0a, 4);
+    stw_raw((uint16_t *) v + 0, 111);  /* "Retu" interrupt GPIO */
+    stw_raw((uint16_t *) v + 1, 108);  /* "Tahvo" interrupt GPIO */
+    v ++;
+
+    /* LCD console? */
+    ADD_TAG(0x6e04, 4);
+    stw_raw((uint16_t *) v + 0, 30);   /* ??? */
+    stw_raw((uint16_t *) v + 1, 24);   /* ??? */
+    v ++;
+
+#if 0
+    /* LCD settings */
+    ADD_TAG(0x6e06, 2);
+    stw_raw((uint16_t *) (v ++), 15);  /* ??? */
+#endif
+
+    /* I^2C (Menelaus) */
+    ADD_TAG(0x6e07, 4);
+    stl_raw(v ++, 0x00720000);         /* ??? */
+
+    /* Unknown */
+    ADD_TAG(0x6e0b, 6);
+    stw_raw((uint16_t *) v + 0, 94);   /* ??? */
+    stw_raw((uint16_t *) v + 1, 23);   /* ??? */
+    stw_raw((uint16_t *) v + 2, 0);    /* ??? */
+    v += 2;
+
+    /* OMAP gpio switch info */
+    ADD_TAG(0x6e0c, 80);
+    strcpy((void *) v, "bat_cover");   v += 3;
+    stw_raw((uint16_t *) v + 0, 110);  /* GPIO num ??? */
+    stw_raw((uint16_t *) v + 1, 1);    /* GPIO num ??? */
+    v += 2;
+    strcpy((void *) v, "cam_act");     v += 3;
+    stw_raw((uint16_t *) v + 0, 95);   /* GPIO num ??? */
+    stw_raw((uint16_t *) v + 1, 32);   /* GPIO num ??? */
+    v += 2;
+    strcpy((void *) v, "cam_turn");    v += 3;
+    stw_raw((uint16_t *) v + 0, 12);   /* GPIO num ??? */
+    stw_raw((uint16_t *) v + 1, 33);   /* GPIO num ??? */
+    v += 2;
+    strcpy((void *) v, "headphone");   v += 3;
+    stw_raw((uint16_t *) v + 0, 107);  /* GPIO num ??? */
+    stw_raw((uint16_t *) v + 1, 17);   /* GPIO num ??? */
+    v += 2;
+
+    /* Bluetooth */
+    ADD_TAG(0x6e0e, 12);
+    stl_raw(v ++, 0x5c623d01);         /* ??? */
+    stl_raw(v ++, 0x00000201);         /* ??? */
+    stl_raw(v ++, 0x00000000);         /* ??? */
+
+    /* CX3110x WLAN settings */
+    ADD_TAG(0x6e0f, 8);
+    stl_raw(v ++, 0x00610025);         /* ??? */
+    stl_raw(v ++, 0xffff0057);         /* ??? */
+
+    /* MMC host settings */
+    ADD_TAG(0x6e10, 12);
+    stl_raw(v ++, 0xffff000f);         /* ??? */
+    stl_raw(v ++, 0xffffffff);         /* ??? */
+    stl_raw(v ++, 0x00000060);         /* ??? */
+
+    /* OneNAND chip select */
+    ADD_TAG(0x6e11, 10);
+    stl_raw(v ++, 0x00000401);         /* ??? */
+    stl_raw(v ++, 0x0002003a);         /* ??? */
+    stl_raw(v ++, 0x00000002);         /* ??? */
+
+    /* TEA5761 sensor settings */
+    ADD_TAG(0x6e12, 2);
+    stl_raw(v ++, 93);                 /* GPIO num ??? */
+
+#if 0
+    /* Unknown tag */
+    ADD_TAG(6e09, 0);
+
+    /* Kernel UART / console */
+    ADD_TAG(6e12, 0);
+#endif
+
+    /* End of the list */
+    stl_raw(p ++, 0x00000000);
+    stl_raw(p ++, 0x00000000);
+}
+
+/* This task is normally performed by the bootloader.  If we're loading
+ * a kernel directly, we need to set up GPMC mappings ourselves.  */
+static void n800_gpmc_init(struct n800_s *s)
+{
+    uint32_t config7 =
+            (0xf << 8) |       /* MASKADDRESS */
+            (1 << 6) |         /* CSVALID */
+            (4 << 0);          /* BASEADDRESS */
+
+    cpu_physical_memory_write(0x6800a078,              /* GPMC_CONFIG7_0 */
+                    (void *) &config7, sizeof(config7));
+}
+
+/* Setup sequence done by the bootloader */
+static void n8x0_boot_init(void *opaque)
+{
+    struct n800_s *s = (struct n800_s *) opaque;
+    uint32_t buf;
+
+    /* PRCM setup */
+#define omap_writel(addr, val) \
+    buf = (val);                       \
+    cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf))
+
+    omap_writel(0x48008060, 0x41);             /* PRCM_CLKSRC_CTRL */
+    omap_writel(0x48008070, 1);                        /* PRCM_CLKOUT_CTRL */
+    omap_writel(0x48008078, 0);                        /* PRCM_CLKEMUL_CTRL */
+    omap_writel(0x48008090, 0);                        /* PRCM_VOLTSETUP */
+    omap_writel(0x48008094, 0);                        /* PRCM_CLKSSETUP */
+    omap_writel(0x48008098, 0);                        /* PRCM_POLCTRL */
+    omap_writel(0x48008140, 2);                        /* CM_CLKSEL_MPU */
+    omap_writel(0x48008148, 0);                        /* CM_CLKSTCTRL_MPU */
+    omap_writel(0x48008158, 1);                        /* RM_RSTST_MPU */
+    omap_writel(0x480081c8, 0x15);             /* PM_WKDEP_MPU */
+    omap_writel(0x480081d4, 0x1d4);            /* PM_EVGENCTRL_MPU */
+    omap_writel(0x480081d8, 0);                        /* PM_EVEGENONTIM_MPU */
+    omap_writel(0x480081dc, 0);                        /* PM_EVEGENOFFTIM_MPU */
+    omap_writel(0x480081e0, 0xc);              /* PM_PWSTCTRL_MPU */
+    omap_writel(0x48008200, 0x047e7ff7);       /* CM_FCLKEN1_CORE */
+    omap_writel(0x48008204, 0x00000004);       /* CM_FCLKEN2_CORE */
+    omap_writel(0x48008210, 0x047e7ff1);       /* CM_ICLKEN1_CORE */
+    omap_writel(0x48008214, 0x00000004);       /* CM_ICLKEN2_CORE */
+    omap_writel(0x4800821c, 0x00000000);       /* CM_ICLKEN4_CORE */
+    omap_writel(0x48008230, 0);                        /* CM_AUTOIDLE1_CORE */
+    omap_writel(0x48008234, 0);                        /* CM_AUTOIDLE2_CORE */
+    omap_writel(0x48008238, 7);                        /* CM_AUTOIDLE3_CORE */
+    omap_writel(0x4800823c, 0);                        /* CM_AUTOIDLE4_CORE */
+    omap_writel(0x48008240, 0x04360626);       /* CM_CLKSEL1_CORE */
+    omap_writel(0x48008244, 0x00000014);       /* CM_CLKSEL2_CORE */
+    omap_writel(0x48008248, 0);                        /* CM_CLKSTCTRL_CORE */
+    omap_writel(0x48008300, 0x00000000);       /* CM_FCLKEN_GFX */
+    omap_writel(0x48008310, 0x00000000);       /* CM_ICLKEN_GFX */
+    omap_writel(0x48008340, 0x00000001);       /* CM_CLKSEL_GFX */
+    omap_writel(0x48008400, 0x00000004);       /* CM_FCLKEN_WKUP */
+    omap_writel(0x48008410, 0x00000004);       /* CM_ICLKEN_WKUP */
+    omap_writel(0x48008440, 0x00000000);       /* CM_CLKSEL_WKUP */
+    omap_writel(0x48008500, 0x000000cf);       /* CM_CLKEN_PLL */
+    omap_writel(0x48008530, 0x0000000c);       /* CM_AUTOIDLE_PLL */
+    omap_writel(0x48008540,                    /* CM_CLKSEL1_PLL */
+                    (0x78 << 12) | (6 << 8));
+    omap_writel(0x48008544, 2);                        /* CM_CLKSEL2_PLL */
+
+    /* GPMC setup */
+    n800_gpmc_init(s);
+
+    /* Video setup */
+    n800_dss_init(&s->blizzard);
+
+    /* CPU setup */
+    s->mpu->cpu->env.GE = 0x5;
+
+    /* If the machine has a slided keyboard, open it */
+    if (s->kbd)
+        qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
+}
+
+#define OMAP_TAG_NOKIA_BT      0x4e01
+#define OMAP_TAG_WLAN_CX3110X  0x4e02
+#define OMAP_TAG_CBUS          0x4e03
+#define OMAP_TAG_EM_ASIC_BB5   0x4e04
+
+static struct omap_gpiosw_info_s {
+    const char *name;
+    int line;
+    int type;
+} n800_gpiosw_info[] = {
+    {
+        "bat_cover", N800_BAT_COVER_GPIO,
+        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
+    }, {
+        "cam_act", N800_CAM_ACT_GPIO,
+        OMAP_GPIOSW_TYPE_ACTIVITY,
+    }, {
+        "cam_turn", N800_CAM_TURN_GPIO,
+        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED,
+    }, {
+        "headphone", N8X0_HEADPHONE_GPIO,
+        OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
+    },
+    { NULL }
+}, n810_gpiosw_info[] = {
+    {
+        "gps_reset", N810_GPS_RESET_GPIO,
+        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
+    }, {
+        "gps_wakeup", N810_GPS_WAKEUP_GPIO,
+        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
+    }, {
+        "headphone", N8X0_HEADPHONE_GPIO,
+        OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
+    }, {
+        "kb_lock", N810_KB_LOCK_GPIO,
+        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
+    }, {
+        "sleepx_led", N810_SLEEPX_LED_GPIO,
+        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED | OMAP_GPIOSW_OUTPUT,
+    }, {
+        "slide", N810_SLIDE_GPIO,
+        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
+    },
+    { NULL }
+};
+
+static struct omap_partition_info_s {
+    uint32_t offset;
+    uint32_t size;
+    int mask;
+    const char *name;
+} n800_part_info[] = {
+    { 0x00000000, 0x00020000, 0x3, "bootloader" },
+    { 0x00020000, 0x00060000, 0x0, "config" },
+    { 0x00080000, 0x00200000, 0x0, "kernel" },
+    { 0x00280000, 0x00200000, 0x3, "initfs" },
+    { 0x00480000, 0x0fb80000, 0x3, "rootfs" },
+
+    { 0, 0, 0, NULL }
+}, n810_part_info[] = {
+    { 0x00000000, 0x00020000, 0x3, "bootloader" },
+    { 0x00020000, 0x00060000, 0x0, "config" },
+    { 0x00080000, 0x00220000, 0x0, "kernel" },
+    { 0x002a0000, 0x00400000, 0x0, "initfs" },
+    { 0x006a0000, 0x0f960000, 0x0, "rootfs" },
+
+    { 0, 0, 0, NULL }
+};
+
+static bdaddr_t n8x0_bd_addr = {{ N8X0_BD_ADDR }};
+
+static int n8x0_atag_setup(void *p, int model)
+{
+    uint8_t *b;
+    uint16_t *w;
+    uint32_t *l;
+    struct omap_gpiosw_info_s *gpiosw;
+    struct omap_partition_info_s *partition;
+    const char *tag;
+
+    w = p;
+
+    stw_raw(w ++, OMAP_TAG_UART);              /* u16 tag */
+    stw_raw(w ++, 4);                          /* u16 len */
+    stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
+    w ++;
+
+#if 0
+    stw_raw(w ++, OMAP_TAG_SERIAL_CONSOLE);    /* u16 tag */
+    stw_raw(w ++, 4);                          /* u16 len */
+    stw_raw(w ++, XLDR_LL_UART + 1);           /* u8 console_uart */
+    stw_raw(w ++, 115200);                     /* u32 console_speed */
+#endif
+
+    stw_raw(w ++, OMAP_TAG_LCD);               /* u16 tag */
+    stw_raw(w ++, 36);                         /* u16 len */
+    strcpy((void *) w, "QEMU LCD panel");      /* char panel_name[16] */
+    w += 8;
+    strcpy((void *) w, "blizzard");            /* char ctrl_name[16] */
+    w += 8;
+    stw_raw(w ++, N810_BLIZZARD_RESET_GPIO);   /* TODO: n800 s16 nreset_gpio */
+    stw_raw(w ++, 24);                         /* u8 data_lines */
+
+    stw_raw(w ++, OMAP_TAG_CBUS);              /* u16 tag */
+    stw_raw(w ++, 8);                          /* u16 len */
+    stw_raw(w ++, N8X0_CBUS_CLK_GPIO);         /* s16 clk_gpio */
+    stw_raw(w ++, N8X0_CBUS_DAT_GPIO);         /* s16 dat_gpio */
+    stw_raw(w ++, N8X0_CBUS_SEL_GPIO);         /* s16 sel_gpio */
+    w ++;
+
+    stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5);       /* u16 tag */
+    stw_raw(w ++, 4);                          /* u16 len */
+    stw_raw(w ++, N8X0_RETU_GPIO);             /* s16 retu_irq_gpio */
+    stw_raw(w ++, N8X0_TAHVO_GPIO);            /* s16 tahvo_irq_gpio */
+
+    gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
+    for (; gpiosw->name; gpiosw ++) {
+        stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);   /* u16 tag */
+        stw_raw(w ++, 20);                     /* u16 len */
+        strcpy((void *) w, gpiosw->name);      /* char name[12] */
+        w += 6;
+        stw_raw(w ++, gpiosw->line);           /* u16 gpio */
+        stw_raw(w ++, gpiosw->type);
+        stw_raw(w ++, 0);
+        stw_raw(w ++, 0);
+    }
+
+    stw_raw(w ++, OMAP_TAG_NOKIA_BT);          /* u16 tag */
+    stw_raw(w ++, 12);                         /* u16 len */
+    b = (void *) w;
+    stb_raw(b ++, 0x01);                       /* u8 chip_type (CSR) */
+    stb_raw(b ++, N8X0_BT_WKUP_GPIO);          /* u8 bt_wakeup_gpio */
+    stb_raw(b ++, N8X0_BT_HOST_WKUP_GPIO);     /* u8 host_wakeup_gpio */
+    stb_raw(b ++, N8X0_BT_RESET_GPIO);         /* u8 reset_gpio */
+    stb_raw(b ++, BT_UART + 1);                        /* u8 bt_uart */
+    memcpy(b, &n8x0_bd_addr, 6);               /* u8 bd_addr[6] */
+    b += 6;
+    stb_raw(b ++, 0x02);                       /* u8 bt_sysclk (38.4) */
+    w = (void *) b;
+
+    stw_raw(w ++, OMAP_TAG_WLAN_CX3110X);      /* u16 tag */
+    stw_raw(w ++, 8);                          /* u16 len */
+    stw_raw(w ++, 0x25);                       /* u8 chip_type */
+    stw_raw(w ++, N8X0_WLAN_PWR_GPIO);         /* s16 power_gpio */
+    stw_raw(w ++, N8X0_WLAN_IRQ_GPIO);         /* s16 irq_gpio */
+    stw_raw(w ++, -1);                         /* s16 spi_cs_gpio */
+
+    stw_raw(w ++, OMAP_TAG_MMC);               /* u16 tag */
+    stw_raw(w ++, 16);                         /* u16 len */
+    if (model == 810) {
+        stw_raw(w ++, 0x23f);                  /* unsigned flags */
+        stw_raw(w ++, -1);                     /* s16 power_pin */
+        stw_raw(w ++, -1);                     /* s16 switch_pin */
+        stw_raw(w ++, -1);                     /* s16 wp_pin */
+        stw_raw(w ++, 0x240);                  /* unsigned flags */
+        stw_raw(w ++, 0xc000);                 /* s16 power_pin */
+        stw_raw(w ++, 0x0248);                 /* s16 switch_pin */
+        stw_raw(w ++, 0xc000);                 /* s16 wp_pin */
+    } else {
+        stw_raw(w ++, 0xf);                    /* unsigned flags */
+        stw_raw(w ++, -1);                     /* s16 power_pin */
+        stw_raw(w ++, -1);                     /* s16 switch_pin */
+        stw_raw(w ++, -1);                     /* s16 wp_pin */
+        stw_raw(w ++, 0);                      /* unsigned flags */
+        stw_raw(w ++, 0);                      /* s16 power_pin */
+        stw_raw(w ++, 0);                      /* s16 switch_pin */
+        stw_raw(w ++, 0);                      /* s16 wp_pin */
+    }
+
+    stw_raw(w ++, OMAP_TAG_TEA5761);           /* u16 tag */
+    stw_raw(w ++, 4);                          /* u16 len */
+    stw_raw(w ++, N8X0_TEA5761_CS_GPIO);       /* u16 enable_gpio */
+    w ++;
+
+    partition = (model == 810) ? n810_part_info : n800_part_info;
+    for (; partition->name; partition ++) {
+        stw_raw(w ++, OMAP_TAG_PARTITION);     /* u16 tag */
+        stw_raw(w ++, 28);                     /* u16 len */
+        strcpy((void *) w, partition->name);   /* char name[16] */
+        l = (void *) (w + 8);
+        stl_raw(l ++, partition->size);                /* unsigned int size */
+        stl_raw(l ++, partition->offset);      /* unsigned int offset */
+        stl_raw(l ++, partition->mask);                /* unsigned int mask_flags */
+        w = (void *) l;
+    }
+
+    stw_raw(w ++, OMAP_TAG_BOOT_REASON);       /* u16 tag */
+    stw_raw(w ++, 12);                         /* u16 len */
+#if 0
+    strcpy((void *) w, "por");                 /* char reason_str[12] */
+    strcpy((void *) w, "charger");             /* char reason_str[12] */
+    strcpy((void *) w, "32wd_to");             /* char reason_str[12] */
+    strcpy((void *) w, "sw_rst");              /* char reason_str[12] */
+    strcpy((void *) w, "mbus");                        /* char reason_str[12] */
+    strcpy((void *) w, "unknown");             /* char reason_str[12] */
+    strcpy((void *) w, "swdg_to");             /* char reason_str[12] */
+    strcpy((void *) w, "sec_vio");             /* char reason_str[12] */
+    strcpy((void *) w, "pwr_key");             /* char reason_str[12] */
+    strcpy((void *) w, "rtc_alarm");           /* char reason_str[12] */
+#else
+    strcpy((void *) w, "pwr_key");             /* char reason_str[12] */
+#endif
+    w += 6;
+
+    tag = (model == 810) ? "RX-44" : "RX-34";
+    stw_raw(w ++, OMAP_TAG_VERSION_STR);       /* u16 tag */
+    stw_raw(w ++, 24);                         /* u16 len */
+    strcpy((void *) w, "product");             /* char component[12] */
+    w += 6;
+    strcpy((void *) w, tag);                   /* char version[12] */
+    w += 6;
+
+    stw_raw(w ++, OMAP_TAG_VERSION_STR);       /* u16 tag */
+    stw_raw(w ++, 24);                         /* u16 len */
+    strcpy((void *) w, "hw-build");            /* char component[12] */
+    w += 6;
+    strcpy((void *) w, "QEMU ");
+    pstrcat((void *) w, 12, qemu_get_version()); /* char version[12] */
+    w += 6;
+
+    tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
+    stw_raw(w ++, OMAP_TAG_VERSION_STR);       /* u16 tag */
+    stw_raw(w ++, 24);                         /* u16 len */
+    strcpy((void *) w, "nolo");                        /* char component[12] */
+    w += 6;
+    strcpy((void *) w, tag);                   /* char version[12] */
+    w += 6;
+
+    return (void *) w - p;
+}
+
+static int n800_atag_setup(const struct arm_boot_info *info, void *p)
+{
+    return n8x0_atag_setup(p, 800);
+}
+
+static int n810_atag_setup(const struct arm_boot_info *info, void *p)
+{
+    return n8x0_atag_setup(p, 810);
+}
+
+static void n8x0_init(QEMUMachineInitArgs *args,
+                      struct arm_boot_info *binfo, int model)
+{
+    MemoryRegion *sysmem = get_system_memory();
+    struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
+    int sdram_size = binfo->ram_size;
+    DisplayState *ds;
+
+    s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model);
+
+    /* Setup peripherals
+     *
+     * Believed external peripherals layout in the N810:
+     * (spi bus 1)
+     *   tsc2005
+     *   lcd_mipid
+     * (spi bus 2)
+     *   Conexant cx3110x (WLAN)
+     *   optional: pc2400m (WiMAX)
+     * (i2c bus 0)
+     *   TLV320AIC33 (audio codec)
+     *   TCM825x (camera by Toshiba)
+     *   lp5521 (clever LEDs)
+     *   tsl2563 (light sensor, hwmon, model 7, rev. 0)
+     *   lm8323 (keypad, manf 00, rev 04)
+     * (i2c bus 1)
+     *   tmp105 (temperature sensor, hwmon)
+     *   menelaus (pm)
+     * (somewhere on i2c - maybe N800-only)
+     *   tea5761 (FM tuner)
+     * (serial 0)
+     *   GPS
+     * (some serial port)
+     *   csr41814 (Bluetooth)
+     */
+    n8x0_gpio_setup(s);
+    n8x0_nand_setup(s);
+    n8x0_i2c_setup(s);
+    if (model == 800)
+        n800_tsc_kbd_setup(s);
+    else if (model == 810) {
+        n810_tsc_setup(s);
+        n810_kbd_setup(s);
+    }
+    n8x0_spi_setup(s);
+    n8x0_dss_setup(s);
+    n8x0_cbus_setup(s);
+    n8x0_uart_setup(s);
+    if (usb_enabled(false)) {
+        n8x0_usb_setup(s);
+    }
+
+    if (args->kernel_filename) {
+        /* Or at the linux loader.  */
+        binfo->kernel_filename = args->kernel_filename;
+        binfo->kernel_cmdline = args->kernel_cmdline;
+        binfo->initrd_filename = args->initrd_filename;
+        arm_load_kernel(s->mpu->cpu, binfo);
+
+        qemu_register_reset(n8x0_boot_init, s);
+    }
+
+    if (option_rom[0].name &&
+        (args->boot_device[0] == 'n' || !args->kernel_filename)) {
+        int rom_size;
+        uint8_t nolo_tags[0x10000];
+        /* No, wait, better start at the ROM.  */
+        s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
+
+        /* This is intended for loading the `secondary.bin' program from
+         * Nokia images (the NOLO bootloader).  The entry point seems
+         * to be at OMAP2_Q2_BASE + 0x400000.
+         *
+         * The `2nd.bin' files contain some kind of earlier boot code and
+         * for them the entry point needs to be set to OMAP2_SRAM_BASE.
+         *
+         * The code above is for loading the `zImage' file from Nokia
+         * images.  */
+        rom_size = load_image_targphys(option_rom[0].name,
+                                       OMAP2_Q2_BASE + 0x400000,
+                                       sdram_size - 0x400000);
+        printf("%i bytes of image loaded\n", rom_size);
+
+        n800_setup_nolo_tags(nolo_tags);
+        cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
+    }
+    /* FIXME: We shouldn't really be doing this here.  The LCD controller
+       will set the size once configured, so this just sets an initial
+       size until the guest activates the display.  */
+    ds = get_displaystate();
+    ds->surface = qemu_resize_displaysurface(ds, 800, 480);
+    dpy_gfx_resize(ds);
+}
+
+static struct arm_boot_info n800_binfo = {
+    .loader_start = OMAP2_Q2_BASE,
+    /* Actually two chips of 0x4000000 bytes each */
+    .ram_size = 0x08000000,
+    .board_id = 0x4f7,
+    .atag_board = n800_atag_setup,
+};
+
+static struct arm_boot_info n810_binfo = {
+    .loader_start = OMAP2_Q2_BASE,
+    /* Actually two chips of 0x4000000 bytes each */
+    .ram_size = 0x08000000,
+    /* 0x60c and 0x6bf (WiMAX Edition) have been assigned but are not
+     * used by some older versions of the bootloader and 5555 is used
+     * instead (including versions that shipped with many devices).  */
+    .board_id = 0x60c,
+    .atag_board = n810_atag_setup,
+};
+
+static void n800_init(QEMUMachineInitArgs *args)
+{
+    return n8x0_init(args, &n800_binfo, 800);
+}
+
+static void n810_init(QEMUMachineInitArgs *args)
+{
+    return n8x0_init(args, &n810_binfo, 810);
+}
+
+static QEMUMachine n800_machine = {
+    .name = "n800",
+    .desc = "Nokia N800 tablet aka. RX-34 (OMAP2420)",
+    .init = n800_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine n810_machine = {
+    .name = "n810",
+    .desc = "Nokia N810 tablet aka. RX-44 (OMAP2420)",
+    .init = n810_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void nseries_machine_init(void)
+{
+    qemu_register_machine(&n800_machine);
+    qemu_register_machine(&n810_machine);
+}
+
+machine_init(nseries_machine_init);
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
new file mode 100644 (file)
index 0000000..6f0a8ca
--- /dev/null
@@ -0,0 +1,4056 @@
+/*
+ * TI OMAP processors emulation.
+ *
+ * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * 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 "hw/hw.h"
+#include "hw/arm-misc.h"
+#include "hw/omap.h"
+#include "sysemu/sysemu.h"
+#include "hw/soc_dma.h"
+#include "sysemu/blockdev.h"
+#include "qemu/range.h"
+#include "hw/sysbus.h"
+
+/* Should signal the TCMI/GPMC */
+uint32_t omap_badwidth_read8(void *opaque, hwaddr addr)
+{
+    uint8_t ret;
+
+    OMAP_8B_REG(addr);
+    cpu_physical_memory_read(addr, (void *) &ret, 1);
+    return ret;
+}
+
+void omap_badwidth_write8(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    uint8_t val8 = value;
+
+    OMAP_8B_REG(addr);
+    cpu_physical_memory_write(addr, (void *) &val8, 1);
+}
+
+uint32_t omap_badwidth_read16(void *opaque, hwaddr addr)
+{
+    uint16_t ret;
+
+    OMAP_16B_REG(addr);
+    cpu_physical_memory_read(addr, (void *) &ret, 2);
+    return ret;
+}
+
+void omap_badwidth_write16(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    uint16_t val16 = value;
+
+    OMAP_16B_REG(addr);
+    cpu_physical_memory_write(addr, (void *) &val16, 2);
+}
+
+uint32_t omap_badwidth_read32(void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+    OMAP_32B_REG(addr);
+    cpu_physical_memory_read(addr, (void *) &ret, 4);
+    return ret;
+}
+
+void omap_badwidth_write32(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    OMAP_32B_REG(addr);
+    cpu_physical_memory_write(addr, (void *) &value, 4);
+}
+
+/* MPU OS timers */
+struct omap_mpu_timer_s {
+    MemoryRegion iomem;
+    qemu_irq irq;
+    omap_clk clk;
+    uint32_t val;
+    int64_t time;
+    QEMUTimer *timer;
+    QEMUBH *tick;
+    int64_t rate;
+    int it_ena;
+
+    int enable;
+    int ptv;
+    int ar;
+    int st;
+    uint32_t reset_val;
+};
+
+static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer)
+{
+    uint64_t distance = qemu_get_clock_ns(vm_clock) - timer->time;
+
+    if (timer->st && timer->enable && timer->rate)
+        return timer->val - muldiv64(distance >> (timer->ptv + 1),
+                                     timer->rate, get_ticks_per_sec());
+    else
+        return timer->val;
+}
+
+static inline void omap_timer_sync(struct omap_mpu_timer_s *timer)
+{
+    timer->val = omap_timer_read(timer);
+    timer->time = qemu_get_clock_ns(vm_clock);
+}
+
+static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
+{
+    int64_t expires;
+
+    if (timer->enable && timer->st && timer->rate) {
+        timer->val = timer->reset_val; /* Should skip this on clk enable */
+        expires = muldiv64((uint64_t) timer->val << (timer->ptv + 1),
+                           get_ticks_per_sec(), timer->rate);
+
+        /* If timer expiry would be sooner than in about 1 ms and
+         * auto-reload isn't set, then fire immediately.  This is a hack
+         * to make systems like PalmOS run in acceptable time.  PalmOS
+         * sets the interval to a very low value and polls the status bit
+         * in a busy loop when it wants to sleep just a couple of CPU
+         * ticks.  */
+        if (expires > (get_ticks_per_sec() >> 10) || timer->ar)
+            qemu_mod_timer(timer->timer, timer->time + expires);
+        else
+            qemu_bh_schedule(timer->tick);
+    } else
+        qemu_del_timer(timer->timer);
+}
+
+static void omap_timer_fire(void *opaque)
+{
+    struct omap_mpu_timer_s *timer = opaque;
+
+    if (!timer->ar) {
+        timer->val = 0;
+        timer->st = 0;
+    }
+
+    if (timer->it_ena)
+        /* Edge-triggered irq */
+        qemu_irq_pulse(timer->irq);
+}
+
+static void omap_timer_tick(void *opaque)
+{
+    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
+
+    omap_timer_sync(timer);
+    omap_timer_fire(timer);
+    omap_timer_update(timer);
+}
+
+static void omap_timer_clk_update(void *opaque, int line, int on)
+{
+    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
+
+    omap_timer_sync(timer);
+    timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
+    omap_timer_update(timer);
+}
+
+static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
+{
+    omap_clk_adduser(timer->clk,
+                    qemu_allocate_irqs(omap_timer_clk_update, timer, 1)[0]);
+    timer->rate = omap_clk_getrate(timer->clk);
+}
+
+static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr,
+                                    unsigned size)
+{
+    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00: /* CNTL_TIMER */
+        return (s->enable << 5) | (s->ptv << 2) | (s->ar << 1) | s->st;
+
+    case 0x04: /* LOAD_TIM */
+        break;
+
+    case 0x08: /* READ_TIM */
+        return omap_timer_read(s);
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mpu_timer_write(void *opaque, hwaddr addr,
+                                 uint64_t value, unsigned size)
+{
+    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00: /* CNTL_TIMER */
+        omap_timer_sync(s);
+        s->enable = (value >> 5) & 1;
+        s->ptv = (value >> 2) & 7;
+        s->ar = (value >> 1) & 1;
+        s->st = value & 1;
+        omap_timer_update(s);
+        return;
+
+    case 0x04: /* LOAD_TIM */
+        s->reset_val = value;
+        return;
+
+    case 0x08: /* READ_TIM */
+        OMAP_RO_REG(addr);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_mpu_timer_ops = {
+    .read = omap_mpu_timer_read,
+    .write = omap_mpu_timer_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s)
+{
+    qemu_del_timer(s->timer);
+    s->enable = 0;
+    s->reset_val = 31337;
+    s->val = 0;
+    s->ptv = 0;
+    s->ar = 0;
+    s->st = 0;
+    s->it_ena = 1;
+}
+
+static struct omap_mpu_timer_s *omap_mpu_timer_init(MemoryRegion *system_memory,
+                hwaddr base,
+                qemu_irq irq, omap_clk clk)
+{
+    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *)
+            g_malloc0(sizeof(struct omap_mpu_timer_s));
+
+    s->irq = irq;
+    s->clk = clk;
+    s->timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, s);
+    s->tick = qemu_bh_new(omap_timer_fire, s);
+    omap_mpu_timer_reset(s);
+    omap_timer_clk_setup(s);
+
+    memory_region_init_io(&s->iomem, &omap_mpu_timer_ops, s,
+                          "omap-mpu-timer", 0x100);
+
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    return s;
+}
+
+/* Watchdog timer */
+struct omap_watchdog_timer_s {
+    struct omap_mpu_timer_s timer;
+    MemoryRegion iomem;
+    uint8_t last_wr;
+    int mode;
+    int free;
+    int reset;
+};
+
+static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr,
+                                   unsigned size)
+{
+    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00: /* CNTL_TIMER */
+        return (s->timer.ptv << 9) | (s->timer.ar << 8) |
+                (s->timer.st << 7) | (s->free << 1);
+
+    case 0x04: /* READ_TIMER */
+        return omap_timer_read(&s->timer);
+
+    case 0x08: /* TIMER_MODE */
+        return s->mode << 15;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_wd_timer_write(void *opaque, hwaddr addr,
+                                uint64_t value, unsigned size)
+{
+    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00: /* CNTL_TIMER */
+        omap_timer_sync(&s->timer);
+        s->timer.ptv = (value >> 9) & 7;
+        s->timer.ar = (value >> 8) & 1;
+        s->timer.st = (value >> 7) & 1;
+        s->free = (value >> 1) & 1;
+        omap_timer_update(&s->timer);
+        break;
+
+    case 0x04: /* LOAD_TIMER */
+        s->timer.reset_val = value & 0xffff;
+        break;
+
+    case 0x08: /* TIMER_MODE */
+        if (!s->mode && ((value >> 15) & 1))
+            omap_clk_get(s->timer.clk);
+        s->mode |= (value >> 15) & 1;
+        if (s->last_wr == 0xf5) {
+            if ((value & 0xff) == 0xa0) {
+                if (s->mode) {
+                    s->mode = 0;
+                    omap_clk_put(s->timer.clk);
+                }
+            } else {
+                /* XXX: on T|E hardware somehow this has no effect,
+                 * on Zire 71 it works as specified.  */
+                s->reset = 1;
+                qemu_system_reset_request();
+            }
+        }
+        s->last_wr = value & 0xff;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_wd_timer_ops = {
+    .read = omap_wd_timer_read,
+    .write = omap_wd_timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s)
+{
+    qemu_del_timer(s->timer.timer);
+    if (!s->mode)
+        omap_clk_get(s->timer.clk);
+    s->mode = 1;
+    s->free = 1;
+    s->reset = 0;
+    s->timer.enable = 1;
+    s->timer.it_ena = 1;
+    s->timer.reset_val = 0xffff;
+    s->timer.val = 0;
+    s->timer.st = 0;
+    s->timer.ptv = 0;
+    s->timer.ar = 0;
+    omap_timer_update(&s->timer);
+}
+
+static struct omap_watchdog_timer_s *omap_wd_timer_init(MemoryRegion *memory,
+                hwaddr base,
+                qemu_irq irq, omap_clk clk)
+{
+    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *)
+            g_malloc0(sizeof(struct omap_watchdog_timer_s));
+
+    s->timer.irq = irq;
+    s->timer.clk = clk;
+    s->timer.timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, &s->timer);
+    omap_wd_timer_reset(s);
+    omap_timer_clk_setup(&s->timer);
+
+    memory_region_init_io(&s->iomem, &omap_wd_timer_ops, s,
+                          "omap-wd-timer", 0x100);
+    memory_region_add_subregion(memory, base, &s->iomem);
+
+    return s;
+}
+
+/* 32-kHz timer */
+struct omap_32khz_timer_s {
+    struct omap_mpu_timer_s timer;
+    MemoryRegion iomem;
+};
+
+static uint64_t omap_os_timer_read(void *opaque, hwaddr addr,
+                                   unsigned size)
+{
+    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00: /* TVR */
+        return s->timer.reset_val;
+
+    case 0x04: /* TCR */
+        return omap_timer_read(&s->timer);
+
+    case 0x08: /* CR */
+        return (s->timer.ar << 3) | (s->timer.it_ena << 2) | s->timer.st;
+
+    default:
+        break;
+    }
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_os_timer_write(void *opaque, hwaddr addr,
+                                uint64_t value, unsigned size)
+{
+    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00: /* TVR */
+        s->timer.reset_val = value & 0x00ffffff;
+        break;
+
+    case 0x04: /* TCR */
+        OMAP_RO_REG(addr);
+        break;
+
+    case 0x08: /* CR */
+        s->timer.ar = (value >> 3) & 1;
+        s->timer.it_ena = (value >> 2) & 1;
+        if (s->timer.st != (value & 1) || (value & 2)) {
+            omap_timer_sync(&s->timer);
+            s->timer.enable = value & 1;
+            s->timer.st = value & 1;
+            omap_timer_update(&s->timer);
+        }
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_os_timer_ops = {
+    .read = omap_os_timer_read,
+    .write = omap_os_timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_os_timer_reset(struct omap_32khz_timer_s *s)
+{
+    qemu_del_timer(s->timer.timer);
+    s->timer.enable = 0;
+    s->timer.it_ena = 0;
+    s->timer.reset_val = 0x00ffffff;
+    s->timer.val = 0;
+    s->timer.st = 0;
+    s->timer.ptv = 0;
+    s->timer.ar = 1;
+}
+
+static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory,
+                hwaddr base,
+                qemu_irq irq, omap_clk clk)
+{
+    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *)
+            g_malloc0(sizeof(struct omap_32khz_timer_s));
+
+    s->timer.irq = irq;
+    s->timer.clk = clk;
+    s->timer.timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, &s->timer);
+    omap_os_timer_reset(s);
+    omap_timer_clk_setup(&s->timer);
+
+    memory_region_init_io(&s->iomem, &omap_os_timer_ops, s,
+                          "omap-os-timer", 0x800);
+    memory_region_add_subregion(memory, base, &s->iomem);
+
+    return s;
+}
+
+/* Ultra Low-Power Device Module */
+static uint64_t omap_ulpd_pm_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    uint16_t ret;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x14: /* IT_STATUS */
+        ret = s->ulpd_pm_regs[addr >> 2];
+        s->ulpd_pm_regs[addr >> 2] = 0;
+        qemu_irq_lower(qdev_get_gpio_in(s->ih[1], OMAP_INT_GAUGE_32K));
+        return ret;
+
+    case 0x18: /* Reserved */
+    case 0x1c: /* Reserved */
+    case 0x20: /* Reserved */
+    case 0x28: /* Reserved */
+    case 0x2c: /* Reserved */
+        OMAP_BAD_REG(addr);
+        /* fall through */
+    case 0x00: /* COUNTER_32_LSB */
+    case 0x04: /* COUNTER_32_MSB */
+    case 0x08: /* COUNTER_HIGH_FREQ_LSB */
+    case 0x0c: /* COUNTER_HIGH_FREQ_MSB */
+    case 0x10: /* GAUGING_CTRL */
+    case 0x24: /* SETUP_ANALOG_CELL3_ULPD1 */
+    case 0x30: /* CLOCK_CTRL */
+    case 0x34: /* SOFT_REQ */
+    case 0x38: /* COUNTER_32_FIQ */
+    case 0x3c: /* DPLL_CTRL */
+    case 0x40: /* STATUS_REQ */
+        /* XXX: check clk::usecount state for every clock */
+    case 0x48: /* LOCL_TIME */
+    case 0x4c: /* APLL_CTRL */
+    case 0x50: /* POWER_CTRL */
+        return s->ulpd_pm_regs[addr >> 2];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static inline void omap_ulpd_clk_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    if (diff & (1 << 4))                               /* USB_MCLK_EN */
+        omap_clk_onoff(omap_findclk(s, "usb_clk0"), (value >> 4) & 1);
+    if (diff & (1 << 5))                               /* DIS_USB_PVCI_CLK */
+        omap_clk_onoff(omap_findclk(s, "usb_w2fc_ck"), (~value >> 5) & 1);
+}
+
+static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    if (diff & (1 << 0))                               /* SOFT_DPLL_REQ */
+        omap_clk_canidle(omap_findclk(s, "dpll4"), (~value >> 0) & 1);
+    if (diff & (1 << 1))                               /* SOFT_COM_REQ */
+        omap_clk_canidle(omap_findclk(s, "com_mclk_out"), (~value >> 1) & 1);
+    if (diff & (1 << 2))                               /* SOFT_SDW_REQ */
+        omap_clk_canidle(omap_findclk(s, "bt_mclk_out"), (~value >> 2) & 1);
+    if (diff & (1 << 3))                               /* SOFT_USB_REQ */
+        omap_clk_canidle(omap_findclk(s, "usb_clk0"), (~value >> 3) & 1);
+}
+
+static void omap_ulpd_pm_write(void *opaque, hwaddr addr,
+                               uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    int64_t now, ticks;
+    int div, mult;
+    static const int bypass_div[4] = { 1, 2, 4, 4 };
+    uint16_t diff;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00: /* COUNTER_32_LSB */
+    case 0x04: /* COUNTER_32_MSB */
+    case 0x08: /* COUNTER_HIGH_FREQ_LSB */
+    case 0x0c: /* COUNTER_HIGH_FREQ_MSB */
+    case 0x14: /* IT_STATUS */
+    case 0x40: /* STATUS_REQ */
+        OMAP_RO_REG(addr);
+        break;
+
+    case 0x10: /* GAUGING_CTRL */
+        /* Bits 0 and 1 seem to be confused in the OMAP 310 TRM */
+        if ((s->ulpd_pm_regs[addr >> 2] ^ value) & 1) {
+            now = qemu_get_clock_ns(vm_clock);
+
+            if (value & 1)
+                s->ulpd_gauge_start = now;
+            else {
+                now -= s->ulpd_gauge_start;
+
+                /* 32-kHz ticks */
+                ticks = muldiv64(now, 32768, get_ticks_per_sec());
+                s->ulpd_pm_regs[0x00 >> 2] = (ticks >>  0) & 0xffff;
+                s->ulpd_pm_regs[0x04 >> 2] = (ticks >> 16) & 0xffff;
+                if (ticks >> 32)       /* OVERFLOW_32K */
+                    s->ulpd_pm_regs[0x14 >> 2] |= 1 << 2;
+
+                /* High frequency ticks */
+                ticks = muldiv64(now, 12000000, get_ticks_per_sec());
+                s->ulpd_pm_regs[0x08 >> 2] = (ticks >>  0) & 0xffff;
+                s->ulpd_pm_regs[0x0c >> 2] = (ticks >> 16) & 0xffff;
+                if (ticks >> 32)       /* OVERFLOW_HI_FREQ */
+                    s->ulpd_pm_regs[0x14 >> 2] |= 1 << 1;
+
+                s->ulpd_pm_regs[0x14 >> 2] |= 1 << 0;  /* IT_GAUGING */
+                qemu_irq_raise(qdev_get_gpio_in(s->ih[1], OMAP_INT_GAUGE_32K));
+            }
+        }
+        s->ulpd_pm_regs[addr >> 2] = value;
+        break;
+
+    case 0x18: /* Reserved */
+    case 0x1c: /* Reserved */
+    case 0x20: /* Reserved */
+    case 0x28: /* Reserved */
+    case 0x2c: /* Reserved */
+        OMAP_BAD_REG(addr);
+        /* fall through */
+    case 0x24: /* SETUP_ANALOG_CELL3_ULPD1 */
+    case 0x38: /* COUNTER_32_FIQ */
+    case 0x48: /* LOCL_TIME */
+    case 0x50: /* POWER_CTRL */
+        s->ulpd_pm_regs[addr >> 2] = value;
+        break;
+
+    case 0x30: /* CLOCK_CTRL */
+        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0x3f;
+        omap_ulpd_clk_update(s, diff, value);
+        break;
+
+    case 0x34: /* SOFT_REQ */
+        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0x1f;
+        omap_ulpd_req_update(s, diff, value);
+        break;
+
+    case 0x3c: /* DPLL_CTRL */
+        /* XXX: OMAP310 TRM claims bit 3 is PLL_ENABLE, and bit 4 is
+         * omitted altogether, probably a typo.  */
+        /* This register has identical semantics with DPLL(1:3) control
+         * registers, see omap_dpll_write() */
+        diff = s->ulpd_pm_regs[addr >> 2] & value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0x2fff;
+        if (diff & (0x3ff << 2)) {
+            if (value & (1 << 4)) {                    /* PLL_ENABLE */
+                div = ((value >> 5) & 3) + 1;          /* PLL_DIV */
+                mult = MIN((value >> 7) & 0x1f, 1);    /* PLL_MULT */
+            } else {
+                div = bypass_div[((value >> 2) & 3)];  /* BYPASS_DIV */
+                mult = 1;
+            }
+            omap_clk_setrate(omap_findclk(s, "dpll4"), div, mult);
+        }
+
+        /* Enter the desired mode.  */
+        s->ulpd_pm_regs[addr >> 2] =
+                (s->ulpd_pm_regs[addr >> 2] & 0xfffe) |
+                ((s->ulpd_pm_regs[addr >> 2] >> 4) & 1);
+
+        /* Act as if the lock is restored.  */
+        s->ulpd_pm_regs[addr >> 2] |= 2;
+        break;
+
+    case 0x4c: /* APLL_CTRL */
+        diff = s->ulpd_pm_regs[addr >> 2] & value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0xf;
+        if (diff & (1 << 0))                           /* APLL_NDPLL_SWITCH */
+            omap_clk_reparent(omap_findclk(s, "ck_48m"), omap_findclk(s,
+                                    (value & (1 << 0)) ? "apll" : "dpll4"));
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_ulpd_pm_ops = {
+    .read = omap_ulpd_pm_read,
+    .write = omap_ulpd_pm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_ulpd_pm_reset(struct omap_mpu_state_s *mpu)
+{
+    mpu->ulpd_pm_regs[0x00 >> 2] = 0x0001;
+    mpu->ulpd_pm_regs[0x04 >> 2] = 0x0000;
+    mpu->ulpd_pm_regs[0x08 >> 2] = 0x0001;
+    mpu->ulpd_pm_regs[0x0c >> 2] = 0x0000;
+    mpu->ulpd_pm_regs[0x10 >> 2] = 0x0000;
+    mpu->ulpd_pm_regs[0x18 >> 2] = 0x01;
+    mpu->ulpd_pm_regs[0x1c >> 2] = 0x01;
+    mpu->ulpd_pm_regs[0x20 >> 2] = 0x01;
+    mpu->ulpd_pm_regs[0x24 >> 2] = 0x03ff;
+    mpu->ulpd_pm_regs[0x28 >> 2] = 0x01;
+    mpu->ulpd_pm_regs[0x2c >> 2] = 0x01;
+    omap_ulpd_clk_update(mpu, mpu->ulpd_pm_regs[0x30 >> 2], 0x0000);
+    mpu->ulpd_pm_regs[0x30 >> 2] = 0x0000;
+    omap_ulpd_req_update(mpu, mpu->ulpd_pm_regs[0x34 >> 2], 0x0000);
+    mpu->ulpd_pm_regs[0x34 >> 2] = 0x0000;
+    mpu->ulpd_pm_regs[0x38 >> 2] = 0x0001;
+    mpu->ulpd_pm_regs[0x3c >> 2] = 0x2211;
+    mpu->ulpd_pm_regs[0x40 >> 2] = 0x0000; /* FIXME: dump a real STATUS_REQ */
+    mpu->ulpd_pm_regs[0x48 >> 2] = 0x960;
+    mpu->ulpd_pm_regs[0x4c >> 2] = 0x08;
+    mpu->ulpd_pm_regs[0x50 >> 2] = 0x08;
+    omap_clk_setrate(omap_findclk(mpu, "dpll4"), 1, 4);
+    omap_clk_reparent(omap_findclk(mpu, "ck_48m"), omap_findclk(mpu, "dpll4"));
+}
+
+static void omap_ulpd_pm_init(MemoryRegion *system_memory,
+                hwaddr base,
+                struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->ulpd_pm_iomem, &omap_ulpd_pm_ops, mpu,
+                          "omap-ulpd-pm", 0x800);
+    memory_region_add_subregion(system_memory, base, &mpu->ulpd_pm_iomem);
+    omap_ulpd_pm_reset(mpu);
+}
+
+/* OMAP Pin Configuration */
+static uint64_t omap_pin_cfg_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00: /* FUNC_MUX_CTRL_0 */
+    case 0x04: /* FUNC_MUX_CTRL_1 */
+    case 0x08: /* FUNC_MUX_CTRL_2 */
+        return s->func_mux_ctrl[addr >> 2];
+
+    case 0x0c: /* COMP_MODE_CTRL_0 */
+        return s->comp_mode_ctrl[0];
+
+    case 0x10: /* FUNC_MUX_CTRL_3 */
+    case 0x14: /* FUNC_MUX_CTRL_4 */
+    case 0x18: /* FUNC_MUX_CTRL_5 */
+    case 0x1c: /* FUNC_MUX_CTRL_6 */
+    case 0x20: /* FUNC_MUX_CTRL_7 */
+    case 0x24: /* FUNC_MUX_CTRL_8 */
+    case 0x28: /* FUNC_MUX_CTRL_9 */
+    case 0x2c: /* FUNC_MUX_CTRL_A */
+    case 0x30: /* FUNC_MUX_CTRL_B */
+    case 0x34: /* FUNC_MUX_CTRL_C */
+    case 0x38: /* FUNC_MUX_CTRL_D */
+        return s->func_mux_ctrl[(addr >> 2) - 1];
+
+    case 0x40: /* PULL_DWN_CTRL_0 */
+    case 0x44: /* PULL_DWN_CTRL_1 */
+    case 0x48: /* PULL_DWN_CTRL_2 */
+    case 0x4c: /* PULL_DWN_CTRL_3 */
+        return s->pull_dwn_ctrl[(addr & 0xf) >> 2];
+
+    case 0x50: /* GATE_INH_CTRL_0 */
+        return s->gate_inh_ctrl[0];
+
+    case 0x60: /* VOLTAGE_CTRL_0 */
+        return s->voltage_ctrl[0];
+
+    case 0x70: /* TEST_DBG_CTRL_0 */
+        return s->test_dbg_ctrl[0];
+
+    case 0x80: /* MOD_CONF_CTRL_0 */
+        return s->mod_conf_ctrl[0];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static inline void omap_pin_funcmux0_update(struct omap_mpu_state_s *s,
+                uint32_t diff, uint32_t value)
+{
+    if (s->compat1509) {
+        if (diff & (1 << 9))                   /* BLUETOOTH */
+            omap_clk_onoff(omap_findclk(s, "bt_mclk_out"),
+                            (~value >> 9) & 1);
+        if (diff & (1 << 7))                   /* USB.CLKO */
+            omap_clk_onoff(omap_findclk(s, "usb.clko"),
+                            (value >> 7) & 1);
+    }
+}
+
+static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s,
+                uint32_t diff, uint32_t value)
+{
+    if (s->compat1509) {
+        if (diff & (1 << 31))                  /* MCBSP3_CLK_HIZ_DI */
+            omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"),
+                            (value >> 31) & 1);
+        if (diff & (1 << 1))                   /* CLK32K */
+            omap_clk_onoff(omap_findclk(s, "clk32k_out"),
+                            (~value >> 1) & 1);
+    }
+}
+
+static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
+                uint32_t diff, uint32_t value)
+{
+    if (diff & (1 << 31))                      /* CONF_MOD_UART3_CLK_MODE_R */
+         omap_clk_reparent(omap_findclk(s, "uart3_ck"),
+                         omap_findclk(s, ((value >> 31) & 1) ?
+                                 "ck_48m" : "armper_ck"));
+    if (diff & (1 << 30))                      /* CONF_MOD_UART2_CLK_MODE_R */
+         omap_clk_reparent(omap_findclk(s, "uart2_ck"),
+                         omap_findclk(s, ((value >> 30) & 1) ?
+                                 "ck_48m" : "armper_ck"));
+    if (diff & (1 << 29))                      /* CONF_MOD_UART1_CLK_MODE_R */
+         omap_clk_reparent(omap_findclk(s, "uart1_ck"),
+                         omap_findclk(s, ((value >> 29) & 1) ?
+                                 "ck_48m" : "armper_ck"));
+    if (diff & (1 << 23))                      /* CONF_MOD_MMC_SD_CLK_REQ_R */
+         omap_clk_reparent(omap_findclk(s, "mmc_ck"),
+                         omap_findclk(s, ((value >> 23) & 1) ?
+                                 "ck_48m" : "armper_ck"));
+    if (diff & (1 << 12))                      /* CONF_MOD_COM_MCLK_12_48_S */
+         omap_clk_reparent(omap_findclk(s, "com_mclk_out"),
+                         omap_findclk(s, ((value >> 12) & 1) ?
+                                 "ck_48m" : "armper_ck"));
+    if (diff & (1 << 9))                       /* CONF_MOD_USB_HOST_HHC_UHO */
+         omap_clk_onoff(omap_findclk(s, "usb_hhc_ck"), (value >> 9) & 1);
+}
+
+static void omap_pin_cfg_write(void *opaque, hwaddr addr,
+                               uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    uint32_t diff;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00: /* FUNC_MUX_CTRL_0 */
+        diff = s->func_mux_ctrl[addr >> 2] ^ value;
+        s->func_mux_ctrl[addr >> 2] = value;
+        omap_pin_funcmux0_update(s, diff, value);
+        return;
+
+    case 0x04: /* FUNC_MUX_CTRL_1 */
+        diff = s->func_mux_ctrl[addr >> 2] ^ value;
+        s->func_mux_ctrl[addr >> 2] = value;
+        omap_pin_funcmux1_update(s, diff, value);
+        return;
+
+    case 0x08: /* FUNC_MUX_CTRL_2 */
+        s->func_mux_ctrl[addr >> 2] = value;
+        return;
+
+    case 0x0c: /* COMP_MODE_CTRL_0 */
+        s->comp_mode_ctrl[0] = value;
+        s->compat1509 = (value != 0x0000eaef);
+        omap_pin_funcmux0_update(s, ~0, s->func_mux_ctrl[0]);
+        omap_pin_funcmux1_update(s, ~0, s->func_mux_ctrl[1]);
+        return;
+
+    case 0x10: /* FUNC_MUX_CTRL_3 */
+    case 0x14: /* FUNC_MUX_CTRL_4 */
+    case 0x18: /* FUNC_MUX_CTRL_5 */
+    case 0x1c: /* FUNC_MUX_CTRL_6 */
+    case 0x20: /* FUNC_MUX_CTRL_7 */
+    case 0x24: /* FUNC_MUX_CTRL_8 */
+    case 0x28: /* FUNC_MUX_CTRL_9 */
+    case 0x2c: /* FUNC_MUX_CTRL_A */
+    case 0x30: /* FUNC_MUX_CTRL_B */
+    case 0x34: /* FUNC_MUX_CTRL_C */
+    case 0x38: /* FUNC_MUX_CTRL_D */
+        s->func_mux_ctrl[(addr >> 2) - 1] = value;
+        return;
+
+    case 0x40: /* PULL_DWN_CTRL_0 */
+    case 0x44: /* PULL_DWN_CTRL_1 */
+    case 0x48: /* PULL_DWN_CTRL_2 */
+    case 0x4c: /* PULL_DWN_CTRL_3 */
+        s->pull_dwn_ctrl[(addr & 0xf) >> 2] = value;
+        return;
+
+    case 0x50: /* GATE_INH_CTRL_0 */
+        s->gate_inh_ctrl[0] = value;
+        return;
+
+    case 0x60: /* VOLTAGE_CTRL_0 */
+        s->voltage_ctrl[0] = value;
+        return;
+
+    case 0x70: /* TEST_DBG_CTRL_0 */
+        s->test_dbg_ctrl[0] = value;
+        return;
+
+    case 0x80: /* MOD_CONF_CTRL_0 */
+        diff = s->mod_conf_ctrl[0] ^ value;
+        s->mod_conf_ctrl[0] = value;
+        omap_pin_modconf1_update(s, diff, value);
+        return;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_pin_cfg_ops = {
+    .read = omap_pin_cfg_read,
+    .write = omap_pin_cfg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_pin_cfg_reset(struct omap_mpu_state_s *mpu)
+{
+    /* Start in Compatibility Mode.  */
+    mpu->compat1509 = 1;
+    omap_pin_funcmux0_update(mpu, mpu->func_mux_ctrl[0], 0);
+    omap_pin_funcmux1_update(mpu, mpu->func_mux_ctrl[1], 0);
+    omap_pin_modconf1_update(mpu, mpu->mod_conf_ctrl[0], 0);
+    memset(mpu->func_mux_ctrl, 0, sizeof(mpu->func_mux_ctrl));
+    memset(mpu->comp_mode_ctrl, 0, sizeof(mpu->comp_mode_ctrl));
+    memset(mpu->pull_dwn_ctrl, 0, sizeof(mpu->pull_dwn_ctrl));
+    memset(mpu->gate_inh_ctrl, 0, sizeof(mpu->gate_inh_ctrl));
+    memset(mpu->voltage_ctrl, 0, sizeof(mpu->voltage_ctrl));
+    memset(mpu->test_dbg_ctrl, 0, sizeof(mpu->test_dbg_ctrl));
+    memset(mpu->mod_conf_ctrl, 0, sizeof(mpu->mod_conf_ctrl));
+}
+
+static void omap_pin_cfg_init(MemoryRegion *system_memory,
+                hwaddr base,
+                struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->pin_cfg_iomem, &omap_pin_cfg_ops, mpu,
+                          "omap-pin-cfg", 0x800);
+    memory_region_add_subregion(system_memory, base, &mpu->pin_cfg_iomem);
+    omap_pin_cfg_reset(mpu);
+}
+
+/* Device Identification, Die Identification */
+static uint64_t omap_id_read(void *opaque, hwaddr addr,
+                             unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0xfffe1800:   /* DIE_ID_LSB */
+        return 0xc9581f0e;
+    case 0xfffe1804:   /* DIE_ID_MSB */
+        return 0xa8858bfa;
+
+    case 0xfffe2000:   /* PRODUCT_ID_LSB */
+        return 0x00aaaafc;
+    case 0xfffe2004:   /* PRODUCT_ID_MSB */
+        return 0xcafeb574;
+
+    case 0xfffed400:   /* JTAG_ID_LSB */
+        switch (s->mpu_model) {
+        case omap310:
+            return 0x03310315;
+        case omap1510:
+            return 0x03310115;
+        default:
+            hw_error("%s: bad mpu model\n", __FUNCTION__);
+        }
+        break;
+
+    case 0xfffed404:   /* JTAG_ID_MSB */
+        switch (s->mpu_model) {
+        case omap310:
+            return 0xfb57402f;
+        case omap1510:
+            return 0xfb47002f;
+        default:
+            hw_error("%s: bad mpu model\n", __FUNCTION__);
+        }
+        break;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_id_write(void *opaque, hwaddr addr,
+                          uint64_t value, unsigned size)
+{
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    OMAP_BAD_REG(addr);
+}
+
+static const MemoryRegionOps omap_id_ops = {
+    .read = omap_id_read,
+    .write = omap_id_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_id_init(MemoryRegion *memory, struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->id_iomem, &omap_id_ops, mpu,
+                          "omap-id", 0x100000000ULL);
+    memory_region_init_alias(&mpu->id_iomem_e18, "omap-id-e18", &mpu->id_iomem,
+                             0xfffe1800, 0x800);
+    memory_region_add_subregion(memory, 0xfffe1800, &mpu->id_iomem_e18);
+    memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-ed4", &mpu->id_iomem,
+                             0xfffed400, 0x100);
+    memory_region_add_subregion(memory, 0xfffed400, &mpu->id_iomem_ed4);
+    if (!cpu_is_omap15xx(mpu)) {
+        memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-e20",
+                                 &mpu->id_iomem, 0xfffe2000, 0x800);
+        memory_region_add_subregion(memory, 0xfffe2000, &mpu->id_iomem_e20);
+    }
+}
+
+/* MPUI Control (Dummy) */
+static uint64_t omap_mpui_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00: /* CTRL */
+        return s->mpui_ctrl;
+    case 0x04: /* DEBUG_ADDR */
+        return 0x01ffffff;
+    case 0x08: /* DEBUG_DATA */
+        return 0xffffffff;
+    case 0x0c: /* DEBUG_FLAG */
+        return 0x00000800;
+    case 0x10: /* STATUS */
+        return 0x00000000;
+
+    /* Not in OMAP310 */
+    case 0x14: /* DSP_STATUS */
+    case 0x18: /* DSP_BOOT_CONFIG */
+        return 0x00000000;
+    case 0x1c: /* DSP_MPUI_CONFIG */
+        return 0x0000ffff;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mpui_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00: /* CTRL */
+        s->mpui_ctrl = value & 0x007fffff;
+        break;
+
+    case 0x04: /* DEBUG_ADDR */
+    case 0x08: /* DEBUG_DATA */
+    case 0x0c: /* DEBUG_FLAG */
+    case 0x10: /* STATUS */
+    /* Not in OMAP310 */
+    case 0x14: /* DSP_STATUS */
+        OMAP_RO_REG(addr);
+        break;
+    case 0x18: /* DSP_BOOT_CONFIG */
+    case 0x1c: /* DSP_MPUI_CONFIG */
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_mpui_ops = {
+    .read = omap_mpui_read,
+    .write = omap_mpui_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_mpui_reset(struct omap_mpu_state_s *s)
+{
+    s->mpui_ctrl = 0x0003ff1b;
+}
+
+static void omap_mpui_init(MemoryRegion *memory, hwaddr base,
+                struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->mpui_iomem, &omap_mpui_ops, mpu,
+                          "omap-mpui", 0x100);
+    memory_region_add_subregion(memory, base, &mpu->mpui_iomem);
+
+    omap_mpui_reset(mpu);
+}
+
+/* TIPB Bridges */
+struct omap_tipb_bridge_s {
+    qemu_irq abort;
+    MemoryRegion iomem;
+
+    int width_intr;
+    uint16_t control;
+    uint16_t alloc;
+    uint16_t buffer;
+    uint16_t enh_control;
+};
+
+static uint64_t omap_tipb_bridge_read(void *opaque, hwaddr addr,
+                                      unsigned size)
+{
+    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
+
+    if (size < 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00: /* TIPB_CNTL */
+        return s->control;
+    case 0x04: /* TIPB_BUS_ALLOC */
+        return s->alloc;
+    case 0x08: /* MPU_TIPB_CNTL */
+        return s->buffer;
+    case 0x0c: /* ENHANCED_TIPB_CNTL */
+        return s->enh_control;
+    case 0x10: /* ADDRESS_DBG */
+    case 0x14: /* DATA_DEBUG_LOW */
+    case 0x18: /* DATA_DEBUG_HIGH */
+        return 0xffff;
+    case 0x1c: /* DEBUG_CNTR_SIG */
+        return 0x00f8;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_tipb_bridge_write(void *opaque, hwaddr addr,
+                                   uint64_t value, unsigned size)
+{
+    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
+
+    if (size < 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00: /* TIPB_CNTL */
+        s->control = value & 0xffff;
+        break;
+
+    case 0x04: /* TIPB_BUS_ALLOC */
+        s->alloc = value & 0x003f;
+        break;
+
+    case 0x08: /* MPU_TIPB_CNTL */
+        s->buffer = value & 0x0003;
+        break;
+
+    case 0x0c: /* ENHANCED_TIPB_CNTL */
+        s->width_intr = !(value & 2);
+        s->enh_control = value & 0x000f;
+        break;
+
+    case 0x10: /* ADDRESS_DBG */
+    case 0x14: /* DATA_DEBUG_LOW */
+    case 0x18: /* DATA_DEBUG_HIGH */
+    case 0x1c: /* DEBUG_CNTR_SIG */
+        OMAP_RO_REG(addr);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_tipb_bridge_ops = {
+    .read = omap_tipb_bridge_read,
+    .write = omap_tipb_bridge_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_tipb_bridge_reset(struct omap_tipb_bridge_s *s)
+{
+    s->control = 0xffff;
+    s->alloc = 0x0009;
+    s->buffer = 0x0000;
+    s->enh_control = 0x000f;
+}
+
+static struct omap_tipb_bridge_s *omap_tipb_bridge_init(
+    MemoryRegion *memory, hwaddr base,
+    qemu_irq abort_irq, omap_clk clk)
+{
+    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *)
+            g_malloc0(sizeof(struct omap_tipb_bridge_s));
+
+    s->abort = abort_irq;
+    omap_tipb_bridge_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_tipb_bridge_ops, s,
+                          "omap-tipb-bridge", 0x100);
+    memory_region_add_subregion(memory, base, &s->iomem);
+
+    return s;
+}
+
+/* Dummy Traffic Controller's Memory Interface */
+static uint64_t omap_tcmi_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    uint32_t ret;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00: /* IMIF_PRIO */
+    case 0x04: /* EMIFS_PRIO */
+    case 0x08: /* EMIFF_PRIO */
+    case 0x0c: /* EMIFS_CONFIG */
+    case 0x10: /* EMIFS_CS0_CONFIG */
+    case 0x14: /* EMIFS_CS1_CONFIG */
+    case 0x18: /* EMIFS_CS2_CONFIG */
+    case 0x1c: /* EMIFS_CS3_CONFIG */
+    case 0x24: /* EMIFF_MRS */
+    case 0x28: /* TIMEOUT1 */
+    case 0x2c: /* TIMEOUT2 */
+    case 0x30: /* TIMEOUT3 */
+    case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
+    case 0x40: /* EMIFS_CFG_DYN_WAIT */
+        return s->tcmi_regs[addr >> 2];
+
+    case 0x20: /* EMIFF_SDRAM_CONFIG */
+        ret = s->tcmi_regs[addr >> 2];
+        s->tcmi_regs[addr >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */
+        /* XXX: We can try using the VGA_DIRTY flag for this */
+        return ret;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_tcmi_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00: /* IMIF_PRIO */
+    case 0x04: /* EMIFS_PRIO */
+    case 0x08: /* EMIFF_PRIO */
+    case 0x10: /* EMIFS_CS0_CONFIG */
+    case 0x14: /* EMIFS_CS1_CONFIG */
+    case 0x18: /* EMIFS_CS2_CONFIG */
+    case 0x1c: /* EMIFS_CS3_CONFIG */
+    case 0x20: /* EMIFF_SDRAM_CONFIG */
+    case 0x24: /* EMIFF_MRS */
+    case 0x28: /* TIMEOUT1 */
+    case 0x2c: /* TIMEOUT2 */
+    case 0x30: /* TIMEOUT3 */
+    case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
+    case 0x40: /* EMIFS_CFG_DYN_WAIT */
+        s->tcmi_regs[addr >> 2] = value;
+        break;
+    case 0x0c: /* EMIFS_CONFIG */
+        s->tcmi_regs[addr >> 2] = (value & 0xf) | (1 << 4);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_tcmi_ops = {
+    .read = omap_tcmi_read,
+    .write = omap_tcmi_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_tcmi_reset(struct omap_mpu_state_s *mpu)
+{
+    mpu->tcmi_regs[0x00 >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x04 >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x08 >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x0c >> 2] = 0x00000010;
+    mpu->tcmi_regs[0x10 >> 2] = 0x0010fffb;
+    mpu->tcmi_regs[0x14 >> 2] = 0x0010fffb;
+    mpu->tcmi_regs[0x18 >> 2] = 0x0010fffb;
+    mpu->tcmi_regs[0x1c >> 2] = 0x0010fffb;
+    mpu->tcmi_regs[0x20 >> 2] = 0x00618800;
+    mpu->tcmi_regs[0x24 >> 2] = 0x00000037;
+    mpu->tcmi_regs[0x28 >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x2c >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x30 >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x3c >> 2] = 0x00000003;
+    mpu->tcmi_regs[0x40 >> 2] = 0x00000000;
+}
+
+static void omap_tcmi_init(MemoryRegion *memory, hwaddr base,
+                struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->tcmi_iomem, &omap_tcmi_ops, mpu,
+                          "omap-tcmi", 0x100);
+    memory_region_add_subregion(memory, base, &mpu->tcmi_iomem);
+    omap_tcmi_reset(mpu);
+}
+
+/* Digital phase-locked loops control */
+struct dpll_ctl_s {
+    MemoryRegion iomem;
+    uint16_t mode;
+    omap_clk dpll;
+};
+
+static uint64_t omap_dpll_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    if (addr == 0x00)  /* CTL_REG */
+        return s->mode;
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_dpll_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
+    uint16_t diff;
+    static const int bypass_div[4] = { 1, 2, 4, 4 };
+    int div, mult;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    if (addr == 0x00) {        /* CTL_REG */
+        /* See omap_ulpd_pm_write() too */
+        diff = s->mode & value;
+        s->mode = value & 0x2fff;
+        if (diff & (0x3ff << 2)) {
+            if (value & (1 << 4)) {                    /* PLL_ENABLE */
+                div = ((value >> 5) & 3) + 1;          /* PLL_DIV */
+                mult = MIN((value >> 7) & 0x1f, 1);    /* PLL_MULT */
+            } else {
+                div = bypass_div[((value >> 2) & 3)];  /* BYPASS_DIV */
+                mult = 1;
+            }
+            omap_clk_setrate(s->dpll, div, mult);
+        }
+
+        /* Enter the desired mode.  */
+        s->mode = (s->mode & 0xfffe) | ((s->mode >> 4) & 1);
+
+        /* Act as if the lock is restored.  */
+        s->mode |= 2;
+    } else {
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_dpll_ops = {
+    .read = omap_dpll_read,
+    .write = omap_dpll_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_dpll_reset(struct dpll_ctl_s *s)
+{
+    s->mode = 0x2002;
+    omap_clk_setrate(s->dpll, 1, 1);
+}
+
+static struct dpll_ctl_s  *omap_dpll_init(MemoryRegion *memory,
+                           hwaddr base, omap_clk clk)
+{
+    struct dpll_ctl_s *s = g_malloc0(sizeof(*s));
+    memory_region_init_io(&s->iomem, &omap_dpll_ops, s, "omap-dpll", 0x100);
+
+    s->dpll = clk;
+    omap_dpll_reset(s);
+
+    memory_region_add_subregion(memory, base, &s->iomem);
+    return s;
+}
+
+/* MPU Clock/Reset/Power Mode Control */
+static uint64_t omap_clkm_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00: /* ARM_CKCTL */
+        return s->clkm.arm_ckctl;
+
+    case 0x04: /* ARM_IDLECT1 */
+        return s->clkm.arm_idlect1;
+
+    case 0x08: /* ARM_IDLECT2 */
+        return s->clkm.arm_idlect2;
+
+    case 0x0c: /* ARM_EWUPCT */
+        return s->clkm.arm_ewupct;
+
+    case 0x10: /* ARM_RSTCT1 */
+        return s->clkm.arm_rstct1;
+
+    case 0x14: /* ARM_RSTCT2 */
+        return s->clkm.arm_rstct2;
+
+    case 0x18: /* ARM_SYSST */
+        return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start;
+
+    case 0x1c: /* ARM_CKOUT1 */
+        return s->clkm.arm_ckout1;
+
+    case 0x20: /* ARM_CKOUT2 */
+        break;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static inline void omap_clkm_ckctl_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+    if (diff & (1 << 14)) {                            /* ARM_INTHCK_SEL */
+        if (value & (1 << 14))
+            /* Reserved */;
+        else {
+            clk = omap_findclk(s, "arminth_ck");
+            omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
+        }
+    }
+    if (diff & (1 << 12)) {                            /* ARM_TIMXO */
+        clk = omap_findclk(s, "armtim_ck");
+        if (value & (1 << 12))
+            omap_clk_reparent(clk, omap_findclk(s, "clkin"));
+        else
+            omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
+    }
+    /* XXX: en_dspck */
+    if (diff & (3 << 10)) {                            /* DSPMMUDIV */
+        clk = omap_findclk(s, "dspmmu_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 10) & 3), 1);
+    }
+    if (diff & (3 << 8)) {                             /* TCDIV */
+        clk = omap_findclk(s, "tc_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 8) & 3), 1);
+    }
+    if (diff & (3 << 6)) {                             /* DSPDIV */
+        clk = omap_findclk(s, "dsp_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 6) & 3), 1);
+    }
+    if (diff & (3 << 4)) {                             /* ARMDIV */
+        clk = omap_findclk(s, "arm_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 4) & 3), 1);
+    }
+    if (diff & (3 << 2)) {                             /* LCDDIV */
+        clk = omap_findclk(s, "lcd_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 2) & 3), 1);
+    }
+    if (diff & (3 << 0)) {                             /* PERDIV */
+        clk = omap_findclk(s, "armper_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 0) & 3), 1);
+    }
+}
+
+static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+    if (value & (1 << 11)) {                            /* SETARM_IDLE */
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+    }
+    if (!(value & (1 << 10)))                          /* WKUP_MODE */
+        qemu_system_shutdown_request();        /* XXX: disable wakeup from IRQ */
+
+#define SET_CANIDLE(clock, bit)                                \
+    if (diff & (1 << bit)) {                           \
+        clk = omap_findclk(s, clock);                  \
+        omap_clk_canidle(clk, (value >> bit) & 1);     \
+    }
+    SET_CANIDLE("mpuwd_ck", 0)                         /* IDLWDT_ARM */
+    SET_CANIDLE("armxor_ck", 1)                                /* IDLXORP_ARM */
+    SET_CANIDLE("mpuper_ck", 2)                                /* IDLPER_ARM */
+    SET_CANIDLE("lcd_ck", 3)                           /* IDLLCD_ARM */
+    SET_CANIDLE("lb_ck", 4)                            /* IDLLB_ARM */
+    SET_CANIDLE("hsab_ck", 5)                          /* IDLHSAB_ARM */
+    SET_CANIDLE("tipb_ck", 6)                          /* IDLIF_ARM */
+    SET_CANIDLE("dma_ck", 6)                           /* IDLIF_ARM */
+    SET_CANIDLE("tc_ck", 6)                            /* IDLIF_ARM */
+    SET_CANIDLE("dpll1", 7)                            /* IDLDPLL_ARM */
+    SET_CANIDLE("dpll2", 7)                            /* IDLDPLL_ARM */
+    SET_CANIDLE("dpll3", 7)                            /* IDLDPLL_ARM */
+    SET_CANIDLE("mpui_ck", 8)                          /* IDLAPI_ARM */
+    SET_CANIDLE("armtim_ck", 9)                                /* IDLTIM_ARM */
+}
+
+static inline void omap_clkm_idlect2_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+#define SET_ONOFF(clock, bit)                          \
+    if (diff & (1 << bit)) {                           \
+        clk = omap_findclk(s, clock);                  \
+        omap_clk_onoff(clk, (value >> bit) & 1);       \
+    }
+    SET_ONOFF("mpuwd_ck", 0)                           /* EN_WDTCK */
+    SET_ONOFF("armxor_ck", 1)                          /* EN_XORPCK */
+    SET_ONOFF("mpuper_ck", 2)                          /* EN_PERCK */
+    SET_ONOFF("lcd_ck", 3)                             /* EN_LCDCK */
+    SET_ONOFF("lb_ck", 4)                              /* EN_LBCK */
+    SET_ONOFF("hsab_ck", 5)                            /* EN_HSABCK */
+    SET_ONOFF("mpui_ck", 6)                            /* EN_APICK */
+    SET_ONOFF("armtim_ck", 7)                          /* EN_TIMCK */
+    SET_CANIDLE("dma_ck", 8)                           /* DMACK_REQ */
+    SET_ONOFF("arm_gpio_ck", 9)                                /* EN_GPIOCK */
+    SET_ONOFF("lbfree_ck", 10)                         /* EN_LBFREECK */
+}
+
+static inline void omap_clkm_ckout1_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+    if (diff & (3 << 4)) {                             /* TCLKOUT */
+        clk = omap_findclk(s, "tclk_out");
+        switch ((value >> 4) & 3) {
+        case 1:
+            omap_clk_reparent(clk, omap_findclk(s, "ck_gen3"));
+            omap_clk_onoff(clk, 1);
+            break;
+        case 2:
+            omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
+            omap_clk_onoff(clk, 1);
+            break;
+        default:
+            omap_clk_onoff(clk, 0);
+        }
+    }
+    if (diff & (3 << 2)) {                             /* DCLKOUT */
+        clk = omap_findclk(s, "dclk_out");
+        switch ((value >> 2) & 3) {
+        case 0:
+            omap_clk_reparent(clk, omap_findclk(s, "dspmmu_ck"));
+            break;
+        case 1:
+            omap_clk_reparent(clk, omap_findclk(s, "ck_gen2"));
+            break;
+        case 2:
+            omap_clk_reparent(clk, omap_findclk(s, "dsp_ck"));
+            break;
+        case 3:
+            omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
+            break;
+        }
+    }
+    if (diff & (3 << 0)) {                             /* ACLKOUT */
+        clk = omap_findclk(s, "aclk_out");
+        switch ((value >> 0) & 3) {
+        case 1:
+            omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
+            omap_clk_onoff(clk, 1);
+            break;
+        case 2:
+            omap_clk_reparent(clk, omap_findclk(s, "arm_ck"));
+            omap_clk_onoff(clk, 1);
+            break;
+        case 3:
+            omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
+            omap_clk_onoff(clk, 1);
+            break;
+        default:
+            omap_clk_onoff(clk, 0);
+        }
+    }
+}
+
+static void omap_clkm_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    uint16_t diff;
+    omap_clk clk;
+    static const char *clkschemename[8] = {
+        "fully synchronous", "fully asynchronous", "synchronous scalable",
+        "mix mode 1", "mix mode 2", "bypass mode", "mix mode 3", "mix mode 4",
+    };
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00: /* ARM_CKCTL */
+        diff = s->clkm.arm_ckctl ^ value;
+        s->clkm.arm_ckctl = value & 0x7fff;
+        omap_clkm_ckctl_update(s, diff, value);
+        return;
+
+    case 0x04: /* ARM_IDLECT1 */
+        diff = s->clkm.arm_idlect1 ^ value;
+        s->clkm.arm_idlect1 = value & 0x0fff;
+        omap_clkm_idlect1_update(s, diff, value);
+        return;
+
+    case 0x08: /* ARM_IDLECT2 */
+        diff = s->clkm.arm_idlect2 ^ value;
+        s->clkm.arm_idlect2 = value & 0x07ff;
+        omap_clkm_idlect2_update(s, diff, value);
+        return;
+
+    case 0x0c: /* ARM_EWUPCT */
+        s->clkm.arm_ewupct = value & 0x003f;
+        return;
+
+    case 0x10: /* ARM_RSTCT1 */
+        diff = s->clkm.arm_rstct1 ^ value;
+        s->clkm.arm_rstct1 = value & 0x0007;
+        if (value & 9) {
+            qemu_system_reset_request();
+            s->clkm.cold_start = 0xa;
+        }
+        if (diff & ~value & 4) {                               /* DSP_RST */
+            omap_mpui_reset(s);
+            omap_tipb_bridge_reset(s->private_tipb);
+            omap_tipb_bridge_reset(s->public_tipb);
+        }
+        if (diff & 2) {                                                /* DSP_EN */
+            clk = omap_findclk(s, "dsp_ck");
+            omap_clk_canidle(clk, (~value >> 1) & 1);
+        }
+        return;
+
+    case 0x14: /* ARM_RSTCT2 */
+        s->clkm.arm_rstct2 = value & 0x0001;
+        return;
+
+    case 0x18: /* ARM_SYSST */
+        if ((s->clkm.clocking_scheme ^ (value >> 11)) & 7) {
+            s->clkm.clocking_scheme = (value >> 11) & 7;
+            printf("%s: clocking scheme set to %s\n", __FUNCTION__,
+                            clkschemename[s->clkm.clocking_scheme]);
+        }
+        s->clkm.cold_start &= value & 0x3f;
+        return;
+
+    case 0x1c: /* ARM_CKOUT1 */
+        diff = s->clkm.arm_ckout1 ^ value;
+        s->clkm.arm_ckout1 = value & 0x003f;
+        omap_clkm_ckout1_update(s, diff, value);
+        return;
+
+    case 0x20: /* ARM_CKOUT2 */
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_clkm_ops = {
+    .read = omap_clkm_read,
+    .write = omap_clkm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
+                                 unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x04: /* DSP_IDLECT1 */
+        return s->clkm.dsp_idlect1;
+
+    case 0x08: /* DSP_IDLECT2 */
+        return s->clkm.dsp_idlect2;
+
+    case 0x14: /* DSP_RSTCT2 */
+        return s->clkm.dsp_rstct2;
+
+    case 0x18: /* DSP_SYSST */
+        return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
+                (s->cpu->env.halted << 6);      /* Quite useless... */
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static inline void omap_clkdsp_idlect1_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+    SET_CANIDLE("dspxor_ck", 1);                       /* IDLXORP_DSP */
+}
+
+static inline void omap_clkdsp_idlect2_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+    SET_ONOFF("dspxor_ck", 1);                         /* EN_XORPCK */
+}
+
+static void omap_clkdsp_write(void *opaque, hwaddr addr,
+                              uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    uint16_t diff;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x04: /* DSP_IDLECT1 */
+        diff = s->clkm.dsp_idlect1 ^ value;
+        s->clkm.dsp_idlect1 = value & 0x01f7;
+        omap_clkdsp_idlect1_update(s, diff, value);
+        break;
+
+    case 0x08: /* DSP_IDLECT2 */
+        s->clkm.dsp_idlect2 = value & 0x0037;
+        diff = s->clkm.dsp_idlect1 ^ value;
+        omap_clkdsp_idlect2_update(s, diff, value);
+        break;
+
+    case 0x14: /* DSP_RSTCT2 */
+        s->clkm.dsp_rstct2 = value & 0x0001;
+        break;
+
+    case 0x18: /* DSP_SYSST */
+        s->clkm.cold_start &= value & 0x3f;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_clkdsp_ops = {
+    .read = omap_clkdsp_read,
+    .write = omap_clkdsp_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_clkm_reset(struct omap_mpu_state_s *s)
+{
+    if (s->wdt && s->wdt->reset)
+        s->clkm.cold_start = 0x6;
+    s->clkm.clocking_scheme = 0;
+    omap_clkm_ckctl_update(s, ~0, 0x3000);
+    s->clkm.arm_ckctl = 0x3000;
+    omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 ^ 0x0400, 0x0400);
+    s->clkm.arm_idlect1 = 0x0400;
+    omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 ^ 0x0100, 0x0100);
+    s->clkm.arm_idlect2 = 0x0100;
+    s->clkm.arm_ewupct = 0x003f;
+    s->clkm.arm_rstct1 = 0x0000;
+    s->clkm.arm_rstct2 = 0x0000;
+    s->clkm.arm_ckout1 = 0x0015;
+    s->clkm.dpll1_mode = 0x2002;
+    omap_clkdsp_idlect1_update(s, s->clkm.dsp_idlect1 ^ 0x0040, 0x0040);
+    s->clkm.dsp_idlect1 = 0x0040;
+    omap_clkdsp_idlect2_update(s, ~0, 0x0000);
+    s->clkm.dsp_idlect2 = 0x0000;
+    s->clkm.dsp_rstct2 = 0x0000;
+}
+
+static void omap_clkm_init(MemoryRegion *memory, hwaddr mpu_base,
+                hwaddr dsp_base, struct omap_mpu_state_s *s)
+{
+    memory_region_init_io(&s->clkm_iomem, &omap_clkm_ops, s,
+                          "omap-clkm", 0x100);
+    memory_region_init_io(&s->clkdsp_iomem, &omap_clkdsp_ops, s,
+                          "omap-clkdsp", 0x1000);
+
+    s->clkm.arm_idlect1 = 0x03ff;
+    s->clkm.arm_idlect2 = 0x0100;
+    s->clkm.dsp_idlect1 = 0x0002;
+    omap_clkm_reset(s);
+    s->clkm.cold_start = 0x3a;
+
+    memory_region_add_subregion(memory, mpu_base, &s->clkm_iomem);
+    memory_region_add_subregion(memory, dsp_base, &s->clkdsp_iomem);
+}
+
+/* MPU I/O */
+struct omap_mpuio_s {
+    qemu_irq irq;
+    qemu_irq kbd_irq;
+    qemu_irq *in;
+    qemu_irq handler[16];
+    qemu_irq wakeup;
+    MemoryRegion iomem;
+
+    uint16_t inputs;
+    uint16_t outputs;
+    uint16_t dir;
+    uint16_t edge;
+    uint16_t mask;
+    uint16_t ints;
+
+    uint16_t debounce;
+    uint16_t latch;
+    uint8_t event;
+
+    uint8_t buttons[5];
+    uint8_t row_latch;
+    uint8_t cols;
+    int kbd_mask;
+    int clk;
+};
+
+static void omap_mpuio_set(void *opaque, int line, int level)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+    uint16_t prev = s->inputs;
+
+    if (level)
+        s->inputs |= 1 << line;
+    else
+        s->inputs &= ~(1 << line);
+
+    if (((1 << line) & s->dir & ~s->mask) && s->clk) {
+        if ((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) {
+            s->ints |= 1 << line;
+            qemu_irq_raise(s->irq);
+            /* TODO: wakeup */
+        }
+        if ((s->event & (1 << 0)) &&           /* SET_GPIO_EVENT_MODE */
+                (s->event >> 1) == line)       /* PIN_SELECT */
+            s->latch = s->inputs;
+    }
+}
+
+static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
+{
+    int i;
+    uint8_t *row, rows = 0, cols = ~s->cols;
+
+    for (row = s->buttons + 4, i = 1 << 4; i; row --, i >>= 1)
+        if (*row & cols)
+            rows |= i;
+
+    qemu_set_irq(s->kbd_irq, rows && !s->kbd_mask && s->clk);
+    s->row_latch = ~rows;
+}
+
+static uint64_t omap_mpuio_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+    uint16_t ret;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00: /* INPUT_LATCH */
+        return s->inputs;
+
+    case 0x04: /* OUTPUT_REG */
+        return s->outputs;
+
+    case 0x08: /* IO_CNTL */
+        return s->dir;
+
+    case 0x10: /* KBR_LATCH */
+        return s->row_latch;
+
+    case 0x14: /* KBC_REG */
+        return s->cols;
+
+    case 0x18: /* GPIO_EVENT_MODE_REG */
+        return s->event;
+
+    case 0x1c: /* GPIO_INT_EDGE_REG */
+        return s->edge;
+
+    case 0x20: /* KBD_INT */
+        return (~s->row_latch & 0x1f) && !s->kbd_mask;
+
+    case 0x24: /* GPIO_INT */
+        ret = s->ints;
+        s->ints &= s->mask;
+        if (ret)
+            qemu_irq_lower(s->irq);
+        return ret;
+
+    case 0x28: /* KBD_MASKIT */
+        return s->kbd_mask;
+
+    case 0x2c: /* GPIO_MASKIT */
+        return s->mask;
+
+    case 0x30: /* GPIO_DEBOUNCING_REG */
+        return s->debounce;
+
+    case 0x34: /* GPIO_LATCH_REG */
+        return s->latch;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mpuio_write(void *opaque, hwaddr addr,
+                             uint64_t value, unsigned size)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+    uint16_t diff;
+    int ln;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x04: /* OUTPUT_REG */
+        diff = (s->outputs ^ value) & ~s->dir;
+        s->outputs = value;
+        while ((ln = ffs(diff))) {
+            ln --;
+            if (s->handler[ln])
+                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+            diff &= ~(1 << ln);
+        }
+        break;
+
+    case 0x08: /* IO_CNTL */
+        diff = s->outputs & (s->dir ^ value);
+        s->dir = value;
+
+        value = s->outputs & ~s->dir;
+        while ((ln = ffs(diff))) {
+            ln --;
+            if (s->handler[ln])
+                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+            diff &= ~(1 << ln);
+        }
+        break;
+
+    case 0x14: /* KBC_REG */
+        s->cols = value;
+        omap_mpuio_kbd_update(s);
+        break;
+
+    case 0x18: /* GPIO_EVENT_MODE_REG */
+        s->event = value & 0x1f;
+        break;
+
+    case 0x1c: /* GPIO_INT_EDGE_REG */
+        s->edge = value;
+        break;
+
+    case 0x28: /* KBD_MASKIT */
+        s->kbd_mask = value & 1;
+        omap_mpuio_kbd_update(s);
+        break;
+
+    case 0x2c: /* GPIO_MASKIT */
+        s->mask = value;
+        break;
+
+    case 0x30: /* GPIO_DEBOUNCING_REG */
+        s->debounce = value & 0x1ff;
+        break;
+
+    case 0x00: /* INPUT_LATCH */
+    case 0x10: /* KBR_LATCH */
+    case 0x20: /* KBD_INT */
+    case 0x24: /* GPIO_INT */
+    case 0x34: /* GPIO_LATCH_REG */
+        OMAP_RO_REG(addr);
+        return;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_mpuio_ops  = {
+    .read = omap_mpuio_read,
+    .write = omap_mpuio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_mpuio_reset(struct omap_mpuio_s *s)
+{
+    s->inputs = 0;
+    s->outputs = 0;
+    s->dir = ~0;
+    s->event = 0;
+    s->edge = 0;
+    s->kbd_mask = 0;
+    s->mask = 0;
+    s->debounce = 0;
+    s->latch = 0;
+    s->ints = 0;
+    s->row_latch = 0x1f;
+    s->clk = 1;
+}
+
+static void omap_mpuio_onoff(void *opaque, int line, int on)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+
+    s->clk = on;
+    if (on)
+        omap_mpuio_kbd_update(s);
+}
+
+static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory,
+                hwaddr base,
+                qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
+                omap_clk clk)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *)
+            g_malloc0(sizeof(struct omap_mpuio_s));
+
+    s->irq = gpio_int;
+    s->kbd_irq = kbd_int;
+    s->wakeup = wakeup;
+    s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
+    omap_mpuio_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_mpuio_ops, s,
+                          "omap-mpuio", 0x800);
+    memory_region_add_subregion(memory, base, &s->iomem);
+
+    omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
+
+    return s;
+}
+
+qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
+{
+    return s->in;
+}
+
+void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
+{
+    if (line >= 16 || line < 0)
+        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
+    s->handler[line] = handler;
+}
+
+void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
+{
+    if (row >= 5 || row < 0)
+        hw_error("%s: No key %i-%i\n", __FUNCTION__, col, row);
+
+    if (down)
+        s->buttons[row] |= 1 << col;
+    else
+        s->buttons[row] &= ~(1 << col);
+
+    omap_mpuio_kbd_update(s);
+}
+
+/* MicroWire Interface */
+struct omap_uwire_s {
+    MemoryRegion iomem;
+    qemu_irq txirq;
+    qemu_irq rxirq;
+    qemu_irq txdrq;
+
+    uint16_t txbuf;
+    uint16_t rxbuf;
+    uint16_t control;
+    uint16_t setup[5];
+
+    uWireSlave *chip[4];
+};
+
+static void omap_uwire_transfer_start(struct omap_uwire_s *s)
+{
+    int chipselect = (s->control >> 10) & 3;           /* INDEX */
+    uWireSlave *slave = s->chip[chipselect];
+
+    if ((s->control >> 5) & 0x1f) {                    /* NB_BITS_WR */
+        if (s->control & (1 << 12))                    /* CS_CMD */
+            if (slave && slave->send)
+                slave->send(slave->opaque,
+                                s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
+        s->control &= ~(1 << 14);                      /* CSRB */
+        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
+         * a DRQ.  When is the level IRQ supposed to be reset?  */
+    }
+
+    if ((s->control >> 0) & 0x1f) {                    /* NB_BITS_RD */
+        if (s->control & (1 << 12))                    /* CS_CMD */
+            if (slave && slave->receive)
+                s->rxbuf = slave->receive(slave->opaque);
+        s->control |= 1 << 15;                         /* RDRB */
+        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
+         * a DRQ.  When is the level IRQ supposed to be reset?  */
+    }
+}
+
+static uint64_t omap_uwire_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00: /* RDR */
+        s->control &= ~(1 << 15);                      /* RDRB */
+        return s->rxbuf;
+
+    case 0x04: /* CSR */
+        return s->control;
+
+    case 0x08: /* SR1 */
+        return s->setup[0];
+    case 0x0c: /* SR2 */
+        return s->setup[1];
+    case 0x10: /* SR3 */
+        return s->setup[2];
+    case 0x14: /* SR4 */
+        return s->setup[3];
+    case 0x18: /* SR5 */
+        return s->setup[4];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_uwire_write(void *opaque, hwaddr addr,
+                             uint64_t value, unsigned size)
+{
+    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00: /* TDR */
+        s->txbuf = value;                              /* TD */
+        if ((s->setup[4] & (1 << 2)) &&                        /* AUTO_TX_EN */
+                        ((s->setup[4] & (1 << 3)) ||   /* CS_TOGGLE_TX_EN */
+                         (s->control & (1 << 12)))) {  /* CS_CMD */
+            s->control |= 1 << 14;                     /* CSRB */
+            omap_uwire_transfer_start(s);
+        }
+        break;
+
+    case 0x04: /* CSR */
+        s->control = value & 0x1fff;
+        if (value & (1 << 13))                         /* START */
+            omap_uwire_transfer_start(s);
+        break;
+
+    case 0x08: /* SR1 */
+        s->setup[0] = value & 0x003f;
+        break;
+
+    case 0x0c: /* SR2 */
+        s->setup[1] = value & 0x0fc0;
+        break;
+
+    case 0x10: /* SR3 */
+        s->setup[2] = value & 0x0003;
+        break;
+
+    case 0x14: /* SR4 */
+        s->setup[3] = value & 0x0001;
+        break;
+
+    case 0x18: /* SR5 */
+        s->setup[4] = value & 0x000f;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_uwire_ops = {
+    .read = omap_uwire_read,
+    .write = omap_uwire_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_uwire_reset(struct omap_uwire_s *s)
+{
+    s->control = 0;
+    s->setup[0] = 0;
+    s->setup[1] = 0;
+    s->setup[2] = 0;
+    s->setup[3] = 0;
+    s->setup[4] = 0;
+}
+
+static struct omap_uwire_s *omap_uwire_init(MemoryRegion *system_memory,
+                                            hwaddr base,
+                                            qemu_irq txirq, qemu_irq rxirq,
+                                            qemu_irq dma,
+                                            omap_clk clk)
+{
+    struct omap_uwire_s *s = (struct omap_uwire_s *)
+            g_malloc0(sizeof(struct omap_uwire_s));
+
+    s->txirq = txirq;
+    s->rxirq = rxirq;
+    s->txdrq = dma;
+    omap_uwire_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_uwire_ops, s, "omap-uwire", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    return s;
+}
+
+void omap_uwire_attach(struct omap_uwire_s *s,
+                uWireSlave *slave, int chipselect)
+{
+    if (chipselect < 0 || chipselect > 3) {
+        fprintf(stderr, "%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
+        exit(-1);
+    }
+
+    s->chip[chipselect] = slave;
+}
+
+/* Pseudonoise Pulse-Width Light Modulator */
+struct omap_pwl_s {
+    MemoryRegion iomem;
+    uint8_t output;
+    uint8_t level;
+    uint8_t enable;
+    int clk;
+};
+
+static void omap_pwl_update(struct omap_pwl_s *s)
+{
+    int output = (s->clk && s->enable) ? s->level : 0;
+
+    if (output != s->output) {
+        s->output = output;
+        printf("%s: Backlight now at %i/256\n", __FUNCTION__, output);
+    }
+}
+
+static uint64_t omap_pwl_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_read8(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00: /* PWL_LEVEL */
+        return s->level;
+    case 0x04: /* PWL_CTRL */
+        return s->enable;
+    }
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_pwl_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00: /* PWL_LEVEL */
+        s->level = value;
+        omap_pwl_update(s);
+        break;
+    case 0x04: /* PWL_CTRL */
+        s->enable = value & 1;
+        omap_pwl_update(s);
+        break;
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_pwl_ops = {
+    .read = omap_pwl_read,
+    .write = omap_pwl_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_pwl_reset(struct omap_pwl_s *s)
+{
+    s->output = 0;
+    s->level = 0;
+    s->enable = 0;
+    s->clk = 1;
+    omap_pwl_update(s);
+}
+
+static void omap_pwl_clk_update(void *opaque, int line, int on)
+{
+    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
+
+    s->clk = on;
+    omap_pwl_update(s);
+}
+
+static struct omap_pwl_s *omap_pwl_init(MemoryRegion *system_memory,
+                                        hwaddr base,
+                                        omap_clk clk)
+{
+    struct omap_pwl_s *s = g_malloc0(sizeof(*s));
+
+    omap_pwl_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_pwl_ops, s,
+                          "omap-pwl", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
+    return s;
+}
+
+/* Pulse-Width Tone module */
+struct omap_pwt_s {
+    MemoryRegion iomem;
+    uint8_t frc;
+    uint8_t vrc;
+    uint8_t gcr;
+    omap_clk clk;
+};
+
+static uint64_t omap_pwt_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_read8(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00: /* FRC */
+        return s->frc;
+    case 0x04: /* VCR */
+        return s->vrc;
+    case 0x08: /* GCR */
+        return s->gcr;
+    }
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_pwt_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00: /* FRC */
+        s->frc = value & 0x3f;
+        break;
+    case 0x04: /* VRC */
+        if ((value ^ s->vrc) & 1) {
+            if (value & 1)
+                printf("%s: %iHz buzz on\n", __FUNCTION__, (int)
+                                /* 1.5 MHz from a 12-MHz or 13-MHz PWT_CLK */
+                                ((omap_clk_getrate(s->clk) >> 3) /
+                                 /* Pre-multiplexer divider */
+                                 ((s->gcr & 2) ? 1 : 154) /
+                                 /* Octave multiplexer */
+                                 (2 << (value & 3)) *
+                                 /* 101/107 divider */
+                                 ((value & (1 << 2)) ? 101 : 107) *
+                                 /*  49/55 divider */
+                                 ((value & (1 << 3)) ?  49 : 55) *
+                                 /*  50/63 divider */
+                                 ((value & (1 << 4)) ?  50 : 63) *
+                                 /*  80/127 divider */
+                                 ((value & (1 << 5)) ?  80 : 127) /
+                                 (107 * 55 * 63 * 127)));
+            else
+                printf("%s: silence!\n", __FUNCTION__);
+        }
+        s->vrc = value & 0x7f;
+        break;
+    case 0x08: /* GCR */
+        s->gcr = value & 3;
+        break;
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_pwt_ops = {
+    .read =omap_pwt_read,
+    .write = omap_pwt_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_pwt_reset(struct omap_pwt_s *s)
+{
+    s->frc = 0;
+    s->vrc = 0;
+    s->gcr = 0;
+}
+
+static struct omap_pwt_s *omap_pwt_init(MemoryRegion *system_memory,
+                                        hwaddr base,
+                                        omap_clk clk)
+{
+    struct omap_pwt_s *s = g_malloc0(sizeof(*s));
+    s->clk = clk;
+    omap_pwt_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_pwt_ops, s,
+                          "omap-pwt", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+    return s;
+}
+
+/* Real-time Clock module */
+struct omap_rtc_s {
+    MemoryRegion iomem;
+    qemu_irq irq;
+    qemu_irq alarm;
+    QEMUTimer *clk;
+
+    uint8_t interrupts;
+    uint8_t status;
+    int16_t comp_reg;
+    int running;
+    int pm_am;
+    int auto_comp;
+    int round;
+    struct tm alarm_tm;
+    time_t alarm_ti;
+
+    struct tm current_tm;
+    time_t ti;
+    uint64_t tick;
+};
+
+static void omap_rtc_interrupts_update(struct omap_rtc_s *s)
+{
+    /* s->alarm is level-triggered */
+    qemu_set_irq(s->alarm, (s->status >> 6) & 1);
+}
+
+static void omap_rtc_alarm_update(struct omap_rtc_s *s)
+{
+    s->alarm_ti = mktimegm(&s->alarm_tm);
+    if (s->alarm_ti == -1)
+        printf("%s: conversion failed\n", __FUNCTION__);
+}
+
+static uint64_t omap_rtc_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+    uint8_t i;
+
+    if (size != 1) {
+        return omap_badwidth_read8(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00: /* SECONDS_REG */
+        return to_bcd(s->current_tm.tm_sec);
+
+    case 0x04: /* MINUTES_REG */
+        return to_bcd(s->current_tm.tm_min);
+
+    case 0x08: /* HOURS_REG */
+        if (s->pm_am)
+            return ((s->current_tm.tm_hour > 11) << 7) |
+                    to_bcd(((s->current_tm.tm_hour - 1) % 12) + 1);
+        else
+            return to_bcd(s->current_tm.tm_hour);
+
+    case 0x0c: /* DAYS_REG */
+        return to_bcd(s->current_tm.tm_mday);
+
+    case 0x10: /* MONTHS_REG */
+        return to_bcd(s->current_tm.tm_mon + 1);
+
+    case 0x14: /* YEARS_REG */
+        return to_bcd(s->current_tm.tm_year % 100);
+
+    case 0x18: /* WEEK_REG */
+        return s->current_tm.tm_wday;
+
+    case 0x20: /* ALARM_SECONDS_REG */
+        return to_bcd(s->alarm_tm.tm_sec);
+
+    case 0x24: /* ALARM_MINUTES_REG */
+        return to_bcd(s->alarm_tm.tm_min);
+
+    case 0x28: /* ALARM_HOURS_REG */
+        if (s->pm_am)
+            return ((s->alarm_tm.tm_hour > 11) << 7) |
+                    to_bcd(((s->alarm_tm.tm_hour - 1) % 12) + 1);
+        else
+            return to_bcd(s->alarm_tm.tm_hour);
+
+    case 0x2c: /* ALARM_DAYS_REG */
+        return to_bcd(s->alarm_tm.tm_mday);
+
+    case 0x30: /* ALARM_MONTHS_REG */
+        return to_bcd(s->alarm_tm.tm_mon + 1);
+
+    case 0x34: /* ALARM_YEARS_REG */
+        return to_bcd(s->alarm_tm.tm_year % 100);
+
+    case 0x40: /* RTC_CTRL_REG */
+        return (s->pm_am << 3) | (s->auto_comp << 2) |
+                (s->round << 1) | s->running;
+
+    case 0x44: /* RTC_STATUS_REG */
+        i = s->status;
+        s->status &= ~0x3d;
+        return i;
+
+    case 0x48: /* RTC_INTERRUPTS_REG */
+        return s->interrupts;
+
+    case 0x4c: /* RTC_COMP_LSB_REG */
+        return ((uint16_t) s->comp_reg) & 0xff;
+
+    case 0x50: /* RTC_COMP_MSB_REG */
+        return ((uint16_t) s->comp_reg) >> 8;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_rtc_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+    struct tm new_tm;
+    time_t ti[2];
+
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00: /* SECONDS_REG */
+#ifdef ALMDEBUG
+        printf("RTC SEC_REG <-- %02x\n", value);
+#endif
+        s->ti -= s->current_tm.tm_sec;
+        s->ti += from_bcd(value);
+        return;
+
+    case 0x04: /* MINUTES_REG */
+#ifdef ALMDEBUG
+        printf("RTC MIN_REG <-- %02x\n", value);
+#endif
+        s->ti -= s->current_tm.tm_min * 60;
+        s->ti += from_bcd(value) * 60;
+        return;
+
+    case 0x08: /* HOURS_REG */
+#ifdef ALMDEBUG
+        printf("RTC HRS_REG <-- %02x\n", value);
+#endif
+        s->ti -= s->current_tm.tm_hour * 3600;
+        if (s->pm_am) {
+            s->ti += (from_bcd(value & 0x3f) & 12) * 3600;
+            s->ti += ((value >> 7) & 1) * 43200;
+        } else
+            s->ti += from_bcd(value & 0x3f) * 3600;
+        return;
+
+    case 0x0c: /* DAYS_REG */
+#ifdef ALMDEBUG
+        printf("RTC DAY_REG <-- %02x\n", value);
+#endif
+        s->ti -= s->current_tm.tm_mday * 86400;
+        s->ti += from_bcd(value) * 86400;
+        return;
+
+    case 0x10: /* MONTHS_REG */
+#ifdef ALMDEBUG
+        printf("RTC MTH_REG <-- %02x\n", value);
+#endif
+        memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
+        new_tm.tm_mon = from_bcd(value);
+        ti[0] = mktimegm(&s->current_tm);
+        ti[1] = mktimegm(&new_tm);
+
+        if (ti[0] != -1 && ti[1] != -1) {
+            s->ti -= ti[0];
+            s->ti += ti[1];
+        } else {
+            /* A less accurate version */
+            s->ti -= s->current_tm.tm_mon * 2592000;
+            s->ti += from_bcd(value) * 2592000;
+        }
+        return;
+
+    case 0x14: /* YEARS_REG */
+#ifdef ALMDEBUG
+        printf("RTC YRS_REG <-- %02x\n", value);
+#endif
+        memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
+        new_tm.tm_year += from_bcd(value) - (new_tm.tm_year % 100);
+        ti[0] = mktimegm(&s->current_tm);
+        ti[1] = mktimegm(&new_tm);
+
+        if (ti[0] != -1 && ti[1] != -1) {
+            s->ti -= ti[0];
+            s->ti += ti[1];
+        } else {
+            /* A less accurate version */
+            s->ti -= (s->current_tm.tm_year % 100) * 31536000;
+            s->ti += from_bcd(value) * 31536000;
+        }
+        return;
+
+    case 0x18: /* WEEK_REG */
+        return;        /* Ignored */
+
+    case 0x20: /* ALARM_SECONDS_REG */
+#ifdef ALMDEBUG
+        printf("ALM SEC_REG <-- %02x\n", value);
+#endif
+        s->alarm_tm.tm_sec = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x24: /* ALARM_MINUTES_REG */
+#ifdef ALMDEBUG
+        printf("ALM MIN_REG <-- %02x\n", value);
+#endif
+        s->alarm_tm.tm_min = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x28: /* ALARM_HOURS_REG */
+#ifdef ALMDEBUG
+        printf("ALM HRS_REG <-- %02x\n", value);
+#endif
+        if (s->pm_am)
+            s->alarm_tm.tm_hour =
+                    ((from_bcd(value & 0x3f)) % 12) +
+                    ((value >> 7) & 1) * 12;
+        else
+            s->alarm_tm.tm_hour = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x2c: /* ALARM_DAYS_REG */
+#ifdef ALMDEBUG
+        printf("ALM DAY_REG <-- %02x\n", value);
+#endif
+        s->alarm_tm.tm_mday = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x30: /* ALARM_MONTHS_REG */
+#ifdef ALMDEBUG
+        printf("ALM MON_REG <-- %02x\n", value);
+#endif
+        s->alarm_tm.tm_mon = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x34: /* ALARM_YEARS_REG */
+#ifdef ALMDEBUG
+        printf("ALM YRS_REG <-- %02x\n", value);
+#endif
+        s->alarm_tm.tm_year = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x40: /* RTC_CTRL_REG */
+#ifdef ALMDEBUG
+        printf("RTC CONTROL <-- %02x\n", value);
+#endif
+        s->pm_am = (value >> 3) & 1;
+        s->auto_comp = (value >> 2) & 1;
+        s->round = (value >> 1) & 1;
+        s->running = value & 1;
+        s->status &= 0xfd;
+        s->status |= s->running << 1;
+        return;
+
+    case 0x44: /* RTC_STATUS_REG */
+#ifdef ALMDEBUG
+        printf("RTC STATUSL <-- %02x\n", value);
+#endif
+        s->status &= ~((value & 0xc0) ^ 0x80);
+        omap_rtc_interrupts_update(s);
+        return;
+
+    case 0x48: /* RTC_INTERRUPTS_REG */
+#ifdef ALMDEBUG
+        printf("RTC INTRS <-- %02x\n", value);
+#endif
+        s->interrupts = value;
+        return;
+
+    case 0x4c: /* RTC_COMP_LSB_REG */
+#ifdef ALMDEBUG
+        printf("RTC COMPLSB <-- %02x\n", value);
+#endif
+        s->comp_reg &= 0xff00;
+        s->comp_reg |= 0x00ff & value;
+        return;
+
+    case 0x50: /* RTC_COMP_MSB_REG */
+#ifdef ALMDEBUG
+        printf("RTC COMPMSB <-- %02x\n", value);
+#endif
+        s->comp_reg &= 0x00ff;
+        s->comp_reg |= 0xff00 & (value << 8);
+        return;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_rtc_ops = {
+    .read = omap_rtc_read,
+    .write = omap_rtc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_rtc_tick(void *opaque)
+{
+    struct omap_rtc_s *s = opaque;
+
+    if (s->round) {
+        /* Round to nearest full minute.  */
+        if (s->current_tm.tm_sec < 30)
+            s->ti -= s->current_tm.tm_sec;
+        else
+            s->ti += 60 - s->current_tm.tm_sec;
+
+        s->round = 0;
+    }
+
+    localtime_r(&s->ti, &s->current_tm);
+
+    if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
+        s->status |= 0x40;
+        omap_rtc_interrupts_update(s);
+    }
+
+    if (s->interrupts & 0x04)
+        switch (s->interrupts & 3) {
+        case 0:
+            s->status |= 0x04;
+            qemu_irq_pulse(s->irq);
+            break;
+        case 1:
+            if (s->current_tm.tm_sec)
+                break;
+            s->status |= 0x08;
+            qemu_irq_pulse(s->irq);
+            break;
+        case 2:
+            if (s->current_tm.tm_sec || s->current_tm.tm_min)
+                break;
+            s->status |= 0x10;
+            qemu_irq_pulse(s->irq);
+            break;
+        case 3:
+            if (s->current_tm.tm_sec ||
+                            s->current_tm.tm_min || s->current_tm.tm_hour)
+                break;
+            s->status |= 0x20;
+            qemu_irq_pulse(s->irq);
+            break;
+        }
+
+    /* Move on */
+    if (s->running)
+        s->ti ++;
+    s->tick += 1000;
+
+    /*
+     * Every full hour add a rough approximation of the compensation
+     * register to the 32kHz Timer (which drives the RTC) value. 
+     */
+    if (s->auto_comp && !s->current_tm.tm_sec && !s->current_tm.tm_min)
+        s->tick += s->comp_reg * 1000 / 32768;
+
+    qemu_mod_timer(s->clk, s->tick);
+}
+
+static void omap_rtc_reset(struct omap_rtc_s *s)
+{
+    struct tm tm;
+
+    s->interrupts = 0;
+    s->comp_reg = 0;
+    s->running = 0;
+    s->pm_am = 0;
+    s->auto_comp = 0;
+    s->round = 0;
+    s->tick = qemu_get_clock_ms(rtc_clock);
+    memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
+    s->alarm_tm.tm_mday = 0x01;
+    s->status = 1 << 7;
+    qemu_get_timedate(&tm, 0);
+    s->ti = mktimegm(&tm);
+
+    omap_rtc_alarm_update(s);
+    omap_rtc_tick(s);
+}
+
+static struct omap_rtc_s *omap_rtc_init(MemoryRegion *system_memory,
+                                        hwaddr base,
+                                        qemu_irq timerirq, qemu_irq alarmirq,
+                                        omap_clk clk)
+{
+    struct omap_rtc_s *s = (struct omap_rtc_s *)
+            g_malloc0(sizeof(struct omap_rtc_s));
+
+    s->irq = timerirq;
+    s->alarm = alarmirq;
+    s->clk = qemu_new_timer_ms(rtc_clock, omap_rtc_tick, s);
+
+    omap_rtc_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_rtc_ops, s,
+                          "omap-rtc", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    return s;
+}
+
+/* Multi-channel Buffered Serial Port interfaces */
+struct omap_mcbsp_s {
+    MemoryRegion iomem;
+    qemu_irq txirq;
+    qemu_irq rxirq;
+    qemu_irq txdrq;
+    qemu_irq rxdrq;
+
+    uint16_t spcr[2];
+    uint16_t rcr[2];
+    uint16_t xcr[2];
+    uint16_t srgr[2];
+    uint16_t mcr[2];
+    uint16_t pcr;
+    uint16_t rcer[8];
+    uint16_t xcer[8];
+    int tx_rate;
+    int rx_rate;
+    int tx_req;
+    int rx_req;
+
+    I2SCodec *codec;
+    QEMUTimer *source_timer;
+    QEMUTimer *sink_timer;
+};
+
+static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s)
+{
+    int irq;
+
+    switch ((s->spcr[0] >> 4) & 3) {                   /* RINTM */
+    case 0:
+        irq = (s->spcr[0] >> 1) & 1;                   /* RRDY */
+        break;
+    case 3:
+        irq = (s->spcr[0] >> 3) & 1;                   /* RSYNCERR */
+        break;
+    default:
+        irq = 0;
+        break;
+    }
+
+    if (irq)
+        qemu_irq_pulse(s->rxirq);
+
+    switch ((s->spcr[1] >> 4) & 3) {                   /* XINTM */
+    case 0:
+        irq = (s->spcr[1] >> 1) & 1;                   /* XRDY */
+        break;
+    case 3:
+        irq = (s->spcr[1] >> 3) & 1;                   /* XSYNCERR */
+        break;
+    default:
+        irq = 0;
+        break;
+    }
+
+    if (irq)
+        qemu_irq_pulse(s->txirq);
+}
+
+static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s)
+{
+    if ((s->spcr[0] >> 1) & 1)                         /* RRDY */
+        s->spcr[0] |= 1 << 2;                          /* RFULL */
+    s->spcr[0] |= 1 << 1;                              /* RRDY */
+    qemu_irq_raise(s->rxdrq);
+    omap_mcbsp_intr_update(s);
+}
+
+static void omap_mcbsp_source_tick(void *opaque)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+    static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
+
+    if (!s->rx_rate)
+        return;
+    if (s->rx_req)
+        printf("%s: Rx FIFO overrun\n", __FUNCTION__);
+
+    s->rx_req = s->rx_rate << bps[(s->rcr[0] >> 5) & 7];
+
+    omap_mcbsp_rx_newdata(s);
+    qemu_mod_timer(s->source_timer, qemu_get_clock_ns(vm_clock) +
+                   get_ticks_per_sec());
+}
+
+static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s)
+{
+    if (!s->codec || !s->codec->rts)
+        omap_mcbsp_source_tick(s);
+    else if (s->codec->in.len) {
+        s->rx_req = s->codec->in.len;
+        omap_mcbsp_rx_newdata(s);
+    }
+}
+
+static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s)
+{
+    qemu_del_timer(s->source_timer);
+}
+
+static void omap_mcbsp_rx_done(struct omap_mcbsp_s *s)
+{
+    s->spcr[0] &= ~(1 << 1);                           /* RRDY */
+    qemu_irq_lower(s->rxdrq);
+    omap_mcbsp_intr_update(s);
+}
+
+static void omap_mcbsp_tx_newdata(struct omap_mcbsp_s *s)
+{
+    s->spcr[1] |= 1 << 1;                              /* XRDY */
+    qemu_irq_raise(s->txdrq);
+    omap_mcbsp_intr_update(s);
+}
+
+static void omap_mcbsp_sink_tick(void *opaque)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+    static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
+
+    if (!s->tx_rate)
+        return;
+    if (s->tx_req)
+        printf("%s: Tx FIFO underrun\n", __FUNCTION__);
+
+    s->tx_req = s->tx_rate << bps[(s->xcr[0] >> 5) & 7];
+
+    omap_mcbsp_tx_newdata(s);
+    qemu_mod_timer(s->sink_timer, qemu_get_clock_ns(vm_clock) +
+                   get_ticks_per_sec());
+}
+
+static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s)
+{
+    if (!s->codec || !s->codec->cts)
+        omap_mcbsp_sink_tick(s);
+    else if (s->codec->out.size) {
+        s->tx_req = s->codec->out.size;
+        omap_mcbsp_tx_newdata(s);
+    }
+}
+
+static void omap_mcbsp_tx_done(struct omap_mcbsp_s *s)
+{
+    s->spcr[1] &= ~(1 << 1);                           /* XRDY */
+    qemu_irq_lower(s->txdrq);
+    omap_mcbsp_intr_update(s);
+    if (s->codec && s->codec->cts)
+        s->codec->tx_swallow(s->codec->opaque);
+}
+
+static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s)
+{
+    s->tx_req = 0;
+    omap_mcbsp_tx_done(s);
+    qemu_del_timer(s->sink_timer);
+}
+
+static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
+{
+    int prev_rx_rate, prev_tx_rate;
+    int rx_rate = 0, tx_rate = 0;
+    int cpu_rate = 1500000;    /* XXX */
+
+    /* TODO: check CLKSTP bit */
+    if (s->spcr[1] & (1 << 6)) {                       /* GRST */
+        if (s->spcr[0] & (1 << 0)) {                   /* RRST */
+            if ((s->srgr[1] & (1 << 13)) &&            /* CLKSM */
+                            (s->pcr & (1 << 8))) {     /* CLKRM */
+                if (~s->pcr & (1 << 7))                        /* SCLKME */
+                    rx_rate = cpu_rate /
+                            ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
+            } else
+                if (s->codec)
+                    rx_rate = s->codec->rx_rate;
+        }
+
+        if (s->spcr[1] & (1 << 0)) {                   /* XRST */
+            if ((s->srgr[1] & (1 << 13)) &&            /* CLKSM */
+                            (s->pcr & (1 << 9))) {     /* CLKXM */
+                if (~s->pcr & (1 << 7))                        /* SCLKME */
+                    tx_rate = cpu_rate /
+                            ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
+            } else
+                if (s->codec)
+                    tx_rate = s->codec->tx_rate;
+        }
+    }
+    prev_tx_rate = s->tx_rate;
+    prev_rx_rate = s->rx_rate;
+    s->tx_rate = tx_rate;
+    s->rx_rate = rx_rate;
+
+    if (s->codec)
+        s->codec->set_rate(s->codec->opaque, rx_rate, tx_rate);
+
+    if (!prev_tx_rate && tx_rate)
+        omap_mcbsp_tx_start(s);
+    else if (s->tx_rate && !tx_rate)
+        omap_mcbsp_tx_stop(s);
+
+    if (!prev_rx_rate && rx_rate)
+        omap_mcbsp_rx_start(s);
+    else if (prev_tx_rate && !tx_rate)
+        omap_mcbsp_rx_stop(s);
+}
+
+static uint64_t omap_mcbsp_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+    uint16_t ret;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00: /* DRR2 */
+        if (((s->rcr[0] >> 5) & 7) < 3)                        /* RWDLEN1 */
+            return 0x0000;
+        /* Fall through.  */
+    case 0x02: /* DRR1 */
+        if (s->rx_req < 2) {
+            printf("%s: Rx FIFO underrun\n", __FUNCTION__);
+            omap_mcbsp_rx_done(s);
+        } else {
+            s->tx_req -= 2;
+            if (s->codec && s->codec->in.len >= 2) {
+                ret = s->codec->in.fifo[s->codec->in.start ++] << 8;
+                ret |= s->codec->in.fifo[s->codec->in.start ++];
+                s->codec->in.len -= 2;
+            } else
+                ret = 0x0000;
+            if (!s->tx_req)
+                omap_mcbsp_rx_done(s);
+            return ret;
+        }
+        return 0x0000;
+
+    case 0x04: /* DXR2 */
+    case 0x06: /* DXR1 */
+        return 0x0000;
+
+    case 0x08: /* SPCR2 */
+        return s->spcr[1];
+    case 0x0a: /* SPCR1 */
+        return s->spcr[0];
+    case 0x0c: /* RCR2 */
+        return s->rcr[1];
+    case 0x0e: /* RCR1 */
+        return s->rcr[0];
+    case 0x10: /* XCR2 */
+        return s->xcr[1];
+    case 0x12: /* XCR1 */
+        return s->xcr[0];
+    case 0x14: /* SRGR2 */
+        return s->srgr[1];
+    case 0x16: /* SRGR1 */
+        return s->srgr[0];
+    case 0x18: /* MCR2 */
+        return s->mcr[1];
+    case 0x1a: /* MCR1 */
+        return s->mcr[0];
+    case 0x1c: /* RCERA */
+        return s->rcer[0];
+    case 0x1e: /* RCERB */
+        return s->rcer[1];
+    case 0x20: /* XCERA */
+        return s->xcer[0];
+    case 0x22: /* XCERB */
+        return s->xcer[1];
+    case 0x24: /* PCR0 */
+        return s->pcr;
+    case 0x26: /* RCERC */
+        return s->rcer[2];
+    case 0x28: /* RCERD */
+        return s->rcer[3];
+    case 0x2a: /* XCERC */
+        return s->xcer[2];
+    case 0x2c: /* XCERD */
+        return s->xcer[3];
+    case 0x2e: /* RCERE */
+        return s->rcer[4];
+    case 0x30: /* RCERF */
+        return s->rcer[5];
+    case 0x32: /* XCERE */
+        return s->xcer[4];
+    case 0x34: /* XCERF */
+        return s->xcer[5];
+    case 0x36: /* RCERG */
+        return s->rcer[6];
+    case 0x38: /* RCERH */
+        return s->rcer[7];
+    case 0x3a: /* XCERG */
+        return s->xcer[6];
+    case 0x3c: /* XCERH */
+        return s->xcer[7];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mcbsp_writeh(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    switch (offset) {
+    case 0x00: /* DRR2 */
+    case 0x02: /* DRR1 */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x04: /* DXR2 */
+        if (((s->xcr[0] >> 5) & 7) < 3)                        /* XWDLEN1 */
+            return;
+        /* Fall through.  */
+    case 0x06: /* DXR1 */
+        if (s->tx_req > 1) {
+            s->tx_req -= 2;
+            if (s->codec && s->codec->cts) {
+                s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff;
+                s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff;
+            }
+            if (s->tx_req < 2)
+                omap_mcbsp_tx_done(s);
+        } else
+            printf("%s: Tx FIFO overrun\n", __FUNCTION__);
+        return;
+
+    case 0x08: /* SPCR2 */
+        s->spcr[1] &= 0x0002;
+        s->spcr[1] |= 0x03f9 & value;
+        s->spcr[1] |= 0x0004 & (value << 2);           /* XEMPTY := XRST */
+        if (~value & 1)                                        /* XRST */
+            s->spcr[1] &= ~6;
+        omap_mcbsp_req_update(s);
+        return;
+    case 0x0a: /* SPCR1 */
+        s->spcr[0] &= 0x0006;
+        s->spcr[0] |= 0xf8f9 & value;
+        if (value & (1 << 15))                         /* DLB */
+            printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__);
+        if (~value & 1) {                              /* RRST */
+            s->spcr[0] &= ~6;
+            s->rx_req = 0;
+            omap_mcbsp_rx_done(s);
+        }
+        omap_mcbsp_req_update(s);
+        return;
+
+    case 0x0c: /* RCR2 */
+        s->rcr[1] = value & 0xffff;
+        return;
+    case 0x0e: /* RCR1 */
+        s->rcr[0] = value & 0x7fe0;
+        return;
+    case 0x10: /* XCR2 */
+        s->xcr[1] = value & 0xffff;
+        return;
+    case 0x12: /* XCR1 */
+        s->xcr[0] = value & 0x7fe0;
+        return;
+    case 0x14: /* SRGR2 */
+        s->srgr[1] = value & 0xffff;
+        omap_mcbsp_req_update(s);
+        return;
+    case 0x16: /* SRGR1 */
+        s->srgr[0] = value & 0xffff;
+        omap_mcbsp_req_update(s);
+        return;
+    case 0x18: /* MCR2 */
+        s->mcr[1] = value & 0x03e3;
+        if (value & 3)                                 /* XMCM */
+            printf("%s: Tx channel selection mode enable attempt\n",
+                            __FUNCTION__);
+        return;
+    case 0x1a: /* MCR1 */
+        s->mcr[0] = value & 0x03e1;
+        if (value & 1)                                 /* RMCM */
+            printf("%s: Rx channel selection mode enable attempt\n",
+                            __FUNCTION__);
+        return;
+    case 0x1c: /* RCERA */
+        s->rcer[0] = value & 0xffff;
+        return;
+    case 0x1e: /* RCERB */
+        s->rcer[1] = value & 0xffff;
+        return;
+    case 0x20: /* XCERA */
+        s->xcer[0] = value & 0xffff;
+        return;
+    case 0x22: /* XCERB */
+        s->xcer[1] = value & 0xffff;
+        return;
+    case 0x24: /* PCR0 */
+        s->pcr = value & 0x7faf;
+        return;
+    case 0x26: /* RCERC */
+        s->rcer[2] = value & 0xffff;
+        return;
+    case 0x28: /* RCERD */
+        s->rcer[3] = value & 0xffff;
+        return;
+    case 0x2a: /* XCERC */
+        s->xcer[2] = value & 0xffff;
+        return;
+    case 0x2c: /* XCERD */
+        s->xcer[3] = value & 0xffff;
+        return;
+    case 0x2e: /* RCERE */
+        s->rcer[4] = value & 0xffff;
+        return;
+    case 0x30: /* RCERF */
+        s->rcer[5] = value & 0xffff;
+        return;
+    case 0x32: /* XCERE */
+        s->xcer[4] = value & 0xffff;
+        return;
+    case 0x34: /* XCERF */
+        s->xcer[5] = value & 0xffff;
+        return;
+    case 0x36: /* RCERG */
+        s->rcer[6] = value & 0xffff;
+        return;
+    case 0x38: /* RCERH */
+        s->rcer[7] = value & 0xffff;
+        return;
+    case 0x3a: /* XCERG */
+        s->xcer[6] = value & 0xffff;
+        return;
+    case 0x3c: /* XCERH */
+        s->xcer[7] = value & 0xffff;
+        return;
+    }
+
+    OMAP_BAD_REG(addr);
+}
+
+static void omap_mcbsp_writew(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (offset == 0x04) {                              /* DXR */
+        if (((s->xcr[0] >> 5) & 7) < 3)                        /* XWDLEN1 */
+            return;
+        if (s->tx_req > 3) {
+            s->tx_req -= 4;
+            if (s->codec && s->codec->cts) {
+                s->codec->out.fifo[s->codec->out.len ++] =
+                        (value >> 24) & 0xff;
+                s->codec->out.fifo[s->codec->out.len ++] =
+                        (value >> 16) & 0xff;
+                s->codec->out.fifo[s->codec->out.len ++] =
+                        (value >> 8) & 0xff;
+                s->codec->out.fifo[s->codec->out.len ++] =
+                        (value >> 0) & 0xff;
+            }
+            if (s->tx_req < 4)
+                omap_mcbsp_tx_done(s);
+        } else
+            printf("%s: Tx FIFO overrun\n", __FUNCTION__);
+        return;
+    }
+
+    omap_badwidth_write16(opaque, addr, value);
+}
+
+static void omap_mcbsp_write(void *opaque, hwaddr addr,
+                             uint64_t value, unsigned size)
+{
+    switch (size) {
+    case 2: return omap_mcbsp_writeh(opaque, addr, value);
+    case 4: return omap_mcbsp_writew(opaque, addr, value);
+    default: return omap_badwidth_write16(opaque, addr, value);
+    }
+}
+
+static const MemoryRegionOps omap_mcbsp_ops = {
+    .read = omap_mcbsp_read,
+    .write = omap_mcbsp_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_mcbsp_reset(struct omap_mcbsp_s *s)
+{
+    memset(&s->spcr, 0, sizeof(s->spcr));
+    memset(&s->rcr, 0, sizeof(s->rcr));
+    memset(&s->xcr, 0, sizeof(s->xcr));
+    s->srgr[0] = 0x0001;
+    s->srgr[1] = 0x2000;
+    memset(&s->mcr, 0, sizeof(s->mcr));
+    memset(&s->pcr, 0, sizeof(s->pcr));
+    memset(&s->rcer, 0, sizeof(s->rcer));
+    memset(&s->xcer, 0, sizeof(s->xcer));
+    s->tx_req = 0;
+    s->rx_req = 0;
+    s->tx_rate = 0;
+    s->rx_rate = 0;
+    qemu_del_timer(s->source_timer);
+    qemu_del_timer(s->sink_timer);
+}
+
+static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory,
+                                            hwaddr base,
+                                            qemu_irq txirq, qemu_irq rxirq,
+                                            qemu_irq *dma, omap_clk clk)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
+            g_malloc0(sizeof(struct omap_mcbsp_s));
+
+    s->txirq = txirq;
+    s->rxirq = rxirq;
+    s->txdrq = dma[0];
+    s->rxdrq = dma[1];
+    s->sink_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_sink_tick, s);
+    s->source_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_source_tick, s);
+    omap_mcbsp_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_mcbsp_ops, s, "omap-mcbsp", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    return s;
+}
+
+static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+
+    if (s->rx_rate) {
+        s->rx_req = s->codec->in.len;
+        omap_mcbsp_rx_newdata(s);
+    }
+}
+
+static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+
+    if (s->tx_rate) {
+        s->tx_req = s->codec->out.size;
+        omap_mcbsp_tx_newdata(s);
+    }
+}
+
+void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave)
+{
+    s->codec = slave;
+    slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
+    slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
+}
+
+/* LED Pulse Generators */
+struct omap_lpg_s {
+    MemoryRegion iomem;
+    QEMUTimer *tm;
+
+    uint8_t control;
+    uint8_t power;
+    int64_t on;
+    int64_t period;
+    int clk;
+    int cycle;
+};
+
+static void omap_lpg_tick(void *opaque)
+{
+    struct omap_lpg_s *s = opaque;
+
+    if (s->cycle)
+        qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->period - s->on);
+    else
+        qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->on);
+
+    s->cycle = !s->cycle;
+    printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off");
+}
+
+static void omap_lpg_update(struct omap_lpg_s *s)
+{
+    int64_t on, period = 1, ticks = 1000;
+    static const int per[8] = { 1, 2, 4, 8, 12, 16, 20, 24 };
+
+    if (~s->control & (1 << 6))                                        /* LPGRES */
+        on = 0;
+    else if (s->control & (1 << 7))                            /* PERM_ON */
+        on = period;
+    else {
+        period = muldiv64(ticks, per[s->control & 7],          /* PERCTRL */
+                        256 / 32);
+        on = (s->clk && s->power) ? muldiv64(ticks,
+                        per[(s->control >> 3) & 7], 256) : 0;  /* ONCTRL */
+    }
+
+    qemu_del_timer(s->tm);
+    if (on == period && s->on < s->period)
+        printf("%s: LED is on\n", __FUNCTION__);
+    else if (on == 0 && s->on)
+        printf("%s: LED is off\n", __FUNCTION__);
+    else if (on && (on != s->on || period != s->period)) {
+        s->cycle = 0;
+        s->on = on;
+        s->period = period;
+        omap_lpg_tick(s);
+        return;
+    }
+
+    s->on = on;
+    s->period = period;
+}
+
+static void omap_lpg_reset(struct omap_lpg_s *s)
+{
+    s->control = 0x00;
+    s->power = 0x00;
+    s->clk = 1;
+    omap_lpg_update(s);
+}
+
+static uint64_t omap_lpg_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_read8(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00: /* LCR */
+        return s->control;
+
+    case 0x04: /* PMR */
+        return s->power;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_lpg_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00: /* LCR */
+        if (~value & (1 << 6))                                 /* LPGRES */
+            omap_lpg_reset(s);
+        s->control = value & 0xff;
+        omap_lpg_update(s);
+        return;
+
+    case 0x04: /* PMR */
+        s->power = value & 0x01;
+        omap_lpg_update(s);
+        return;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_lpg_ops = {
+    .read = omap_lpg_read,
+    .write = omap_lpg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_lpg_clk_update(void *opaque, int line, int on)
+{
+    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
+
+    s->clk = on;
+    omap_lpg_update(s);
+}
+
+static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory,
+                                        hwaddr base, omap_clk clk)
+{
+    struct omap_lpg_s *s = (struct omap_lpg_s *)
+            g_malloc0(sizeof(struct omap_lpg_s));
+
+    s->tm = qemu_new_timer_ms(vm_clock, omap_lpg_tick, s);
+
+    omap_lpg_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_lpg_ops, s, "omap-lpg", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
+
+    return s;
+}
+
+/* MPUI Peripheral Bridge configuration */
+static uint64_t omap_mpui_io_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    if (addr == OMAP_MPUI_BASE)        /* CMR */
+        return 0xfe4d;
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mpui_io_write(void *opaque, hwaddr addr,
+                               uint64_t value, unsigned size)
+{
+    /* FIXME: infinite loop */
+    omap_badwidth_write16(opaque, addr, value);
+}
+
+static const MemoryRegionOps omap_mpui_io_ops = {
+    .read = omap_mpui_io_read,
+    .write = omap_mpui_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_setup_mpui_io(MemoryRegion *system_memory,
+                               struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->mpui_io_iomem, &omap_mpui_io_ops, mpu,
+                          "omap-mpui-io", 0x7fff);
+    memory_region_add_subregion(system_memory, OMAP_MPUI_BASE,
+                                &mpu->mpui_io_iomem);
+}
+
+/* General chip reset */
+static void omap1_mpu_reset(void *opaque)
+{
+    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
+
+    omap_dma_reset(mpu->dma);
+    omap_mpu_timer_reset(mpu->timer[0]);
+    omap_mpu_timer_reset(mpu->timer[1]);
+    omap_mpu_timer_reset(mpu->timer[2]);
+    omap_wd_timer_reset(mpu->wdt);
+    omap_os_timer_reset(mpu->os_timer);
+    omap_lcdc_reset(mpu->lcd);
+    omap_ulpd_pm_reset(mpu);
+    omap_pin_cfg_reset(mpu);
+    omap_mpui_reset(mpu);
+    omap_tipb_bridge_reset(mpu->private_tipb);
+    omap_tipb_bridge_reset(mpu->public_tipb);
+    omap_dpll_reset(mpu->dpll[0]);
+    omap_dpll_reset(mpu->dpll[1]);
+    omap_dpll_reset(mpu->dpll[2]);
+    omap_uart_reset(mpu->uart[0]);
+    omap_uart_reset(mpu->uart[1]);
+    omap_uart_reset(mpu->uart[2]);
+    omap_mmc_reset(mpu->mmc);
+    omap_mpuio_reset(mpu->mpuio);
+    omap_uwire_reset(mpu->microwire);
+    omap_pwl_reset(mpu->pwl);
+    omap_pwt_reset(mpu->pwt);
+    omap_rtc_reset(mpu->rtc);
+    omap_mcbsp_reset(mpu->mcbsp1);
+    omap_mcbsp_reset(mpu->mcbsp2);
+    omap_mcbsp_reset(mpu->mcbsp3);
+    omap_lpg_reset(mpu->led[0]);
+    omap_lpg_reset(mpu->led[1]);
+    omap_clkm_reset(mpu);
+    cpu_reset(CPU(mpu->cpu));
+}
+
+static const struct omap_map_s {
+    hwaddr phys_dsp;
+    hwaddr phys_mpu;
+    uint32_t size;
+    const char *name;
+} omap15xx_dsp_mm[] = {
+    /* Strobe 0 */
+    { 0xe1010000, 0xfffb0000, 0x800, "UART1 BT" },             /* CS0 */
+    { 0xe1010800, 0xfffb0800, 0x800, "UART2 COM" },            /* CS1 */
+    { 0xe1011800, 0xfffb1800, 0x800, "McBSP1 audio" },         /* CS3 */
+    { 0xe1012000, 0xfffb2000, 0x800, "MCSI2 communication" },  /* CS4 */
+    { 0xe1012800, 0xfffb2800, 0x800, "MCSI1 BT u-Law" },       /* CS5 */
+    { 0xe1013000, 0xfffb3000, 0x800, "uWire" },                        /* CS6 */
+    { 0xe1013800, 0xfffb3800, 0x800, "I^2C" },                 /* CS7 */
+    { 0xe1014000, 0xfffb4000, 0x800, "USB W2FC" },             /* CS8 */
+    { 0xe1014800, 0xfffb4800, 0x800, "RTC" },                  /* CS9 */
+    { 0xe1015000, 0xfffb5000, 0x800, "MPUIO" },                        /* CS10 */
+    { 0xe1015800, 0xfffb5800, 0x800, "PWL" },                  /* CS11 */
+    { 0xe1016000, 0xfffb6000, 0x800, "PWT" },                  /* CS12 */
+    { 0xe1017000, 0xfffb7000, 0x800, "McBSP3" },               /* CS14 */
+    { 0xe1017800, 0xfffb7800, 0x800, "MMC" },                  /* CS15 */
+    { 0xe1019000, 0xfffb9000, 0x800, "32-kHz timer" },         /* CS18 */
+    { 0xe1019800, 0xfffb9800, 0x800, "UART3" },                        /* CS19 */
+    { 0xe101c800, 0xfffbc800, 0x800, "TIPB switches" },                /* CS25 */
+    /* Strobe 1 */
+    { 0xe101e000, 0xfffce000, 0x800, "GPIOs" },                        /* CS28 */
+
+    { 0 }
+};
+
+static void omap_setup_dsp_mapping(MemoryRegion *system_memory,
+                                   const struct omap_map_s *map)
+{
+    MemoryRegion *io;
+
+    for (; map->phys_dsp; map ++) {
+        io = g_new(MemoryRegion, 1);
+        memory_region_init_alias(io, map->name,
+                                 system_memory, map->phys_mpu, map->size);
+        memory_region_add_subregion(system_memory, map->phys_dsp, io);
+    }
+}
+
+void omap_mpu_wakeup(void *opaque, int irq, int req)
+{
+    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
+
+    if (mpu->cpu->env.halted) {
+        cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
+    }
+}
+
+static const struct dma_irq_map omap1_dma_irq_map[] = {
+    { 0, OMAP_INT_DMA_CH0_6 },
+    { 0, OMAP_INT_DMA_CH1_7 },
+    { 0, OMAP_INT_DMA_CH2_8 },
+    { 0, OMAP_INT_DMA_CH3 },
+    { 0, OMAP_INT_DMA_CH4 },
+    { 0, OMAP_INT_DMA_CH5 },
+    { 1, OMAP_INT_1610_DMA_CH6 },
+    { 1, OMAP_INT_1610_DMA_CH7 },
+    { 1, OMAP_INT_1610_DMA_CH8 },
+    { 1, OMAP_INT_1610_DMA_CH9 },
+    { 1, OMAP_INT_1610_DMA_CH10 },
+    { 1, OMAP_INT_1610_DMA_CH11 },
+    { 1, OMAP_INT_1610_DMA_CH12 },
+    { 1, OMAP_INT_1610_DMA_CH13 },
+    { 1, OMAP_INT_1610_DMA_CH14 },
+    { 1, OMAP_INT_1610_DMA_CH15 }
+};
+
+/* DMA ports for OMAP1 */
+static int omap_validate_emiff_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(OMAP_EMIFF_BASE, s->sdram_size, addr);
+}
+
+static int omap_validate_emifs_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(OMAP_EMIFS_BASE, OMAP_EMIFF_BASE - OMAP_EMIFS_BASE,
+                             addr);
+}
+
+static int omap_validate_imif_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(OMAP_IMIF_BASE, s->sram_size, addr);
+}
+
+static int omap_validate_tipb_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(0xfffb0000, 0xffff0000 - 0xfffb0000, addr);
+}
+
+static int omap_validate_local_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(OMAP_LOCALBUS_BASE, 0x1000000, addr);
+}
+
+static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(0xe1010000, 0xe1020004 - 0xe1010000, addr);
+}
+
+struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
+                unsigned long sdram_size,
+                const char *core)
+{
+    int i;
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
+            g_malloc0(sizeof(struct omap_mpu_state_s));
+    qemu_irq *cpu_irq;
+    qemu_irq dma_irqs[6];
+    DriveInfo *dinfo;
+    SysBusDevice *busdev;
+
+    if (!core)
+        core = "ti925t";
+
+    /* Core */
+    s->mpu_model = omap310;
+    s->cpu = cpu_arm_init(core);
+    if (s->cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    s->sdram_size = sdram_size;
+    s->sram_size = OMAP15XX_SRAM_SIZE;
+
+    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
+
+    /* Clocks */
+    omap_clk_init(s);
+
+    /* Memory-mapped stuff */
+    memory_region_init_ram(&s->emiff_ram, "omap1.dram", s->sdram_size);
+    vmstate_register_ram_global(&s->emiff_ram);
+    memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram);
+    memory_region_init_ram(&s->imif_ram, "omap1.sram", s->sram_size);
+    vmstate_register_ram_global(&s->imif_ram);
+    memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram);
+
+    omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s);
+
+    cpu_irq = arm_pic_init_cpu(s->cpu);
+    s->ih[0] = qdev_create(NULL, "omap-intc");
+    qdev_prop_set_uint32(s->ih[0], "size", 0x100);
+    qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck"));
+    qdev_init_nofail(s->ih[0]);
+    busdev = SYS_BUS_DEVICE(s->ih[0]);
+    sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
+    sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
+    sysbus_mmio_map(busdev, 0, 0xfffecb00);
+    s->ih[1] = qdev_create(NULL, "omap-intc");
+    qdev_prop_set_uint32(s->ih[1], "size", 0x800);
+    qdev_prop_set_ptr(s->ih[1], "clk", omap_findclk(s, "arminth_ck"));
+    qdev_init_nofail(s->ih[1]);
+    busdev = SYS_BUS_DEVICE(s->ih[1]);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_15XX_IH2_IRQ));
+    /* The second interrupt controller's FIQ output is not wired up */
+    sysbus_mmio_map(busdev, 0, 0xfffe0000);
+
+    for (i = 0; i < 6; i++) {
+        dma_irqs[i] = qdev_get_gpio_in(s->ih[omap1_dma_irq_map[i].ih],
+                                       omap1_dma_irq_map[i].intr);
+    }
+    s->dma = omap_dma_init(0xfffed800, dma_irqs, system_memory,
+                           qdev_get_gpio_in(s->ih[0], OMAP_INT_DMA_LCD),
+                           s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
+
+    s->port[emiff    ].addr_valid = omap_validate_emiff_addr;
+    s->port[emifs    ].addr_valid = omap_validate_emifs_addr;
+    s->port[imif     ].addr_valid = omap_validate_imif_addr;
+    s->port[tipb     ].addr_valid = omap_validate_tipb_addr;
+    s->port[local    ].addr_valid = omap_validate_local_addr;
+    s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr;
+
+    /* Register SDRAM and SRAM DMA ports for fast transfers.  */
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->emiff_ram),
+                         OMAP_EMIFF_BASE, s->sdram_size);
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->imif_ram),
+                         OMAP_IMIF_BASE, s->sram_size);
+
+    s->timer[0] = omap_mpu_timer_init(system_memory, 0xfffec500,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER1),
+                    omap_findclk(s, "mputim_ck"));
+    s->timer[1] = omap_mpu_timer_init(system_memory, 0xfffec600,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER2),
+                    omap_findclk(s, "mputim_ck"));
+    s->timer[2] = omap_mpu_timer_init(system_memory, 0xfffec700,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER3),
+                    omap_findclk(s, "mputim_ck"));
+
+    s->wdt = omap_wd_timer_init(system_memory, 0xfffec800,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_WD_TIMER),
+                    omap_findclk(s, "armwdt_ck"));
+
+    s->os_timer = omap_os_timer_init(system_memory, 0xfffb9000,
+                    qdev_get_gpio_in(s->ih[1], OMAP_INT_OS_TIMER),
+                    omap_findclk(s, "clk32-kHz"));
+
+    s->lcd = omap_lcdc_init(system_memory, 0xfffec000,
+                            qdev_get_gpio_in(s->ih[0], OMAP_INT_LCD_CTRL),
+                            omap_dma_get_lcdch(s->dma),
+                            omap_findclk(s, "lcd_ck"));
+
+    omap_ulpd_pm_init(system_memory, 0xfffe0800, s);
+    omap_pin_cfg_init(system_memory, 0xfffe1000, s);
+    omap_id_init(system_memory, s);
+
+    omap_mpui_init(system_memory, 0xfffec900, s);
+
+    s->private_tipb = omap_tipb_bridge_init(system_memory, 0xfffeca00,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_BRIDGE_PRIV),
+                    omap_findclk(s, "tipb_ck"));
+    s->public_tipb = omap_tipb_bridge_init(system_memory, 0xfffed300,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_BRIDGE_PUB),
+                    omap_findclk(s, "tipb_ck"));
+
+    omap_tcmi_init(system_memory, 0xfffecc00, s);
+
+    s->uart[0] = omap_uart_init(0xfffb0000,
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_UART1),
+                    omap_findclk(s, "uart1_ck"),
+                    omap_findclk(s, "uart1_ck"),
+                    s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX],
+                    "uart1",
+                    serial_hds[0]);
+    s->uart[1] = omap_uart_init(0xfffb0800,
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_UART2),
+                    omap_findclk(s, "uart2_ck"),
+                    omap_findclk(s, "uart2_ck"),
+                    s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX],
+                    "uart2",
+                    serial_hds[0] ? serial_hds[1] : NULL);
+    s->uart[2] = omap_uart_init(0xfffb9800,
+                                qdev_get_gpio_in(s->ih[0], OMAP_INT_UART3),
+                    omap_findclk(s, "uart3_ck"),
+                    omap_findclk(s, "uart3_ck"),
+                    s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX],
+                    "uart3",
+                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
+
+    s->dpll[0] = omap_dpll_init(system_memory, 0xfffecf00,
+                                omap_findclk(s, "dpll1"));
+    s->dpll[1] = omap_dpll_init(system_memory, 0xfffed000,
+                                omap_findclk(s, "dpll2"));
+    s->dpll[2] = omap_dpll_init(system_memory, 0xfffed100,
+                                omap_findclk(s, "dpll3"));
+
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "qemu: missing SecureDigital device\n");
+        exit(1);
+    }
+    s->mmc = omap_mmc_init(0xfffb7800, system_memory, dinfo->bdrv,
+                           qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
+                           &s->drq[OMAP_DMA_MMC_TX],
+                    omap_findclk(s, "mmc_ck"));
+
+    s->mpuio = omap_mpuio_init(system_memory, 0xfffb5000,
+                               qdev_get_gpio_in(s->ih[1], OMAP_INT_KEYBOARD),
+                               qdev_get_gpio_in(s->ih[1], OMAP_INT_MPUIO),
+                               s->wakeup, omap_findclk(s, "clk32-kHz"));
+
+    s->gpio = qdev_create(NULL, "omap-gpio");
+    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
+    qdev_prop_set_ptr(s->gpio, "clk", omap_findclk(s, "arm_gpio_ck"));
+    qdev_init_nofail(s->gpio);
+    sysbus_connect_irq(SYS_BUS_DEVICE(s->gpio), 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_GPIO_BANK1));
+    sysbus_mmio_map(SYS_BUS_DEVICE(s->gpio), 0, 0xfffce000);
+
+    s->microwire = omap_uwire_init(system_memory, 0xfffb3000,
+                                   qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireTX),
+                                   qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireRX),
+                    s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
+
+    s->pwl = omap_pwl_init(system_memory, 0xfffb5800,
+                           omap_findclk(s, "armxor_ck"));
+    s->pwt = omap_pwt_init(system_memory, 0xfffb6000,
+                           omap_findclk(s, "armxor_ck"));
+
+    s->i2c[0] = qdev_create(NULL, "omap_i2c");
+    qdev_prop_set_uint8(s->i2c[0], "revision", 0x11);
+    qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "mpuper_ck"));
+    qdev_init_nofail(s->i2c[0]);
+    busdev = SYS_BUS_DEVICE(s->i2c[0]);
+    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C));
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_I2C_TX]);
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_I2C_RX]);
+    sysbus_mmio_map(busdev, 0, 0xfffb3800);
+
+    s->rtc = omap_rtc_init(system_memory, 0xfffb4800,
+                           qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_TIMER),
+                           qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_ALARM),
+                    omap_findclk(s, "clk32-kHz"));
+
+    s->mcbsp1 = omap_mcbsp_init(system_memory, 0xfffb1800,
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP1TX),
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP1RX),
+                    &s->drq[OMAP_DMA_MCBSP1_TX], omap_findclk(s, "dspxor_ck"));
+    s->mcbsp2 = omap_mcbsp_init(system_memory, 0xfffb1000,
+                                qdev_get_gpio_in(s->ih[0],
+                                                 OMAP_INT_310_McBSP2_TX),
+                                qdev_get_gpio_in(s->ih[0],
+                                                 OMAP_INT_310_McBSP2_RX),
+                    &s->drq[OMAP_DMA_MCBSP2_TX], omap_findclk(s, "mpuper_ck"));
+    s->mcbsp3 = omap_mcbsp_init(system_memory, 0xfffb7000,
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP3TX),
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP3RX),
+                    &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck"));
+
+    s->led[0] = omap_lpg_init(system_memory,
+                              0xfffbd000, omap_findclk(s, "clk32-kHz"));
+    s->led[1] = omap_lpg_init(system_memory,
+                              0xfffbd800, omap_findclk(s, "clk32-kHz"));
+
+    /* Register mappings not currenlty implemented:
+     * MCSI2 Comm      fffb2000 - fffb27ff (not mapped on OMAP310)
+     * MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310)
+     * USB W2FC                fffb4000 - fffb47ff
+     * Camera Interface        fffb6800 - fffb6fff
+     * USB Host                fffba000 - fffba7ff
+     * FAC             fffba800 - fffbafff
+     * HDQ/1-Wire      fffbc000 - fffbc7ff
+     * TIPB switches   fffbc800 - fffbcfff
+     * Mailbox         fffcf000 - fffcf7ff
+     * Local bus IF    fffec100 - fffec1ff
+     * Local bus MMU   fffec200 - fffec2ff
+     * DSP MMU         fffed200 - fffed2ff
+     */
+
+    omap_setup_dsp_mapping(system_memory, omap15xx_dsp_mm);
+    omap_setup_mpui_io(system_memory, s);
+
+    qemu_register_reset(omap1_mpu_reset, s);
+
+    return s;
+}
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
new file mode 100644 (file)
index 0000000..0a2cd7b
--- /dev/null
@@ -0,0 +1,2684 @@
+/*
+ * TI OMAP processors emulation.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * 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 "sysemu/blockdev.h"
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
+#include "hw/omap.h"
+#include "sysemu/sysemu.h"
+#include "qemu/timer.h"
+#include "char/char.h"
+#include "hw/flash.h"
+#include "hw/soc_dma.h"
+#include "hw/sysbus.h"
+#include "audio/audio.h"
+
+/* Enhanced Audio Controller (CODEC only) */
+struct omap_eac_s {
+    qemu_irq irq;
+    MemoryRegion iomem;
+
+    uint16_t sysconfig;
+    uint8_t config[4];
+    uint8_t control;
+    uint8_t address;
+    uint16_t data;
+    uint8_t vtol;
+    uint8_t vtsl;
+    uint16_t mixer;
+    uint16_t gain[4];
+    uint8_t att;
+    uint16_t max[7];
+
+    struct {
+        qemu_irq txdrq;
+        qemu_irq rxdrq;
+        uint32_t (*txrx)(void *opaque, uint32_t, int);
+        void *opaque;
+
+#define EAC_BUF_LEN 1024
+        uint32_t rxbuf[EAC_BUF_LEN];
+        int rxoff;
+        int rxlen;
+        int rxavail;
+        uint32_t txbuf[EAC_BUF_LEN];
+        int txlen;
+        int txavail;
+
+        int enable;
+        int rate;
+
+        uint16_t config[4];
+
+        /* These need to be moved to the actual codec */
+        QEMUSoundCard card;
+        SWVoiceIn *in_voice;
+        SWVoiceOut *out_voice;
+        int hw_enable;
+    } codec;
+
+    struct {
+        uint8_t control;
+        uint16_t config;
+    } modem, bt;
+};
+
+static inline void omap_eac_interrupt_update(struct omap_eac_s *s)
+{
+    qemu_set_irq(s->irq, (s->codec.config[1] >> 14) & 1);      /* AURDI */
+}
+
+static inline void omap_eac_in_dmarequest_update(struct omap_eac_s *s)
+{
+    qemu_set_irq(s->codec.rxdrq, (s->codec.rxavail || s->codec.rxlen) &&
+                    ((s->codec.config[1] >> 12) & 1));         /* DMAREN */
+}
+
+static inline void omap_eac_out_dmarequest_update(struct omap_eac_s *s)
+{
+    qemu_set_irq(s->codec.txdrq, s->codec.txlen < s->codec.txavail &&
+                    ((s->codec.config[1] >> 11) & 1));         /* DMAWEN */
+}
+
+static inline void omap_eac_in_refill(struct omap_eac_s *s)
+{
+    int left = MIN(EAC_BUF_LEN - s->codec.rxlen, s->codec.rxavail) << 2;
+    int start = ((s->codec.rxoff + s->codec.rxlen) & (EAC_BUF_LEN - 1)) << 2;
+    int leftwrap = MIN(left, (EAC_BUF_LEN << 2) - start);
+    int recv = 1;
+    uint8_t *buf = (uint8_t *) s->codec.rxbuf + start;
+
+    left -= leftwrap;
+    start = 0;
+    while (leftwrap && (recv = AUD_read(s->codec.in_voice, buf + start,
+                                    leftwrap)) > 0) {  /* Be defensive */
+        start += recv;
+        leftwrap -= recv;
+    }
+    if (recv <= 0)
+        s->codec.rxavail = 0;
+    else
+        s->codec.rxavail -= start >> 2;
+    s->codec.rxlen += start >> 2;
+
+    if (recv > 0 && left > 0) {
+        start = 0;
+        while (left && (recv = AUD_read(s->codec.in_voice,
+                                        (uint8_t *) s->codec.rxbuf + start,
+                                        left)) > 0) {  /* Be defensive */
+            start += recv;
+            left -= recv;
+        }
+        if (recv <= 0)
+            s->codec.rxavail = 0;
+        else
+            s->codec.rxavail -= start >> 2;
+        s->codec.rxlen += start >> 2;
+    }
+}
+
+static inline void omap_eac_out_empty(struct omap_eac_s *s)
+{
+    int left = s->codec.txlen << 2;
+    int start = 0;
+    int sent = 1;
+
+    while (left && (sent = AUD_write(s->codec.out_voice,
+                                    (uint8_t *) s->codec.txbuf + start,
+                                    left)) > 0) {      /* Be defensive */
+        start += sent;
+        left -= sent;
+    }
+
+    if (!sent) {
+        s->codec.txavail = 0;
+        omap_eac_out_dmarequest_update(s);
+    }
+
+    if (start)
+        s->codec.txlen = 0;
+}
+
+static void omap_eac_in_cb(void *opaque, int avail_b)
+{
+    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
+
+    s->codec.rxavail = avail_b >> 2;
+    omap_eac_in_refill(s);
+    /* TODO: possibly discard current buffer if overrun */
+    omap_eac_in_dmarequest_update(s);
+}
+
+static void omap_eac_out_cb(void *opaque, int free_b)
+{
+    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
+
+    s->codec.txavail = free_b >> 2;
+    if (s->codec.txlen)
+        omap_eac_out_empty(s);
+    else
+        omap_eac_out_dmarequest_update(s);
+}
+
+static void omap_eac_enable_update(struct omap_eac_s *s)
+{
+    s->codec.enable = !(s->codec.config[1] & 1) &&             /* EACPWD */
+            (s->codec.config[1] & 2) &&                                /* AUDEN */
+            s->codec.hw_enable;
+}
+
+static const int omap_eac_fsint[4] = {
+    8000,
+    11025,
+    22050,
+    44100,
+};
+
+static const int omap_eac_fsint2[8] = {
+    8000,
+    11025,
+    22050,
+    44100,
+    48000,
+    0, 0, 0,
+};
+
+static const int omap_eac_fsint3[16] = {
+    8000,
+    11025,
+    16000,
+    22050,
+    24000,
+    32000,
+    44100,
+    48000,
+    0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void omap_eac_rate_update(struct omap_eac_s *s)
+{
+    int fsint[3];
+
+    fsint[2] = (s->codec.config[3] >> 9) & 0xf;
+    fsint[1] = (s->codec.config[2] >> 0) & 0x7;
+    fsint[0] = (s->codec.config[0] >> 6) & 0x3;
+    if (fsint[2] < 0xf)
+        s->codec.rate = omap_eac_fsint3[fsint[2]];
+    else if (fsint[1] < 0x7)
+        s->codec.rate = omap_eac_fsint2[fsint[1]];
+    else
+        s->codec.rate = omap_eac_fsint[fsint[0]];
+}
+
+static void omap_eac_volume_update(struct omap_eac_s *s)
+{
+    /* TODO */
+}
+
+static void omap_eac_format_update(struct omap_eac_s *s)
+{
+    struct audsettings fmt;
+
+    /* The hardware buffers at most one sample */
+    if (s->codec.rxlen)
+        s->codec.rxlen = 1;
+
+    if (s->codec.in_voice) {
+        AUD_set_active_in(s->codec.in_voice, 0);
+        AUD_close_in(&s->codec.card, s->codec.in_voice);
+        s->codec.in_voice = NULL;
+    }
+    if (s->codec.out_voice) {
+        omap_eac_out_empty(s);
+        AUD_set_active_out(s->codec.out_voice, 0);
+        AUD_close_out(&s->codec.card, s->codec.out_voice);
+        s->codec.out_voice = NULL;
+        s->codec.txavail = 0;
+    }
+    /* Discard what couldn't be written */
+    s->codec.txlen = 0;
+
+    omap_eac_enable_update(s);
+    if (!s->codec.enable)
+        return;
+
+    omap_eac_rate_update(s);
+    fmt.endianness = ((s->codec.config[0] >> 8) & 1);          /* LI_BI */
+    fmt.nchannels = ((s->codec.config[0] >> 10) & 1) ? 2 : 1;  /* MN_ST */
+    fmt.freq = s->codec.rate;
+    /* TODO: signedness possibly depends on the CODEC hardware - or
+     * does I2S specify it?  */
+    /* All register writes are 16 bits so we we store 16-bit samples
+     * in the buffers regardless of AGCFR[B8_16] value.  */
+    fmt.fmt = AUD_FMT_U16;
+
+    s->codec.in_voice = AUD_open_in(&s->codec.card, s->codec.in_voice,
+                    "eac.codec.in", s, omap_eac_in_cb, &fmt);
+    s->codec.out_voice = AUD_open_out(&s->codec.card, s->codec.out_voice,
+                    "eac.codec.out", s, omap_eac_out_cb, &fmt);
+
+    omap_eac_volume_update(s);
+
+    AUD_set_active_in(s->codec.in_voice, 1);
+    AUD_set_active_out(s->codec.out_voice, 1);
+}
+
+static void omap_eac_reset(struct omap_eac_s *s)
+{
+    s->sysconfig = 0;
+    s->config[0] = 0x0c;
+    s->config[1] = 0x09;
+    s->config[2] = 0xab;
+    s->config[3] = 0x03;
+    s->control = 0x00;
+    s->address = 0x00;
+    s->data = 0x0000;
+    s->vtol = 0x00;
+    s->vtsl = 0x00;
+    s->mixer = 0x0000;
+    s->gain[0] = 0xe7e7;
+    s->gain[1] = 0x6767;
+    s->gain[2] = 0x6767;
+    s->gain[3] = 0x6767;
+    s->att = 0xce;
+    s->max[0] = 0;
+    s->max[1] = 0;
+    s->max[2] = 0;
+    s->max[3] = 0;
+    s->max[4] = 0;
+    s->max[5] = 0;
+    s->max[6] = 0;
+
+    s->modem.control = 0x00;
+    s->modem.config = 0x0000;
+    s->bt.control = 0x00;
+    s->bt.config = 0x0000;
+    s->codec.config[0] = 0x0649;
+    s->codec.config[1] = 0x0000;
+    s->codec.config[2] = 0x0007;
+    s->codec.config[3] = 0x1ffc;
+    s->codec.rxoff = 0;
+    s->codec.rxlen = 0;
+    s->codec.txlen = 0;
+    s->codec.rxavail = 0;
+    s->codec.txavail = 0;
+
+    omap_eac_format_update(s);
+    omap_eac_interrupt_update(s);
+}
+
+static uint64_t omap_eac_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
+    uint32_t ret;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x000:        /* CPCFR1 */
+        return s->config[0];
+    case 0x004:        /* CPCFR2 */
+        return s->config[1];
+    case 0x008:        /* CPCFR3 */
+        return s->config[2];
+    case 0x00c:        /* CPCFR4 */
+        return s->config[3];
+
+    case 0x010:        /* CPTCTL */
+        return s->control | ((s->codec.rxavail + s->codec.rxlen > 0) << 7) |
+                ((s->codec.txlen < s->codec.txavail) << 5);
+
+    case 0x014:        /* CPTTADR */
+        return s->address;
+    case 0x018:        /* CPTDATL */
+        return s->data & 0xff;
+    case 0x01c:        /* CPTDATH */
+        return s->data >> 8;
+    case 0x020:        /* CPTVSLL */
+        return s->vtol;
+    case 0x024:        /* CPTVSLH */
+        return s->vtsl | (3 << 5);     /* CRDY1 | CRDY2 */
+    case 0x040:        /* MPCTR */
+        return s->modem.control;
+    case 0x044:        /* MPMCCFR */
+        return s->modem.config;
+    case 0x060:        /* BPCTR */
+        return s->bt.control;
+    case 0x064:        /* BPMCCFR */
+        return s->bt.config;
+    case 0x080:        /* AMSCFR */
+        return s->mixer;
+    case 0x084:        /* AMVCTR */
+        return s->gain[0];
+    case 0x088:        /* AM1VCTR */
+        return s->gain[1];
+    case 0x08c:        /* AM2VCTR */
+        return s->gain[2];
+    case 0x090:        /* AM3VCTR */
+        return s->gain[3];
+    case 0x094:        /* ASTCTR */
+        return s->att;
+    case 0x098:        /* APD1LCR */
+        return s->max[0];
+    case 0x09c:        /* APD1RCR */
+        return s->max[1];
+    case 0x0a0:        /* APD2LCR */
+        return s->max[2];
+    case 0x0a4:        /* APD2RCR */
+        return s->max[3];
+    case 0x0a8:        /* APD3LCR */
+        return s->max[4];
+    case 0x0ac:        /* APD3RCR */
+        return s->max[5];
+    case 0x0b0:        /* APD4R */
+        return s->max[6];
+    case 0x0b4:        /* ADWR */
+        /* This should be write-only?  Docs list it as read-only.  */
+        return 0x0000;
+    case 0x0b8:        /* ADRDR */
+        if (likely(s->codec.rxlen > 1)) {
+            ret = s->codec.rxbuf[s->codec.rxoff ++];
+            s->codec.rxlen --;
+            s->codec.rxoff &= EAC_BUF_LEN - 1;
+            return ret;
+        } else if (s->codec.rxlen) {
+            ret = s->codec.rxbuf[s->codec.rxoff ++];
+            s->codec.rxlen --;
+            s->codec.rxoff &= EAC_BUF_LEN - 1;
+            if (s->codec.rxavail)
+                omap_eac_in_refill(s);
+            omap_eac_in_dmarequest_update(s);
+            return ret;
+        }
+        return 0x0000;
+    case 0x0bc:        /* AGCFR */
+        return s->codec.config[0];
+    case 0x0c0:        /* AGCTR */
+        return s->codec.config[1] | ((s->codec.config[1] & 2) << 14);
+    case 0x0c4:        /* AGCFR2 */
+        return s->codec.config[2];
+    case 0x0c8:        /* AGCFR3 */
+        return s->codec.config[3];
+    case 0x0cc:        /* MBPDMACTR */
+    case 0x0d0:        /* MPDDMARR */
+    case 0x0d8:        /* MPUDMARR */
+    case 0x0e4:        /* BPDDMARR */
+    case 0x0ec:        /* BPUDMARR */
+        return 0x0000;
+
+    case 0x100:        /* VERSION_NUMBER */
+        return 0x0010;
+
+    case 0x104:        /* SYSCONFIG */
+        return s->sysconfig;
+
+    case 0x108:        /* SYSSTATUS */
+        return 1 | 0xe;                                        /* RESETDONE | stuff */
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_eac_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x098:        /* APD1LCR */
+    case 0x09c:        /* APD1RCR */
+    case 0x0a0:        /* APD2LCR */
+    case 0x0a4:        /* APD2RCR */
+    case 0x0a8:        /* APD3LCR */
+    case 0x0ac:        /* APD3RCR */
+    case 0x0b0:        /* APD4R */
+    case 0x0b8:        /* ADRDR */
+    case 0x0d0:        /* MPDDMARR */
+    case 0x0d8:        /* MPUDMARR */
+    case 0x0e4:        /* BPDDMARR */
+    case 0x0ec:        /* BPUDMARR */
+    case 0x100:        /* VERSION_NUMBER */
+    case 0x108:        /* SYSSTATUS */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x000:        /* CPCFR1 */
+        s->config[0] = value & 0xff;
+        omap_eac_format_update(s);
+        break;
+    case 0x004:        /* CPCFR2 */
+        s->config[1] = value & 0xff;
+        omap_eac_format_update(s);
+        break;
+    case 0x008:        /* CPCFR3 */
+        s->config[2] = value & 0xff;
+        omap_eac_format_update(s);
+        break;
+    case 0x00c:        /* CPCFR4 */
+        s->config[3] = value & 0xff;
+        omap_eac_format_update(s);
+        break;
+
+    case 0x010:        /* CPTCTL */
+        /* Assuming TXF and TXE bits are read-only... */
+        s->control = value & 0x5f;
+        omap_eac_interrupt_update(s);
+        break;
+
+    case 0x014:        /* CPTTADR */
+        s->address = value & 0xff;
+        break;
+    case 0x018:        /* CPTDATL */
+        s->data &= 0xff00;
+        s->data |= value & 0xff;
+        break;
+    case 0x01c:        /* CPTDATH */
+        s->data &= 0x00ff;
+        s->data |= value << 8;
+        break;
+    case 0x020:        /* CPTVSLL */
+        s->vtol = value & 0xf8;
+        break;
+    case 0x024:        /* CPTVSLH */
+        s->vtsl = value & 0x9f;
+        break;
+    case 0x040:        /* MPCTR */
+        s->modem.control = value & 0x8f;
+        break;
+    case 0x044:        /* MPMCCFR */
+        s->modem.config = value & 0x7fff;
+        break;
+    case 0x060:        /* BPCTR */
+        s->bt.control = value & 0x8f;
+        break;
+    case 0x064:        /* BPMCCFR */
+        s->bt.config = value & 0x7fff;
+        break;
+    case 0x080:        /* AMSCFR */
+        s->mixer = value & 0x0fff;
+        break;
+    case 0x084:        /* AMVCTR */
+        s->gain[0] = value & 0xffff;
+        break;
+    case 0x088:        /* AM1VCTR */
+        s->gain[1] = value & 0xff7f;
+        break;
+    case 0x08c:        /* AM2VCTR */
+        s->gain[2] = value & 0xff7f;
+        break;
+    case 0x090:        /* AM3VCTR */
+        s->gain[3] = value & 0xff7f;
+        break;
+    case 0x094:        /* ASTCTR */
+        s->att = value & 0xff;
+        break;
+
+    case 0x0b4:        /* ADWR */
+        s->codec.txbuf[s->codec.txlen ++] = value;
+        if (unlikely(s->codec.txlen == EAC_BUF_LEN ||
+                                s->codec.txlen == s->codec.txavail)) {
+            if (s->codec.txavail)
+                omap_eac_out_empty(s);
+            /* Discard what couldn't be written */
+            s->codec.txlen = 0;
+        }
+        break;
+
+    case 0x0bc:        /* AGCFR */
+        s->codec.config[0] = value & 0x07ff;
+        omap_eac_format_update(s);
+        break;
+    case 0x0c0:        /* AGCTR */
+        s->codec.config[1] = value & 0x780f;
+        omap_eac_format_update(s);
+        break;
+    case 0x0c4:        /* AGCFR2 */
+        s->codec.config[2] = value & 0x003f;
+        omap_eac_format_update(s);
+        break;
+    case 0x0c8:        /* AGCFR3 */
+        s->codec.config[3] = value & 0xffff;
+        omap_eac_format_update(s);
+        break;
+    case 0x0cc:        /* MBPDMACTR */
+    case 0x0d4:        /* MPDDMAWR */
+    case 0x0e0:        /* MPUDMAWR */
+    case 0x0e8:        /* BPDDMAWR */
+    case 0x0f0:        /* BPUDMAWR */
+        break;
+
+    case 0x104:        /* SYSCONFIG */
+        if (value & (1 << 1))                          /* SOFTRESET */
+            omap_eac_reset(s);
+        s->sysconfig = value & 0x31d;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_eac_ops = {
+    .read = omap_eac_read,
+    .write = omap_eac_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
+                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
+{
+    struct omap_eac_s *s = (struct omap_eac_s *)
+            g_malloc0(sizeof(struct omap_eac_s));
+
+    s->irq = irq;
+    s->codec.rxdrq = *drq ++;
+    s->codec.txdrq = *drq;
+    omap_eac_reset(s);
+
+    AUD_register_card("OMAP EAC", &s->codec.card);
+
+    memory_region_init_io(&s->iomem, &omap_eac_ops, s, "omap.eac",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
+
+    return s;
+}
+
+/* STI/XTI (emulation interface) console - reverse engineered only */
+struct omap_sti_s {
+    qemu_irq irq;
+    MemoryRegion iomem;
+    MemoryRegion iomem_fifo;
+    CharDriverState *chr;
+
+    uint32_t sysconfig;
+    uint32_t systest;
+    uint32_t irqst;
+    uint32_t irqen;
+    uint32_t clkcontrol;
+    uint32_t serial_config;
+};
+
+#define STI_TRACE_CONSOLE_CHANNEL      239
+#define STI_TRACE_CONTROL_CHANNEL      253
+
+static inline void omap_sti_interrupt_update(struct omap_sti_s *s)
+{
+    qemu_set_irq(s->irq, s->irqst & s->irqen);
+}
+
+static void omap_sti_reset(struct omap_sti_s *s)
+{
+    s->sysconfig = 0;
+    s->irqst = 0;
+    s->irqen = 0;
+    s->clkcontrol = 0;
+    s->serial_config = 0;
+
+    omap_sti_interrupt_update(s);
+}
+
+static uint64_t omap_sti_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00: /* STI_REVISION */
+        return 0x10;
+
+    case 0x10: /* STI_SYSCONFIG */
+        return s->sysconfig;
+
+    case 0x14: /* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
+        return 0x00;
+
+    case 0x18: /* STI_IRQSTATUS */
+        return s->irqst;
+
+    case 0x1c: /* STI_IRQSETEN / STI_IRQCLREN */
+        return s->irqen;
+
+    case 0x24: /* STI_ER / STI_DR / XTI_TRACESELECT */
+    case 0x28: /* STI_RX_DR / XTI_RXDATA */
+        /* TODO */
+        return 0;
+
+    case 0x2c: /* STI_CLK_CTRL / XTI_SCLKCRTL */
+        return s->clkcontrol;
+
+    case 0x30: /* STI_SERIAL_CFG / XTI_SCONFIG */
+        return s->serial_config;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_sti_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00: /* STI_REVISION */
+    case 0x14: /* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x10: /* STI_SYSCONFIG */
+        if (value & (1 << 1))                          /* SOFTRESET */
+            omap_sti_reset(s);
+        s->sysconfig = value & 0xfe;
+        break;
+
+    case 0x18: /* STI_IRQSTATUS */
+        s->irqst &= ~value;
+        omap_sti_interrupt_update(s);
+        break;
+
+    case 0x1c: /* STI_IRQSETEN / STI_IRQCLREN */
+        s->irqen = value & 0xffff;
+        omap_sti_interrupt_update(s);
+        break;
+
+    case 0x2c: /* STI_CLK_CTRL / XTI_SCLKCRTL */
+        s->clkcontrol = value & 0xff;
+        break;
+
+    case 0x30: /* STI_SERIAL_CFG / XTI_SCONFIG */
+        s->serial_config = value & 0xff;
+        break;
+
+    case 0x24: /* STI_ER / STI_DR / XTI_TRACESELECT */
+    case 0x28: /* STI_RX_DR / XTI_RXDATA */
+        /* TODO */
+        return;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_sti_ops = {
+    .read = omap_sti_read,
+    .write = omap_sti_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr,
+                                   unsigned size)
+{
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_sti_fifo_write(void *opaque, hwaddr addr,
+                                uint64_t value, unsigned size)
+{
+    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
+    int ch = addr >> 6;
+    uint8_t byte = value;
+
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, size);
+    }
+
+    if (ch == STI_TRACE_CONTROL_CHANNEL) {
+        /* Flush channel <i>value</i>.  */
+        qemu_chr_fe_write(s->chr, (const uint8_t *) "\r", 1);
+    } else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
+        if (value == 0xc0 || value == 0xc3) {
+            /* Open channel <i>ch</i>.  */
+        } else if (value == 0x00)
+            qemu_chr_fe_write(s->chr, (const uint8_t *) "\n", 1);
+        else
+            qemu_chr_fe_write(s->chr, &byte, 1);
+    }
+}
+
+static const MemoryRegionOps omap_sti_fifo_ops = {
+    .read = omap_sti_fifo_read,
+    .write = omap_sti_fifo_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
+                MemoryRegion *sysmem,
+                hwaddr channel_base, qemu_irq irq, omap_clk clk,
+                CharDriverState *chr)
+{
+    struct omap_sti_s *s = (struct omap_sti_s *)
+            g_malloc0(sizeof(struct omap_sti_s));
+
+    s->irq = irq;
+    omap_sti_reset(s);
+
+    s->chr = chr ?: qemu_chr_new("null", "null", NULL);
+
+    memory_region_init_io(&s->iomem, &omap_sti_ops, s, "omap.sti",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
+
+    memory_region_init_io(&s->iomem_fifo, &omap_sti_fifo_ops, s,
+                          "omap.sti.fifo", 0x10000);
+    memory_region_add_subregion(sysmem, channel_base, &s->iomem_fifo);
+
+    return s;
+}
+
+/* L4 Interconnect */
+#define L4TA(n)                (n)
+#define L4TAO(n)       ((n) + 39)
+
+static const struct omap_l4_region_s omap_l4_region[125] = {
+    [  1] = { 0x40800,  0x800, 32          }, /* Initiator agent */
+    [  2] = { 0x41000, 0x1000, 32          }, /* Link agent */
+    [  0] = { 0x40000,  0x800, 32          }, /* Address and protection */
+    [  3] = { 0x00000, 0x1000, 32 | 16 | 8 }, /* System Control and Pinout */
+    [  4] = { 0x01000, 0x1000, 32 | 16 | 8 }, /* L4TAO1 */
+    [  5] = { 0x04000, 0x1000, 32 | 16     }, /* 32K Timer */
+    [  6] = { 0x05000, 0x1000, 32 | 16 | 8 }, /* L4TAO2 */
+    [  7] = { 0x08000,  0x800, 32          }, /* PRCM Region A */
+    [  8] = { 0x08800,  0x800, 32          }, /* PRCM Region B */
+    [  9] = { 0x09000, 0x1000, 32 | 16 | 8 }, /* L4TAO */
+    [ 10] = { 0x12000, 0x1000, 32 | 16 | 8 }, /* Test (BCM) */
+    [ 11] = { 0x13000, 0x1000, 32 | 16 | 8 }, /* L4TA1 */
+    [ 12] = { 0x14000, 0x1000, 32          }, /* Test/emulation (TAP) */
+    [ 13] = { 0x15000, 0x1000, 32 | 16 | 8 }, /* L4TA2 */
+    [ 14] = { 0x18000, 0x1000, 32 | 16 | 8 }, /* GPIO1 */
+    [ 16] = { 0x1a000, 0x1000, 32 | 16 | 8 }, /* GPIO2 */
+    [ 18] = { 0x1c000, 0x1000, 32 | 16 | 8 }, /* GPIO3 */
+    [ 19] = { 0x1e000, 0x1000, 32 | 16 | 8 }, /* GPIO4 */
+    [ 15] = { 0x19000, 0x1000, 32 | 16 | 8 }, /* Quad GPIO TOP */
+    [ 17] = { 0x1b000, 0x1000, 32 | 16 | 8 }, /* L4TA3 */
+    [ 20] = { 0x20000, 0x1000, 32 | 16 | 8 }, /* WD Timer 1 (Secure) */
+    [ 22] = { 0x22000, 0x1000, 32 | 16 | 8 }, /* WD Timer 2 (OMAP) */
+    [ 21] = { 0x21000, 0x1000, 32 | 16 | 8 }, /* Dual WD timer TOP */
+    [ 23] = { 0x23000, 0x1000, 32 | 16 | 8 }, /* L4TA4 */
+    [ 24] = { 0x28000, 0x1000, 32 | 16 | 8 }, /* GP Timer 1 */
+    [ 25] = { 0x29000, 0x1000, 32 | 16 | 8 }, /* L4TA7 */
+    [ 26] = { 0x48000, 0x2000, 32 | 16 | 8 }, /* Emulation (ARM11ETB) */
+    [ 27] = { 0x4a000, 0x1000, 32 | 16 | 8 }, /* L4TA9 */
+    [ 28] = { 0x50000,  0x400, 32 | 16 | 8 }, /* Display top */
+    [ 29] = { 0x50400,  0x400, 32 | 16 | 8 }, /* Display control */
+    [ 30] = { 0x50800,  0x400, 32 | 16 | 8 }, /* Display RFBI */
+    [ 31] = { 0x50c00,  0x400, 32 | 16 | 8 }, /* Display encoder */
+    [ 32] = { 0x51000, 0x1000, 32 | 16 | 8 }, /* L4TA10 */
+    [ 33] = { 0x52000,  0x400, 32 | 16 | 8 }, /* Camera top */
+    [ 34] = { 0x52400,  0x400, 32 | 16 | 8 }, /* Camera core */
+    [ 35] = { 0x52800,  0x400, 32 | 16 | 8 }, /* Camera DMA */
+    [ 36] = { 0x52c00,  0x400, 32 | 16 | 8 }, /* Camera MMU */
+    [ 37] = { 0x53000, 0x1000, 32 | 16 | 8 }, /* L4TA11 */
+    [ 38] = { 0x56000, 0x1000, 32 | 16 | 8 }, /* sDMA */
+    [ 39] = { 0x57000, 0x1000, 32 | 16 | 8 }, /* L4TA12 */
+    [ 40] = { 0x58000, 0x1000, 32 | 16 | 8 }, /* SSI top */
+    [ 41] = { 0x59000, 0x1000, 32 | 16 | 8 }, /* SSI GDD */
+    [ 42] = { 0x5a000, 0x1000, 32 | 16 | 8 }, /* SSI Port1 */
+    [ 43] = { 0x5b000, 0x1000, 32 | 16 | 8 }, /* SSI Port2 */
+    [ 44] = { 0x5c000, 0x1000, 32 | 16 | 8 }, /* L4TA13 */
+    [ 45] = { 0x5e000, 0x1000, 32 | 16 | 8 }, /* USB OTG */
+    [ 46] = { 0x5f000, 0x1000, 32 | 16 | 8 }, /* L4TAO4 */
+    [ 47] = { 0x60000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER1SDRC) */
+    [ 48] = { 0x61000, 0x1000, 32 | 16 | 8 }, /* L4TA14 */
+    [ 49] = { 0x62000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER2GPMC) */
+    [ 50] = { 0x63000, 0x1000, 32 | 16 | 8 }, /* L4TA15 */
+    [ 51] = { 0x64000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER3OCM) */
+    [ 52] = { 0x65000, 0x1000, 32 | 16 | 8 }, /* L4TA16 */
+    [ 53] = { 0x66000,  0x300, 32 | 16 | 8 }, /* Emulation (WIN_TRACER4L4) */
+    [ 54] = { 0x67000, 0x1000, 32 | 16 | 8 }, /* L4TA17 */
+    [ 55] = { 0x68000, 0x1000, 32 | 16 | 8 }, /* Emulation (XTI) */
+    [ 56] = { 0x69000, 0x1000, 32 | 16 | 8 }, /* L4TA18 */
+    [ 57] = { 0x6a000, 0x1000,      16 | 8 }, /* UART1 */
+    [ 58] = { 0x6b000, 0x1000, 32 | 16 | 8 }, /* L4TA19 */
+    [ 59] = { 0x6c000, 0x1000,      16 | 8 }, /* UART2 */
+    [ 60] = { 0x6d000, 0x1000, 32 | 16 | 8 }, /* L4TA20 */
+    [ 61] = { 0x6e000, 0x1000,      16 | 8 }, /* UART3 */
+    [ 62] = { 0x6f000, 0x1000, 32 | 16 | 8 }, /* L4TA21 */
+    [ 63] = { 0x70000, 0x1000,      16     }, /* I2C1 */
+    [ 64] = { 0x71000, 0x1000, 32 | 16 | 8 }, /* L4TAO5 */
+    [ 65] = { 0x72000, 0x1000,      16     }, /* I2C2 */
+    [ 66] = { 0x73000, 0x1000, 32 | 16 | 8 }, /* L4TAO6 */
+    [ 67] = { 0x74000, 0x1000,      16     }, /* McBSP1 */
+    [ 68] = { 0x75000, 0x1000, 32 | 16 | 8 }, /* L4TAO7 */
+    [ 69] = { 0x76000, 0x1000,      16     }, /* McBSP2 */
+    [ 70] = { 0x77000, 0x1000, 32 | 16 | 8 }, /* L4TAO8 */
+    [ 71] = { 0x24000, 0x1000, 32 | 16 | 8 }, /* WD Timer 3 (DSP) */
+    [ 72] = { 0x25000, 0x1000, 32 | 16 | 8 }, /* L4TA5 */
+    [ 73] = { 0x26000, 0x1000, 32 | 16 | 8 }, /* WD Timer 4 (IVA) */
+    [ 74] = { 0x27000, 0x1000, 32 | 16 | 8 }, /* L4TA6 */
+    [ 75] = { 0x2a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 2 */
+    [ 76] = { 0x2b000, 0x1000, 32 | 16 | 8 }, /* L4TA8 */
+    [ 77] = { 0x78000, 0x1000, 32 | 16 | 8 }, /* GP Timer 3 */
+    [ 78] = { 0x79000, 0x1000, 32 | 16 | 8 }, /* L4TA22 */
+    [ 79] = { 0x7a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 4 */
+    [ 80] = { 0x7b000, 0x1000, 32 | 16 | 8 }, /* L4TA23 */
+    [ 81] = { 0x7c000, 0x1000, 32 | 16 | 8 }, /* GP Timer 5 */
+    [ 82] = { 0x7d000, 0x1000, 32 | 16 | 8 }, /* L4TA24 */
+    [ 83] = { 0x7e000, 0x1000, 32 | 16 | 8 }, /* GP Timer 6 */
+    [ 84] = { 0x7f000, 0x1000, 32 | 16 | 8 }, /* L4TA25 */
+    [ 85] = { 0x80000, 0x1000, 32 | 16 | 8 }, /* GP Timer 7 */
+    [ 86] = { 0x81000, 0x1000, 32 | 16 | 8 }, /* L4TA26 */
+    [ 87] = { 0x82000, 0x1000, 32 | 16 | 8 }, /* GP Timer 8 */
+    [ 88] = { 0x83000, 0x1000, 32 | 16 | 8 }, /* L4TA27 */
+    [ 89] = { 0x84000, 0x1000, 32 | 16 | 8 }, /* GP Timer 9 */
+    [ 90] = { 0x85000, 0x1000, 32 | 16 | 8 }, /* L4TA28 */
+    [ 91] = { 0x86000, 0x1000, 32 | 16 | 8 }, /* GP Timer 10 */
+    [ 92] = { 0x87000, 0x1000, 32 | 16 | 8 }, /* L4TA29 */
+    [ 93] = { 0x88000, 0x1000, 32 | 16 | 8 }, /* GP Timer 11 */
+    [ 94] = { 0x89000, 0x1000, 32 | 16 | 8 }, /* L4TA30 */
+    [ 95] = { 0x8a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 12 */
+    [ 96] = { 0x8b000, 0x1000, 32 | 16 | 8 }, /* L4TA31 */
+    [ 97] = { 0x90000, 0x1000,      16     }, /* EAC */
+    [ 98] = { 0x91000, 0x1000, 32 | 16 | 8 }, /* L4TA32 */
+    [ 99] = { 0x92000, 0x1000,      16     }, /* FAC */
+    [100] = { 0x93000, 0x1000, 32 | 16 | 8 }, /* L4TA33 */
+    [101] = { 0x94000, 0x1000, 32 | 16 | 8 }, /* IPC (MAILBOX) */
+    [102] = { 0x95000, 0x1000, 32 | 16 | 8 }, /* L4TA34 */
+    [103] = { 0x98000, 0x1000, 32 | 16 | 8 }, /* SPI1 */
+    [104] = { 0x99000, 0x1000, 32 | 16 | 8 }, /* L4TA35 */
+    [105] = { 0x9a000, 0x1000, 32 | 16 | 8 }, /* SPI2 */
+    [106] = { 0x9b000, 0x1000, 32 | 16 | 8 }, /* L4TA36 */
+    [107] = { 0x9c000, 0x1000,      16 | 8 }, /* MMC SDIO */
+    [108] = { 0x9d000, 0x1000, 32 | 16 | 8 }, /* L4TAO9 */
+    [109] = { 0x9e000, 0x1000, 32 | 16 | 8 }, /* MS_PRO */
+    [110] = { 0x9f000, 0x1000, 32 | 16 | 8 }, /* L4TAO10 */
+    [111] = { 0xa0000, 0x1000, 32          }, /* RNG */
+    [112] = { 0xa1000, 0x1000, 32 | 16 | 8 }, /* L4TAO11 */
+    [113] = { 0xa2000, 0x1000, 32          }, /* DES3DES */
+    [114] = { 0xa3000, 0x1000, 32 | 16 | 8 }, /* L4TAO12 */
+    [115] = { 0xa4000, 0x1000, 32          }, /* SHA1MD5 */
+    [116] = { 0xa5000, 0x1000, 32 | 16 | 8 }, /* L4TAO13 */
+    [117] = { 0xa6000, 0x1000, 32          }, /* AES */
+    [118] = { 0xa7000, 0x1000, 32 | 16 | 8 }, /* L4TA37 */
+    [119] = { 0xa8000, 0x2000, 32          }, /* PKA */
+    [120] = { 0xaa000, 0x1000, 32 | 16 | 8 }, /* L4TA38 */
+    [121] = { 0xb0000, 0x1000, 32          }, /* MG */
+    [122] = { 0xb1000, 0x1000, 32 | 16 | 8 },
+    [123] = { 0xb2000, 0x1000, 32          }, /* HDQ/1-Wire */
+    [124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */
+};
+
+static const struct omap_l4_agent_info_s omap_l4_agent_info[54] = {
+    { 0,           0, 3, 2 }, /* L4IA initiatior agent */
+    { L4TAO(1),    3, 2, 1 }, /* Control and pinout module */
+    { L4TAO(2),    5, 2, 1 }, /* 32K timer */
+    { L4TAO(3),    7, 3, 2 }, /* PRCM */
+    { L4TA(1),    10, 2, 1 }, /* BCM */
+    { L4TA(2),    12, 2, 1 }, /* Test JTAG */
+    { L4TA(3),    14, 6, 3 }, /* Quad GPIO */
+    { L4TA(4),    20, 4, 3 }, /* WD timer 1/2 */
+    { L4TA(7),    24, 2, 1 }, /* GP timer 1 */
+    { L4TA(9),    26, 2, 1 }, /* ATM11 ETB */
+    { L4TA(10),   28, 5, 4 }, /* Display subsystem */
+    { L4TA(11),   33, 5, 4 }, /* Camera subsystem */
+    { L4TA(12),   38, 2, 1 }, /* sDMA */
+    { L4TA(13),   40, 5, 4 }, /* SSI */
+    { L4TAO(4),   45, 2, 1 }, /* USB */
+    { L4TA(14),   47, 2, 1 }, /* Win Tracer1 */
+    { L4TA(15),   49, 2, 1 }, /* Win Tracer2 */
+    { L4TA(16),   51, 2, 1 }, /* Win Tracer3 */
+    { L4TA(17),   53, 2, 1 }, /* Win Tracer4 */
+    { L4TA(18),   55, 2, 1 }, /* XTI */
+    { L4TA(19),   57, 2, 1 }, /* UART1 */
+    { L4TA(20),   59, 2, 1 }, /* UART2 */
+    { L4TA(21),   61, 2, 1 }, /* UART3 */
+    { L4TAO(5),   63, 2, 1 }, /* I2C1 */
+    { L4TAO(6),   65, 2, 1 }, /* I2C2 */
+    { L4TAO(7),   67, 2, 1 }, /* McBSP1 */
+    { L4TAO(8),   69, 2, 1 }, /* McBSP2 */
+    { L4TA(5),    71, 2, 1 }, /* WD Timer 3 (DSP) */
+    { L4TA(6),    73, 2, 1 }, /* WD Timer 4 (IVA) */
+    { L4TA(8),    75, 2, 1 }, /* GP Timer 2 */
+    { L4TA(22),   77, 2, 1 }, /* GP Timer 3 */
+    { L4TA(23),   79, 2, 1 }, /* GP Timer 4 */
+    { L4TA(24),   81, 2, 1 }, /* GP Timer 5 */
+    { L4TA(25),   83, 2, 1 }, /* GP Timer 6 */
+    { L4TA(26),   85, 2, 1 }, /* GP Timer 7 */
+    { L4TA(27),   87, 2, 1 }, /* GP Timer 8 */
+    { L4TA(28),   89, 2, 1 }, /* GP Timer 9 */
+    { L4TA(29),   91, 2, 1 }, /* GP Timer 10 */
+    { L4TA(30),   93, 2, 1 }, /* GP Timer 11 */
+    { L4TA(31),   95, 2, 1 }, /* GP Timer 12 */
+    { L4TA(32),   97, 2, 1 }, /* EAC */
+    { L4TA(33),   99, 2, 1 }, /* FAC */
+    { L4TA(34),  101, 2, 1 }, /* IPC */
+    { L4TA(35),  103, 2, 1 }, /* SPI1 */
+    { L4TA(36),  105, 2, 1 }, /* SPI2 */
+    { L4TAO(9),  107, 2, 1 }, /* MMC SDIO */
+    { L4TAO(10), 109, 2, 1 },
+    { L4TAO(11), 111, 2, 1 }, /* RNG */
+    { L4TAO(12), 113, 2, 1 }, /* DES3DES */
+    { L4TAO(13), 115, 2, 1 }, /* SHA1MD5 */
+    { L4TA(37),  117, 2, 1 }, /* AES */
+    { L4TA(38),  119, 2, 1 }, /* PKA */
+    { -1,        121, 2, 1 },
+    { L4TA(39),  123, 2, 1 }, /* HDQ/1-Wire */
+};
+
+#define omap_l4ta(bus, cs)     \
+    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TA(cs))
+#define omap_l4tao(bus, cs)    \
+    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TAO(cs))
+
+/* Power, Reset, and Clock Management */
+struct omap_prcm_s {
+    qemu_irq irq[3];
+    struct omap_mpu_state_s *mpu;
+    MemoryRegion iomem0;
+    MemoryRegion iomem1;
+
+    uint32_t irqst[3];
+    uint32_t irqen[3];
+
+    uint32_t sysconfig;
+    uint32_t voltctrl;
+    uint32_t scratch[20];
+
+    uint32_t clksrc[1];
+    uint32_t clkout[1];
+    uint32_t clkemul[1];
+    uint32_t clkpol[1];
+    uint32_t clksel[8];
+    uint32_t clken[12];
+    uint32_t clkctrl[4];
+    uint32_t clkidle[7];
+    uint32_t setuptime[2];
+
+    uint32_t wkup[3];
+    uint32_t wken[3];
+    uint32_t wkst[3];
+    uint32_t rst[4];
+    uint32_t rstctrl[1];
+    uint32_t power[4];
+    uint32_t rsttime_wkup;
+
+    uint32_t ev;
+    uint32_t evtime[2];
+
+    int dpll_lock, apll_lock[2];
+};
+
+static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
+{
+    qemu_set_irq(s->irq[dom], s->irqst[dom] & s->irqen[dom]);
+    /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */
+}
+
+static uint64_t omap_prcm_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
+    uint32_t ret;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x000:        /* PRCM_REVISION */
+        return 0x10;
+
+    case 0x010:        /* PRCM_SYSCONFIG */
+        return s->sysconfig;
+
+    case 0x018:        /* PRCM_IRQSTATUS_MPU */
+        return s->irqst[0];
+
+    case 0x01c:        /* PRCM_IRQENABLE_MPU */
+        return s->irqen[0];
+
+    case 0x050:        /* PRCM_VOLTCTRL */
+        return s->voltctrl;
+    case 0x054:        /* PRCM_VOLTST */
+        return s->voltctrl & 3;
+
+    case 0x060:        /* PRCM_CLKSRC_CTRL */
+        return s->clksrc[0];
+    case 0x070:        /* PRCM_CLKOUT_CTRL */
+        return s->clkout[0];
+    case 0x078:        /* PRCM_CLKEMUL_CTRL */
+        return s->clkemul[0];
+    case 0x080:        /* PRCM_CLKCFG_CTRL */
+    case 0x084:        /* PRCM_CLKCFG_STATUS */
+        return 0;
+
+    case 0x090:        /* PRCM_VOLTSETUP */
+        return s->setuptime[0];
+
+    case 0x094:        /* PRCM_CLKSSETUP */
+        return s->setuptime[1];
+
+    case 0x098:        /* PRCM_POLCTRL */
+        return s->clkpol[0];
+
+    case 0x0b0:        /* GENERAL_PURPOSE1 */
+    case 0x0b4:        /* GENERAL_PURPOSE2 */
+    case 0x0b8:        /* GENERAL_PURPOSE3 */
+    case 0x0bc:        /* GENERAL_PURPOSE4 */
+    case 0x0c0:        /* GENERAL_PURPOSE5 */
+    case 0x0c4:        /* GENERAL_PURPOSE6 */
+    case 0x0c8:        /* GENERAL_PURPOSE7 */
+    case 0x0cc:        /* GENERAL_PURPOSE8 */
+    case 0x0d0:        /* GENERAL_PURPOSE9 */
+    case 0x0d4:        /* GENERAL_PURPOSE10 */
+    case 0x0d8:        /* GENERAL_PURPOSE11 */
+    case 0x0dc:        /* GENERAL_PURPOSE12 */
+    case 0x0e0:        /* GENERAL_PURPOSE13 */
+    case 0x0e4:        /* GENERAL_PURPOSE14 */
+    case 0x0e8:        /* GENERAL_PURPOSE15 */
+    case 0x0ec:        /* GENERAL_PURPOSE16 */
+    case 0x0f0:        /* GENERAL_PURPOSE17 */
+    case 0x0f4:        /* GENERAL_PURPOSE18 */
+    case 0x0f8:        /* GENERAL_PURPOSE19 */
+    case 0x0fc:        /* GENERAL_PURPOSE20 */
+        return s->scratch[(addr - 0xb0) >> 2];
+
+    case 0x140:        /* CM_CLKSEL_MPU */
+        return s->clksel[0];
+    case 0x148:        /* CM_CLKSTCTRL_MPU */
+        return s->clkctrl[0];
+
+    case 0x158:        /* RM_RSTST_MPU */
+        return s->rst[0];
+    case 0x1c8:        /* PM_WKDEP_MPU */
+        return s->wkup[0];
+    case 0x1d4:        /* PM_EVGENCTRL_MPU */
+        return s->ev;
+    case 0x1d8:        /* PM_EVEGENONTIM_MPU */
+        return s->evtime[0];
+    case 0x1dc:        /* PM_EVEGENOFFTIM_MPU */
+        return s->evtime[1];
+    case 0x1e0:        /* PM_PWSTCTRL_MPU */
+        return s->power[0];
+    case 0x1e4:        /* PM_PWSTST_MPU */
+        return 0;
+
+    case 0x200:        /* CM_FCLKEN1_CORE */
+        return s->clken[0];
+    case 0x204:        /* CM_FCLKEN2_CORE */
+        return s->clken[1];
+    case 0x210:        /* CM_ICLKEN1_CORE */
+        return s->clken[2];
+    case 0x214:        /* CM_ICLKEN2_CORE */
+        return s->clken[3];
+    case 0x21c:        /* CM_ICLKEN4_CORE */
+        return s->clken[4];
+
+    case 0x220:        /* CM_IDLEST1_CORE */
+        /* TODO: check the actual iclk status */
+        return 0x7ffffff9;
+    case 0x224:        /* CM_IDLEST2_CORE */
+        /* TODO: check the actual iclk status */
+        return 0x00000007;
+    case 0x22c:        /* CM_IDLEST4_CORE */
+        /* TODO: check the actual iclk status */
+        return 0x0000001f;
+
+    case 0x230:        /* CM_AUTOIDLE1_CORE */
+        return s->clkidle[0];
+    case 0x234:        /* CM_AUTOIDLE2_CORE */
+        return s->clkidle[1];
+    case 0x238:        /* CM_AUTOIDLE3_CORE */
+        return s->clkidle[2];
+    case 0x23c:        /* CM_AUTOIDLE4_CORE */
+        return s->clkidle[3];
+
+    case 0x240:        /* CM_CLKSEL1_CORE */
+        return s->clksel[1];
+    case 0x244:        /* CM_CLKSEL2_CORE */
+        return s->clksel[2];
+
+    case 0x248:        /* CM_CLKSTCTRL_CORE */
+        return s->clkctrl[1];
+
+    case 0x2a0:        /* PM_WKEN1_CORE */
+        return s->wken[0];
+    case 0x2a4:        /* PM_WKEN2_CORE */
+        return s->wken[1];
+
+    case 0x2b0:        /* PM_WKST1_CORE */
+        return s->wkst[0];
+    case 0x2b4:        /* PM_WKST2_CORE */
+        return s->wkst[1];
+    case 0x2c8:        /* PM_WKDEP_CORE */
+        return 0x1e;
+
+    case 0x2e0:        /* PM_PWSTCTRL_CORE */
+        return s->power[1];
+    case 0x2e4:        /* PM_PWSTST_CORE */
+        return 0x000030 | (s->power[1] & 0xfc00);
+
+    case 0x300:        /* CM_FCLKEN_GFX */
+        return s->clken[5];
+    case 0x310:        /* CM_ICLKEN_GFX */
+        return s->clken[6];
+    case 0x320:        /* CM_IDLEST_GFX */
+        /* TODO: check the actual iclk status */
+        return 0x00000001;
+    case 0x340:        /* CM_CLKSEL_GFX */
+        return s->clksel[3];
+    case 0x348:        /* CM_CLKSTCTRL_GFX */
+        return s->clkctrl[2];
+    case 0x350:        /* RM_RSTCTRL_GFX */
+        return s->rstctrl[0];
+    case 0x358:        /* RM_RSTST_GFX */
+        return s->rst[1];
+    case 0x3c8:        /* PM_WKDEP_GFX */
+        return s->wkup[1];
+
+    case 0x3e0:        /* PM_PWSTCTRL_GFX */
+        return s->power[2];
+    case 0x3e4:        /* PM_PWSTST_GFX */
+        return s->power[2] & 3;
+
+    case 0x400:        /* CM_FCLKEN_WKUP */
+        return s->clken[7];
+    case 0x410:        /* CM_ICLKEN_WKUP */
+        return s->clken[8];
+    case 0x420:        /* CM_IDLEST_WKUP */
+        /* TODO: check the actual iclk status */
+        return 0x0000003f;
+    case 0x430:        /* CM_AUTOIDLE_WKUP */
+        return s->clkidle[4];
+    case 0x440:        /* CM_CLKSEL_WKUP */
+        return s->clksel[4];
+    case 0x450:        /* RM_RSTCTRL_WKUP */
+        return 0;
+    case 0x454:        /* RM_RSTTIME_WKUP */
+        return s->rsttime_wkup;
+    case 0x458:        /* RM_RSTST_WKUP */
+        return s->rst[2];
+    case 0x4a0:        /* PM_WKEN_WKUP */
+        return s->wken[2];
+    case 0x4b0:        /* PM_WKST_WKUP */
+        return s->wkst[2];
+
+    case 0x500:        /* CM_CLKEN_PLL */
+        return s->clken[9];
+    case 0x520:        /* CM_IDLEST_CKGEN */
+        ret = 0x0000070 | (s->apll_lock[0] << 9) | (s->apll_lock[1] << 8);
+        if (!(s->clksel[6] & 3))
+            /* Core uses 32-kHz clock */
+            ret |= 3 << 0;
+        else if (!s->dpll_lock)
+            /* DPLL not locked, core uses ref_clk */
+            ret |= 1 << 0;
+        else
+            /* Core uses DPLL */
+            ret |= 2 << 0;
+        return ret;
+    case 0x530:        /* CM_AUTOIDLE_PLL */
+        return s->clkidle[5];
+    case 0x540:        /* CM_CLKSEL1_PLL */
+        return s->clksel[5];
+    case 0x544:        /* CM_CLKSEL2_PLL */
+        return s->clksel[6];
+
+    case 0x800:        /* CM_FCLKEN_DSP */
+        return s->clken[10];
+    case 0x810:        /* CM_ICLKEN_DSP */
+        return s->clken[11];
+    case 0x820:        /* CM_IDLEST_DSP */
+        /* TODO: check the actual iclk status */
+        return 0x00000103;
+    case 0x830:        /* CM_AUTOIDLE_DSP */
+        return s->clkidle[6];
+    case 0x840:        /* CM_CLKSEL_DSP */
+        return s->clksel[7];
+    case 0x848:        /* CM_CLKSTCTRL_DSP */
+        return s->clkctrl[3];
+    case 0x850:        /* RM_RSTCTRL_DSP */
+        return 0;
+    case 0x858:        /* RM_RSTST_DSP */
+        return s->rst[3];
+    case 0x8c8:        /* PM_WKDEP_DSP */
+        return s->wkup[2];
+    case 0x8e0:        /* PM_PWSTCTRL_DSP */
+        return s->power[3];
+    case 0x8e4:        /* PM_PWSTST_DSP */
+        return 0x008030 | (s->power[3] & 0x3003);
+
+    case 0x8f0:        /* PRCM_IRQSTATUS_DSP */
+        return s->irqst[1];
+    case 0x8f4:        /* PRCM_IRQENABLE_DSP */
+        return s->irqen[1];
+
+    case 0x8f8:        /* PRCM_IRQSTATUS_IVA */
+        return s->irqst[2];
+    case 0x8fc:        /* PRCM_IRQENABLE_IVA */
+        return s->irqen[2];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_prcm_apll_update(struct omap_prcm_s *s)
+{
+    int mode[2];
+
+    mode[0] = (s->clken[9] >> 6) & 3;
+    s->apll_lock[0] = (mode[0] == 3);
+    mode[1] = (s->clken[9] >> 2) & 3;
+    s->apll_lock[1] = (mode[1] == 3);
+    /* TODO: update clocks */
+
+    if (mode[0] == 1 || mode[0] == 2 || mode[1] == 1 || mode[1] == 2)
+        fprintf(stderr, "%s: bad EN_54M_PLL or bad EN_96M_PLL\n",
+                        __FUNCTION__);
+}
+
+static void omap_prcm_dpll_update(struct omap_prcm_s *s)
+{
+    omap_clk dpll = omap_findclk(s->mpu, "dpll");
+    omap_clk dpll_x2 = omap_findclk(s->mpu, "dpll");
+    omap_clk core = omap_findclk(s->mpu, "core_clk");
+    int mode = (s->clken[9] >> 0) & 3;
+    int mult, div;
+
+    mult = (s->clksel[5] >> 12) & 0x3ff;
+    div = (s->clksel[5] >> 8) & 0xf;
+    if (mult == 0 || mult == 1)
+        mode = 1;      /* Bypass */
+
+    s->dpll_lock = 0;
+    switch (mode) {
+    case 0:
+        fprintf(stderr, "%s: bad EN_DPLL\n", __FUNCTION__);
+        break;
+    case 1:    /* Low-power bypass mode (Default) */
+    case 2:    /* Fast-relock bypass mode */
+        omap_clk_setrate(dpll, 1, 1);
+        omap_clk_setrate(dpll_x2, 1, 1);
+        break;
+    case 3:    /* Lock mode */
+        s->dpll_lock = 1; /* After 20 FINT cycles (ref_clk / (div + 1)).  */
+
+        omap_clk_setrate(dpll, div + 1, mult);
+        omap_clk_setrate(dpll_x2, div + 1, mult * 2);
+        break;
+    }
+
+    switch ((s->clksel[6] >> 0) & 3) {
+    case 0:
+        omap_clk_reparent(core, omap_findclk(s->mpu, "clk32-kHz"));
+        break;
+    case 1:
+        omap_clk_reparent(core, dpll);
+        break;
+    case 2:
+        /* Default */
+        omap_clk_reparent(core, dpll_x2);
+        break;
+    case 3:
+        fprintf(stderr, "%s: bad CORE_CLK_SRC\n", __FUNCTION__);
+        break;
+    }
+}
+
+static void omap_prcm_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x000:        /* PRCM_REVISION */
+    case 0x054:        /* PRCM_VOLTST */
+    case 0x084:        /* PRCM_CLKCFG_STATUS */
+    case 0x1e4:        /* PM_PWSTST_MPU */
+    case 0x220:        /* CM_IDLEST1_CORE */
+    case 0x224:        /* CM_IDLEST2_CORE */
+    case 0x22c:        /* CM_IDLEST4_CORE */
+    case 0x2c8:        /* PM_WKDEP_CORE */
+    case 0x2e4:        /* PM_PWSTST_CORE */
+    case 0x320:        /* CM_IDLEST_GFX */
+    case 0x3e4:        /* PM_PWSTST_GFX */
+    case 0x420:        /* CM_IDLEST_WKUP */
+    case 0x520:        /* CM_IDLEST_CKGEN */
+    case 0x820:        /* CM_IDLEST_DSP */
+    case 0x8e4:        /* PM_PWSTST_DSP */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x010:        /* PRCM_SYSCONFIG */
+        s->sysconfig = value & 1;
+        break;
+
+    case 0x018:        /* PRCM_IRQSTATUS_MPU */
+        s->irqst[0] &= ~value;
+        omap_prcm_int_update(s, 0);
+        break;
+    case 0x01c:        /* PRCM_IRQENABLE_MPU */
+        s->irqen[0] = value & 0x3f;
+        omap_prcm_int_update(s, 0);
+        break;
+
+    case 0x050:        /* PRCM_VOLTCTRL */
+        s->voltctrl = value & 0xf1c3;
+        break;
+
+    case 0x060:        /* PRCM_CLKSRC_CTRL */
+        s->clksrc[0] = value & 0xdb;
+        /* TODO update clocks */
+        break;
+
+    case 0x070:        /* PRCM_CLKOUT_CTRL */
+        s->clkout[0] = value & 0xbbbb;
+        /* TODO update clocks */
+        break;
+
+    case 0x078:        /* PRCM_CLKEMUL_CTRL */
+        s->clkemul[0] = value & 1;
+        /* TODO update clocks */
+        break;
+
+    case 0x080:        /* PRCM_CLKCFG_CTRL */
+        break;
+
+    case 0x090:        /* PRCM_VOLTSETUP */
+        s->setuptime[0] = value & 0xffff;
+        break;
+    case 0x094:        /* PRCM_CLKSSETUP */
+        s->setuptime[1] = value & 0xffff;
+        break;
+
+    case 0x098:        /* PRCM_POLCTRL */
+        s->clkpol[0] = value & 0x701;
+        break;
+
+    case 0x0b0:        /* GENERAL_PURPOSE1 */
+    case 0x0b4:        /* GENERAL_PURPOSE2 */
+    case 0x0b8:        /* GENERAL_PURPOSE3 */
+    case 0x0bc:        /* GENERAL_PURPOSE4 */
+    case 0x0c0:        /* GENERAL_PURPOSE5 */
+    case 0x0c4:        /* GENERAL_PURPOSE6 */
+    case 0x0c8:        /* GENERAL_PURPOSE7 */
+    case 0x0cc:        /* GENERAL_PURPOSE8 */
+    case 0x0d0:        /* GENERAL_PURPOSE9 */
+    case 0x0d4:        /* GENERAL_PURPOSE10 */
+    case 0x0d8:        /* GENERAL_PURPOSE11 */
+    case 0x0dc:        /* GENERAL_PURPOSE12 */
+    case 0x0e0:        /* GENERAL_PURPOSE13 */
+    case 0x0e4:        /* GENERAL_PURPOSE14 */
+    case 0x0e8:        /* GENERAL_PURPOSE15 */
+    case 0x0ec:        /* GENERAL_PURPOSE16 */
+    case 0x0f0:        /* GENERAL_PURPOSE17 */
+    case 0x0f4:        /* GENERAL_PURPOSE18 */
+    case 0x0f8:        /* GENERAL_PURPOSE19 */
+    case 0x0fc:        /* GENERAL_PURPOSE20 */
+        s->scratch[(addr - 0xb0) >> 2] = value;
+        break;
+
+    case 0x140:        /* CM_CLKSEL_MPU */
+        s->clksel[0] = value & 0x1f;
+        /* TODO update clocks */
+        break;
+    case 0x148:        /* CM_CLKSTCTRL_MPU */
+        s->clkctrl[0] = value & 0x1f;
+        break;
+
+    case 0x158:        /* RM_RSTST_MPU */
+        s->rst[0] &= ~value;
+        break;
+    case 0x1c8:        /* PM_WKDEP_MPU */
+        s->wkup[0] = value & 0x15;
+        break;
+
+    case 0x1d4:        /* PM_EVGENCTRL_MPU */
+        s->ev = value & 0x1f;
+        break;
+    case 0x1d8:        /* PM_EVEGENONTIM_MPU */
+        s->evtime[0] = value;
+        break;
+    case 0x1dc:        /* PM_EVEGENOFFTIM_MPU */
+        s->evtime[1] = value;
+        break;
+
+    case 0x1e0:        /* PM_PWSTCTRL_MPU */
+        s->power[0] = value & 0xc0f;
+        break;
+
+    case 0x200:        /* CM_FCLKEN1_CORE */
+        s->clken[0] = value & 0xbfffffff;
+        /* TODO update clocks */
+        /* The EN_EAC bit only gets/puts func_96m_clk.  */
+        break;
+    case 0x204:        /* CM_FCLKEN2_CORE */
+        s->clken[1] = value & 0x00000007;
+        /* TODO update clocks */
+        break;
+    case 0x210:        /* CM_ICLKEN1_CORE */
+        s->clken[2] = value & 0xfffffff9;
+        /* TODO update clocks */
+        /* The EN_EAC bit only gets/puts core_l4_iclk.  */
+        break;
+    case 0x214:        /* CM_ICLKEN2_CORE */
+        s->clken[3] = value & 0x00000007;
+        /* TODO update clocks */
+        break;
+    case 0x21c:        /* CM_ICLKEN4_CORE */
+        s->clken[4] = value & 0x0000001f;
+        /* TODO update clocks */
+        break;
+
+    case 0x230:        /* CM_AUTOIDLE1_CORE */
+        s->clkidle[0] = value & 0xfffffff9;
+        /* TODO update clocks */
+        break;
+    case 0x234:        /* CM_AUTOIDLE2_CORE */
+        s->clkidle[1] = value & 0x00000007;
+        /* TODO update clocks */
+        break;
+    case 0x238:        /* CM_AUTOIDLE3_CORE */
+        s->clkidle[2] = value & 0x00000007;
+        /* TODO update clocks */
+        break;
+    case 0x23c:        /* CM_AUTOIDLE4_CORE */
+        s->clkidle[3] = value & 0x0000001f;
+        /* TODO update clocks */
+        break;
+
+    case 0x240:        /* CM_CLKSEL1_CORE */
+        s->clksel[1] = value & 0x0fffbf7f;
+        /* TODO update clocks */
+        break;
+
+    case 0x244:        /* CM_CLKSEL2_CORE */
+        s->clksel[2] = value & 0x00fffffc;
+        /* TODO update clocks */
+        break;
+
+    case 0x248:        /* CM_CLKSTCTRL_CORE */
+        s->clkctrl[1] = value & 0x7;
+        break;
+
+    case 0x2a0:        /* PM_WKEN1_CORE */
+        s->wken[0] = value & 0x04667ff8;
+        break;
+    case 0x2a4:        /* PM_WKEN2_CORE */
+        s->wken[1] = value & 0x00000005;
+        break;
+
+    case 0x2b0:        /* PM_WKST1_CORE */
+        s->wkst[0] &= ~value;
+        break;
+    case 0x2b4:        /* PM_WKST2_CORE */
+        s->wkst[1] &= ~value;
+        break;
+
+    case 0x2e0:        /* PM_PWSTCTRL_CORE */
+        s->power[1] = (value & 0x00fc3f) | (1 << 2);
+        break;
+
+    case 0x300:        /* CM_FCLKEN_GFX */
+        s->clken[5] = value & 6;
+        /* TODO update clocks */
+        break;
+    case 0x310:        /* CM_ICLKEN_GFX */
+        s->clken[6] = value & 1;
+        /* TODO update clocks */
+        break;
+    case 0x340:        /* CM_CLKSEL_GFX */
+        s->clksel[3] = value & 7;
+        /* TODO update clocks */
+        break;
+    case 0x348:        /* CM_CLKSTCTRL_GFX */
+        s->clkctrl[2] = value & 1;
+        break;
+    case 0x350:        /* RM_RSTCTRL_GFX */
+        s->rstctrl[0] = value & 1;
+        /* TODO: reset */
+        break;
+    case 0x358:        /* RM_RSTST_GFX */
+        s->rst[1] &= ~value;
+        break;
+    case 0x3c8:        /* PM_WKDEP_GFX */
+        s->wkup[1] = value & 0x13;
+        break;
+    case 0x3e0:        /* PM_PWSTCTRL_GFX */
+        s->power[2] = (value & 0x00c0f) | (3 << 2);
+        break;
+
+    case 0x400:        /* CM_FCLKEN_WKUP */
+        s->clken[7] = value & 0xd;
+        /* TODO update clocks */
+        break;
+    case 0x410:        /* CM_ICLKEN_WKUP */
+        s->clken[8] = value & 0x3f;
+        /* TODO update clocks */
+        break;
+    case 0x430:        /* CM_AUTOIDLE_WKUP */
+        s->clkidle[4] = value & 0x0000003f;
+        /* TODO update clocks */
+        break;
+    case 0x440:        /* CM_CLKSEL_WKUP */
+        s->clksel[4] = value & 3;
+        /* TODO update clocks */
+        break;
+    case 0x450:        /* RM_RSTCTRL_WKUP */
+        /* TODO: reset */
+        if (value & 2)
+            qemu_system_reset_request();
+        break;
+    case 0x454:        /* RM_RSTTIME_WKUP */
+        s->rsttime_wkup = value & 0x1fff;
+        break;
+    case 0x458:        /* RM_RSTST_WKUP */
+        s->rst[2] &= ~value;
+        break;
+    case 0x4a0:        /* PM_WKEN_WKUP */
+        s->wken[2] = value & 0x00000005;
+        break;
+    case 0x4b0:        /* PM_WKST_WKUP */
+        s->wkst[2] &= ~value;
+        break;
+
+    case 0x500:        /* CM_CLKEN_PLL */
+        if (value & 0xffffff30)
+            fprintf(stderr, "%s: write 0s in CM_CLKEN_PLL for "
+                            "future compatibility\n", __FUNCTION__);
+        if ((s->clken[9] ^ value) & 0xcc) {
+            s->clken[9] &= ~0xcc;
+            s->clken[9] |= value & 0xcc;
+            omap_prcm_apll_update(s);
+        }
+        if ((s->clken[9] ^ value) & 3) {
+            s->clken[9] &= ~3;
+            s->clken[9] |= value & 3;
+            omap_prcm_dpll_update(s);
+        }
+        break;
+    case 0x530:        /* CM_AUTOIDLE_PLL */
+        s->clkidle[5] = value & 0x000000cf;
+        /* TODO update clocks */
+        break;
+    case 0x540:        /* CM_CLKSEL1_PLL */
+        if (value & 0xfc4000d7)
+            fprintf(stderr, "%s: write 0s in CM_CLKSEL1_PLL for "
+                            "future compatibility\n", __FUNCTION__);
+        if ((s->clksel[5] ^ value) & 0x003fff00) {
+            s->clksel[5] = value & 0x03bfff28;
+            omap_prcm_dpll_update(s);
+        }
+        /* TODO update the other clocks */
+
+        s->clksel[5] = value & 0x03bfff28;
+        break;
+    case 0x544:        /* CM_CLKSEL2_PLL */
+        if (value & ~3)
+            fprintf(stderr, "%s: write 0s in CM_CLKSEL2_PLL[31:2] for "
+                            "future compatibility\n", __FUNCTION__);
+        if (s->clksel[6] != (value & 3)) {
+            s->clksel[6] = value & 3;
+            omap_prcm_dpll_update(s);
+        }
+        break;
+
+    case 0x800:        /* CM_FCLKEN_DSP */
+        s->clken[10] = value & 0x501;
+        /* TODO update clocks */
+        break;
+    case 0x810:        /* CM_ICLKEN_DSP */
+        s->clken[11] = value & 0x2;
+        /* TODO update clocks */
+        break;
+    case 0x830:        /* CM_AUTOIDLE_DSP */
+        s->clkidle[6] = value & 0x2;
+        /* TODO update clocks */
+        break;
+    case 0x840:        /* CM_CLKSEL_DSP */
+        s->clksel[7] = value & 0x3fff;
+        /* TODO update clocks */
+        break;
+    case 0x848:        /* CM_CLKSTCTRL_DSP */
+        s->clkctrl[3] = value & 0x101;
+        break;
+    case 0x850:        /* RM_RSTCTRL_DSP */
+        /* TODO: reset */
+        break;
+    case 0x858:        /* RM_RSTST_DSP */
+        s->rst[3] &= ~value;
+        break;
+    case 0x8c8:        /* PM_WKDEP_DSP */
+        s->wkup[2] = value & 0x13;
+        break;
+    case 0x8e0:        /* PM_PWSTCTRL_DSP */
+        s->power[3] = (value & 0x03017) | (3 << 2);
+        break;
+
+    case 0x8f0:        /* PRCM_IRQSTATUS_DSP */
+        s->irqst[1] &= ~value;
+        omap_prcm_int_update(s, 1);
+        break;
+    case 0x8f4:        /* PRCM_IRQENABLE_DSP */
+        s->irqen[1] = value & 0x7;
+        omap_prcm_int_update(s, 1);
+        break;
+
+    case 0x8f8:        /* PRCM_IRQSTATUS_IVA */
+        s->irqst[2] &= ~value;
+        omap_prcm_int_update(s, 2);
+        break;
+    case 0x8fc:        /* PRCM_IRQENABLE_IVA */
+        s->irqen[2] = value & 0x7;
+        omap_prcm_int_update(s, 2);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_prcm_ops = {
+    .read = omap_prcm_read,
+    .write = omap_prcm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_prcm_reset(struct omap_prcm_s *s)
+{
+    s->sysconfig = 0;
+    s->irqst[0] = 0;
+    s->irqst[1] = 0;
+    s->irqst[2] = 0;
+    s->irqen[0] = 0;
+    s->irqen[1] = 0;
+    s->irqen[2] = 0;
+    s->voltctrl = 0x1040;
+    s->ev = 0x14;
+    s->evtime[0] = 0;
+    s->evtime[1] = 0;
+    s->clkctrl[0] = 0;
+    s->clkctrl[1] = 0;
+    s->clkctrl[2] = 0;
+    s->clkctrl[3] = 0;
+    s->clken[1] = 7;
+    s->clken[3] = 7;
+    s->clken[4] = 0;
+    s->clken[5] = 0;
+    s->clken[6] = 0;
+    s->clken[7] = 0xc;
+    s->clken[8] = 0x3e;
+    s->clken[9] = 0x0d;
+    s->clken[10] = 0;
+    s->clken[11] = 0;
+    s->clkidle[0] = 0;
+    s->clkidle[2] = 7;
+    s->clkidle[3] = 0;
+    s->clkidle[4] = 0;
+    s->clkidle[5] = 0x0c;
+    s->clkidle[6] = 0;
+    s->clksel[0] = 0x01;
+    s->clksel[1] = 0x02100121;
+    s->clksel[2] = 0x00000000;
+    s->clksel[3] = 0x01;
+    s->clksel[4] = 0;
+    s->clksel[7] = 0x0121;
+    s->wkup[0] = 0x15;
+    s->wkup[1] = 0x13;
+    s->wkup[2] = 0x13;
+    s->wken[0] = 0x04667ff8;
+    s->wken[1] = 0x00000005;
+    s->wken[2] = 5;
+    s->wkst[0] = 0;
+    s->wkst[1] = 0;
+    s->wkst[2] = 0;
+    s->power[0] = 0x00c;
+    s->power[1] = 4;
+    s->power[2] = 0x0000c;
+    s->power[3] = 0x14;
+    s->rstctrl[0] = 1;
+    s->rst[3] = 1;
+    omap_prcm_apll_update(s);
+    omap_prcm_dpll_update(s);
+}
+
+static void omap_prcm_coldreset(struct omap_prcm_s *s)
+{
+    s->setuptime[0] = 0;
+    s->setuptime[1] = 0;
+    memset(&s->scratch, 0, sizeof(s->scratch));
+    s->rst[0] = 0x01;
+    s->rst[1] = 0x00;
+    s->rst[2] = 0x01;
+    s->clken[0] = 0;
+    s->clken[2] = 0;
+    s->clkidle[1] = 0;
+    s->clksel[5] = 0;
+    s->clksel[6] = 2;
+    s->clksrc[0] = 0x43;
+    s->clkout[0] = 0x0303;
+    s->clkemul[0] = 0;
+    s->clkpol[0] = 0x100;
+    s->rsttime_wkup = 0x1002;
+
+    omap_prcm_reset(s);
+}
+
+static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
+                qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
+                struct omap_mpu_state_s *mpu)
+{
+    struct omap_prcm_s *s = (struct omap_prcm_s *)
+            g_malloc0(sizeof(struct omap_prcm_s));
+
+    s->irq[0] = mpu_int;
+    s->irq[1] = dsp_int;
+    s->irq[2] = iva_int;
+    s->mpu = mpu;
+    omap_prcm_coldreset(s);
+
+    memory_region_init_io(&s->iomem0, &omap_prcm_ops, s, "omap.pcrm0",
+                          omap_l4_region_size(ta, 0));
+    memory_region_init_io(&s->iomem1, &omap_prcm_ops, s, "omap.pcrm1",
+                          omap_l4_region_size(ta, 1));
+    omap_l4_attach(ta, 0, &s->iomem0);
+    omap_l4_attach(ta, 1, &s->iomem1);
+
+    return s;
+}
+
+/* System and Pinout control */
+struct omap_sysctl_s {
+    struct omap_mpu_state_s *mpu;
+    MemoryRegion iomem;
+
+    uint32_t sysconfig;
+    uint32_t devconfig;
+    uint32_t psaconfig;
+    uint32_t padconf[0x45];
+    uint8_t obs;
+    uint32_t msuspendmux[5];
+};
+
+static uint32_t omap_sysctl_read8(void *opaque, hwaddr addr)
+{
+
+    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
+    int pad_offset, byte_offset;
+    int value;
+
+    switch (addr) {
+    case 0x030 ... 0x140:      /* CONTROL_PADCONF - only used in the POP */
+        pad_offset = (addr - 0x30) >> 2;
+        byte_offset = (addr - 0x30) & (4 - 1);
+
+        value = s->padconf[pad_offset];
+        value = (value >> (byte_offset * 8)) & 0xff;
+
+        return value;
+
+    default:
+        break;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static uint32_t omap_sysctl_read(void *opaque, hwaddr addr)
+{
+    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
+
+    switch (addr) {
+    case 0x000:        /* CONTROL_REVISION */
+        return 0x20;
+
+    case 0x010:        /* CONTROL_SYSCONFIG */
+        return s->sysconfig;
+
+    case 0x030 ... 0x140:      /* CONTROL_PADCONF - only used in the POP */
+        return s->padconf[(addr - 0x30) >> 2];
+
+    case 0x270:        /* CONTROL_DEBOBS */
+        return s->obs;
+
+    case 0x274:        /* CONTROL_DEVCONF */
+        return s->devconfig;
+
+    case 0x28c:        /* CONTROL_EMU_SUPPORT */
+        return 0;
+
+    case 0x290:        /* CONTROL_MSUSPENDMUX_0 */
+        return s->msuspendmux[0];
+    case 0x294:        /* CONTROL_MSUSPENDMUX_1 */
+        return s->msuspendmux[1];
+    case 0x298:        /* CONTROL_MSUSPENDMUX_2 */
+        return s->msuspendmux[2];
+    case 0x29c:        /* CONTROL_MSUSPENDMUX_3 */
+        return s->msuspendmux[3];
+    case 0x2a0:        /* CONTROL_MSUSPENDMUX_4 */
+        return s->msuspendmux[4];
+    case 0x2a4:        /* CONTROL_MSUSPENDMUX_5 */
+        return 0;
+
+    case 0x2b8:        /* CONTROL_PSA_CTRL */
+        return s->psaconfig;
+    case 0x2bc:        /* CONTROL_PSA_CMD */
+    case 0x2c0:        /* CONTROL_PSA_VALUE */
+        return 0;
+
+    case 0x2b0:        /* CONTROL_SEC_CTRL */
+        return 0x800000f1;
+    case 0x2d0:        /* CONTROL_SEC_EMU */
+        return 0x80000015;
+    case 0x2d4:        /* CONTROL_SEC_TAP */
+        return 0x8000007f;
+    case 0x2b4:        /* CONTROL_SEC_TEST */
+    case 0x2f0:        /* CONTROL_SEC_STATUS */
+    case 0x2f4:        /* CONTROL_SEC_ERR_STATUS */
+        /* Secure mode is not present on general-pusrpose device.  Outside
+         * secure mode these values cannot be read or written.  */
+        return 0;
+
+    case 0x2d8:        /* CONTROL_OCM_RAM_PERM */
+        return 0xff;
+    case 0x2dc:        /* CONTROL_OCM_PUB_RAM_ADD */
+    case 0x2e0:        /* CONTROL_EXT_SEC_RAM_START_ADD */
+    case 0x2e4:        /* CONTROL_EXT_SEC_RAM_STOP_ADD */
+        /* No secure mode so no Extended Secure RAM present.  */
+        return 0;
+
+    case 0x2f8:        /* CONTROL_STATUS */
+        /* Device Type => General-purpose */
+        return 0x0300;
+    case 0x2fc:        /* CONTROL_GENERAL_PURPOSE_STATUS */
+
+    case 0x300:        /* CONTROL_RPUB_KEY_H_0 */
+    case 0x304:        /* CONTROL_RPUB_KEY_H_1 */
+    case 0x308:        /* CONTROL_RPUB_KEY_H_2 */
+    case 0x30c:        /* CONTROL_RPUB_KEY_H_3 */
+        return 0xdecafbad;
+
+    case 0x310:        /* CONTROL_RAND_KEY_0 */
+    case 0x314:        /* CONTROL_RAND_KEY_1 */
+    case 0x318:        /* CONTROL_RAND_KEY_2 */
+    case 0x31c:        /* CONTROL_RAND_KEY_3 */
+    case 0x320:        /* CONTROL_CUST_KEY_0 */
+    case 0x324:        /* CONTROL_CUST_KEY_1 */
+    case 0x330:        /* CONTROL_TEST_KEY_0 */
+    case 0x334:        /* CONTROL_TEST_KEY_1 */
+    case 0x338:        /* CONTROL_TEST_KEY_2 */
+    case 0x33c:        /* CONTROL_TEST_KEY_3 */
+    case 0x340:        /* CONTROL_TEST_KEY_4 */
+    case 0x344:        /* CONTROL_TEST_KEY_5 */
+    case 0x348:        /* CONTROL_TEST_KEY_6 */
+    case 0x34c:        /* CONTROL_TEST_KEY_7 */
+    case 0x350:        /* CONTROL_TEST_KEY_8 */
+    case 0x354:        /* CONTROL_TEST_KEY_9 */
+        /* Can only be accessed in secure mode and when C_FieldAccEnable
+         * bit is set in CONTROL_SEC_CTRL.
+         * TODO: otherwise an interconnect access error is generated.  */
+        return 0;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_sysctl_write8(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
+    int pad_offset, byte_offset;
+    int prev_value;
+
+    switch (addr) {
+    case 0x030 ... 0x140:      /* CONTROL_PADCONF - only used in the POP */
+        pad_offset = (addr - 0x30) >> 2;
+        byte_offset = (addr - 0x30) & (4 - 1);
+
+        prev_value = s->padconf[pad_offset];
+        prev_value &= ~(0xff << (byte_offset * 8));
+        prev_value |= ((value & 0x1f1f1f1f) << (byte_offset * 8)) & 0x1f1f1f1f;
+        s->padconf[pad_offset] = prev_value;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        break;
+    }
+}
+
+static void omap_sysctl_write(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
+
+    switch (addr) {
+    case 0x000:        /* CONTROL_REVISION */
+    case 0x2a4:        /* CONTROL_MSUSPENDMUX_5 */
+    case 0x2c0:        /* CONTROL_PSA_VALUE */
+    case 0x2f8:        /* CONTROL_STATUS */
+    case 0x2fc:        /* CONTROL_GENERAL_PURPOSE_STATUS */
+    case 0x300:        /* CONTROL_RPUB_KEY_H_0 */
+    case 0x304:        /* CONTROL_RPUB_KEY_H_1 */
+    case 0x308:        /* CONTROL_RPUB_KEY_H_2 */
+    case 0x30c:        /* CONTROL_RPUB_KEY_H_3 */
+    case 0x310:        /* CONTROL_RAND_KEY_0 */
+    case 0x314:        /* CONTROL_RAND_KEY_1 */
+    case 0x318:        /* CONTROL_RAND_KEY_2 */
+    case 0x31c:        /* CONTROL_RAND_KEY_3 */
+    case 0x320:        /* CONTROL_CUST_KEY_0 */
+    case 0x324:        /* CONTROL_CUST_KEY_1 */
+    case 0x330:        /* CONTROL_TEST_KEY_0 */
+    case 0x334:        /* CONTROL_TEST_KEY_1 */
+    case 0x338:        /* CONTROL_TEST_KEY_2 */
+    case 0x33c:        /* CONTROL_TEST_KEY_3 */
+    case 0x340:        /* CONTROL_TEST_KEY_4 */
+    case 0x344:        /* CONTROL_TEST_KEY_5 */
+    case 0x348:        /* CONTROL_TEST_KEY_6 */
+    case 0x34c:        /* CONTROL_TEST_KEY_7 */
+    case 0x350:        /* CONTROL_TEST_KEY_8 */
+    case 0x354:        /* CONTROL_TEST_KEY_9 */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x010:        /* CONTROL_SYSCONFIG */
+        s->sysconfig = value & 0x1e;
+        break;
+
+    case 0x030 ... 0x140:      /* CONTROL_PADCONF - only used in the POP */
+        /* XXX: should check constant bits */
+        s->padconf[(addr - 0x30) >> 2] = value & 0x1f1f1f1f;
+        break;
+
+    case 0x270:        /* CONTROL_DEBOBS */
+        s->obs = value & 0xff;
+        break;
+
+    case 0x274:        /* CONTROL_DEVCONF */
+        s->devconfig = value & 0xffffc7ff;
+        break;
+
+    case 0x28c:        /* CONTROL_EMU_SUPPORT */
+        break;
+
+    case 0x290:        /* CONTROL_MSUSPENDMUX_0 */
+        s->msuspendmux[0] = value & 0x3fffffff;
+        break;
+    case 0x294:        /* CONTROL_MSUSPENDMUX_1 */
+        s->msuspendmux[1] = value & 0x3fffffff;
+        break;
+    case 0x298:        /* CONTROL_MSUSPENDMUX_2 */
+        s->msuspendmux[2] = value & 0x3fffffff;
+        break;
+    case 0x29c:        /* CONTROL_MSUSPENDMUX_3 */
+        s->msuspendmux[3] = value & 0x3fffffff;
+        break;
+    case 0x2a0:        /* CONTROL_MSUSPENDMUX_4 */
+        s->msuspendmux[4] = value & 0x3fffffff;
+        break;
+
+    case 0x2b8:        /* CONTROL_PSA_CTRL */
+        s->psaconfig = value & 0x1c;
+        s->psaconfig |= (value & 0x20) ? 2 : 1;
+        break;
+    case 0x2bc:        /* CONTROL_PSA_CMD */
+        break;
+
+    case 0x2b0:        /* CONTROL_SEC_CTRL */
+    case 0x2b4:        /* CONTROL_SEC_TEST */
+    case 0x2d0:        /* CONTROL_SEC_EMU */
+    case 0x2d4:        /* CONTROL_SEC_TAP */
+    case 0x2d8:        /* CONTROL_OCM_RAM_PERM */
+    case 0x2dc:        /* CONTROL_OCM_PUB_RAM_ADD */
+    case 0x2e0:        /* CONTROL_EXT_SEC_RAM_START_ADD */
+    case 0x2e4:        /* CONTROL_EXT_SEC_RAM_STOP_ADD */
+    case 0x2f0:        /* CONTROL_SEC_STATUS */
+    case 0x2f4:        /* CONTROL_SEC_ERR_STATUS */
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_sysctl_ops = {
+    .old_mmio = {
+        .read = {
+            omap_sysctl_read8,
+            omap_badwidth_read32,      /* TODO */
+            omap_sysctl_read,
+        },
+        .write = {
+            omap_sysctl_write8,
+            omap_badwidth_write32,     /* TODO */
+            omap_sysctl_write,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_sysctl_reset(struct omap_sysctl_s *s)
+{
+    /* (power-on reset) */
+    s->sysconfig = 0;
+    s->obs = 0;
+    s->devconfig = 0x0c000000;
+    s->msuspendmux[0] = 0x00000000;
+    s->msuspendmux[1] = 0x00000000;
+    s->msuspendmux[2] = 0x00000000;
+    s->msuspendmux[3] = 0x00000000;
+    s->msuspendmux[4] = 0x00000000;
+    s->psaconfig = 1;
+
+    s->padconf[0x00] = 0x000f0f0f;
+    s->padconf[0x01] = 0x00000000;
+    s->padconf[0x02] = 0x00000000;
+    s->padconf[0x03] = 0x00000000;
+    s->padconf[0x04] = 0x00000000;
+    s->padconf[0x05] = 0x00000000;
+    s->padconf[0x06] = 0x00000000;
+    s->padconf[0x07] = 0x00000000;
+    s->padconf[0x08] = 0x08080800;
+    s->padconf[0x09] = 0x08080808;
+    s->padconf[0x0a] = 0x08080808;
+    s->padconf[0x0b] = 0x08080808;
+    s->padconf[0x0c] = 0x08080808;
+    s->padconf[0x0d] = 0x08080800;
+    s->padconf[0x0e] = 0x08080808;
+    s->padconf[0x0f] = 0x08080808;
+    s->padconf[0x10] = 0x18181808;     /* | 0x07070700 if SBoot3 */
+    s->padconf[0x11] = 0x18181818;     /* | 0x07070707 if SBoot3 */
+    s->padconf[0x12] = 0x18181818;     /* | 0x07070707 if SBoot3 */
+    s->padconf[0x13] = 0x18181818;     /* | 0x07070707 if SBoot3 */
+    s->padconf[0x14] = 0x18181818;     /* | 0x00070707 if SBoot3 */
+    s->padconf[0x15] = 0x18181818;
+    s->padconf[0x16] = 0x18181818;     /* | 0x07000000 if SBoot3 */
+    s->padconf[0x17] = 0x1f001f00;
+    s->padconf[0x18] = 0x1f1f1f1f;
+    s->padconf[0x19] = 0x00000000;
+    s->padconf[0x1a] = 0x1f180000;
+    s->padconf[0x1b] = 0x00001f1f;
+    s->padconf[0x1c] = 0x1f001f00;
+    s->padconf[0x1d] = 0x00000000;
+    s->padconf[0x1e] = 0x00000000;
+    s->padconf[0x1f] = 0x08000000;
+    s->padconf[0x20] = 0x08080808;
+    s->padconf[0x21] = 0x08080808;
+    s->padconf[0x22] = 0x0f080808;
+    s->padconf[0x23] = 0x0f0f0f0f;
+    s->padconf[0x24] = 0x000f0f0f;
+    s->padconf[0x25] = 0x1f1f1f0f;
+    s->padconf[0x26] = 0x080f0f1f;
+    s->padconf[0x27] = 0x070f1808;
+    s->padconf[0x28] = 0x0f070707;
+    s->padconf[0x29] = 0x000f0f1f;
+    s->padconf[0x2a] = 0x0f0f0f1f;
+    s->padconf[0x2b] = 0x08000000;
+    s->padconf[0x2c] = 0x0000001f;
+    s->padconf[0x2d] = 0x0f0f1f00;
+    s->padconf[0x2e] = 0x1f1f0f0f;
+    s->padconf[0x2f] = 0x0f1f1f1f;
+    s->padconf[0x30] = 0x0f0f0f0f;
+    s->padconf[0x31] = 0x0f1f0f1f;
+    s->padconf[0x32] = 0x0f0f0f0f;
+    s->padconf[0x33] = 0x0f1f0f1f;
+    s->padconf[0x34] = 0x1f1f0f0f;
+    s->padconf[0x35] = 0x0f0f1f1f;
+    s->padconf[0x36] = 0x0f0f1f0f;
+    s->padconf[0x37] = 0x0f0f0f0f;
+    s->padconf[0x38] = 0x1f18180f;
+    s->padconf[0x39] = 0x1f1f1f1f;
+    s->padconf[0x3a] = 0x00001f1f;
+    s->padconf[0x3b] = 0x00000000;
+    s->padconf[0x3c] = 0x00000000;
+    s->padconf[0x3d] = 0x0f0f0f0f;
+    s->padconf[0x3e] = 0x18000f0f;
+    s->padconf[0x3f] = 0x00070000;
+    s->padconf[0x40] = 0x00000707;
+    s->padconf[0x41] = 0x0f1f0700;
+    s->padconf[0x42] = 0x1f1f070f;
+    s->padconf[0x43] = 0x0008081f;
+    s->padconf[0x44] = 0x00000800;
+}
+
+static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
+                omap_clk iclk, struct omap_mpu_state_s *mpu)
+{
+    struct omap_sysctl_s *s = (struct omap_sysctl_s *)
+            g_malloc0(sizeof(struct omap_sysctl_s));
+
+    s->mpu = mpu;
+    omap_sysctl_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_sysctl_ops, s, "omap.sysctl",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
+
+    return s;
+}
+
+/* General chip reset */
+static void omap2_mpu_reset(void *opaque)
+{
+    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
+
+    omap_dma_reset(mpu->dma);
+    omap_prcm_reset(mpu->prcm);
+    omap_sysctl_reset(mpu->sysc);
+    omap_gp_timer_reset(mpu->gptimer[0]);
+    omap_gp_timer_reset(mpu->gptimer[1]);
+    omap_gp_timer_reset(mpu->gptimer[2]);
+    omap_gp_timer_reset(mpu->gptimer[3]);
+    omap_gp_timer_reset(mpu->gptimer[4]);
+    omap_gp_timer_reset(mpu->gptimer[5]);
+    omap_gp_timer_reset(mpu->gptimer[6]);
+    omap_gp_timer_reset(mpu->gptimer[7]);
+    omap_gp_timer_reset(mpu->gptimer[8]);
+    omap_gp_timer_reset(mpu->gptimer[9]);
+    omap_gp_timer_reset(mpu->gptimer[10]);
+    omap_gp_timer_reset(mpu->gptimer[11]);
+    omap_synctimer_reset(mpu->synctimer);
+    omap_sdrc_reset(mpu->sdrc);
+    omap_gpmc_reset(mpu->gpmc);
+    omap_dss_reset(mpu->dss);
+    omap_uart_reset(mpu->uart[0]);
+    omap_uart_reset(mpu->uart[1]);
+    omap_uart_reset(mpu->uart[2]);
+    omap_mmc_reset(mpu->mmc);
+    omap_mcspi_reset(mpu->mcspi[0]);
+    omap_mcspi_reset(mpu->mcspi[1]);
+    cpu_reset(CPU(mpu->cpu));
+}
+
+static int omap2_validate_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return 1;
+}
+
+static const struct dma_irq_map omap2_dma_irq_map[] = {
+    { 0, OMAP_INT_24XX_SDMA_IRQ0 },
+    { 0, OMAP_INT_24XX_SDMA_IRQ1 },
+    { 0, OMAP_INT_24XX_SDMA_IRQ2 },
+    { 0, OMAP_INT_24XX_SDMA_IRQ3 },
+};
+
+struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
+                unsigned long sdram_size,
+                const char *core)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
+            g_malloc0(sizeof(struct omap_mpu_state_s));
+    qemu_irq *cpu_irq;
+    qemu_irq dma_irqs[4];
+    DriveInfo *dinfo;
+    int i;
+    SysBusDevice *busdev;
+    struct omap_target_agent_s *ta;
+
+    /* Core */
+    s->mpu_model = omap2420;
+    s->cpu = cpu_arm_init(core ?: "arm1136-r2");
+    if (s->cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    s->sdram_size = sdram_size;
+    s->sram_size = OMAP242X_SRAM_SIZE;
+
+    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
+
+    /* Clocks */
+    omap_clk_init(s);
+
+    /* Memory-mapped stuff */
+    memory_region_init_ram(&s->sdram, "omap2.dram", s->sdram_size);
+    vmstate_register_ram_global(&s->sdram);
+    memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
+    memory_region_init_ram(&s->sram, "omap2.sram", s->sram_size);
+    vmstate_register_ram_global(&s->sram);
+    memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
+
+    s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
+
+    /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
+    cpu_irq = arm_pic_init_cpu(s->cpu);
+    s->ih[0] = qdev_create(NULL, "omap2-intc");
+    qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
+    qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
+    qdev_prop_set_ptr(s->ih[0], "iclk", omap_findclk(s, "mpu_intc_iclk"));
+    qdev_init_nofail(s->ih[0]);
+    busdev = SYS_BUS_DEVICE(s->ih[0]);
+    sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
+    sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
+    sysbus_mmio_map(busdev, 0, 0x480fe000);
+    s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
+                             qdev_get_gpio_in(s->ih[0],
+                                              OMAP_INT_24XX_PRCM_MPU_IRQ),
+                             NULL, NULL, s);
+
+    s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1),
+                    omap_findclk(s, "omapctrl_iclk"), s);
+
+    for (i = 0; i < 4; i++) {
+        dma_irqs[i] = qdev_get_gpio_in(s->ih[omap2_dma_irq_map[i].ih],
+                                       omap2_dma_irq_map[i].intr);
+    }
+    s->dma = omap_dma4_init(0x48056000, dma_irqs, sysmem, s, 256, 32,
+                    omap_findclk(s, "sdma_iclk"),
+                    omap_findclk(s, "sdma_fclk"));
+    s->port->addr_valid = omap2_validate_addr;
+
+    /* Register SDRAM and SRAM ports for fast DMA transfers.  */
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram),
+                         OMAP2_Q2_BASE, s->sdram_size);
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
+                         OMAP2_SRAM_BASE, s->sram_size);
+
+    s->uart[0] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 19),
+                                 qdev_get_gpio_in(s->ih[0],
+                                                  OMAP_INT_24XX_UART1_IRQ),
+                    omap_findclk(s, "uart1_fclk"),
+                    omap_findclk(s, "uart1_iclk"),
+                    s->drq[OMAP24XX_DMA_UART1_TX],
+                    s->drq[OMAP24XX_DMA_UART1_RX],
+                    "uart1",
+                    serial_hds[0]);
+    s->uart[1] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 20),
+                                 qdev_get_gpio_in(s->ih[0],
+                                                  OMAP_INT_24XX_UART2_IRQ),
+                    omap_findclk(s, "uart2_fclk"),
+                    omap_findclk(s, "uart2_iclk"),
+                    s->drq[OMAP24XX_DMA_UART2_TX],
+                    s->drq[OMAP24XX_DMA_UART2_RX],
+                    "uart2",
+                    serial_hds[0] ? serial_hds[1] : NULL);
+    s->uart[2] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 21),
+                                 qdev_get_gpio_in(s->ih[0],
+                                                  OMAP_INT_24XX_UART3_IRQ),
+                    omap_findclk(s, "uart3_fclk"),
+                    omap_findclk(s, "uart3_iclk"),
+                    s->drq[OMAP24XX_DMA_UART3_TX],
+                    s->drq[OMAP24XX_DMA_UART3_RX],
+                    "uart3",
+                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
+
+    s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER1),
+                    omap_findclk(s, "wu_gpt1_clk"),
+                    omap_findclk(s, "wu_l4_iclk"));
+    s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER2),
+                    omap_findclk(s, "core_gpt2_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER3),
+                    omap_findclk(s, "core_gpt3_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER4),
+                    omap_findclk(s, "core_gpt4_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER5),
+                    omap_findclk(s, "core_gpt5_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER6),
+                    omap_findclk(s, "core_gpt6_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER7),
+                    omap_findclk(s, "core_gpt7_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER8),
+                    omap_findclk(s, "core_gpt8_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER9),
+                    omap_findclk(s, "core_gpt9_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER10),
+                    omap_findclk(s, "core_gpt10_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER11),
+                    omap_findclk(s, "core_gpt11_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER12),
+                    omap_findclk(s, "core_gpt12_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+
+    omap_tap_init(omap_l4ta(s->l4, 2), s);
+
+    s->synctimer = omap_synctimer_init(omap_l4tao(s->l4, 2), s,
+                    omap_findclk(s, "clk32-kHz"),
+                    omap_findclk(s, "core_l4_iclk"));
+
+    s->i2c[0] = qdev_create(NULL, "omap_i2c");
+    qdev_prop_set_uint8(s->i2c[0], "revision", 0x34);
+    qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk"));
+    qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk"));
+    qdev_init_nofail(s->i2c[0]);
+    busdev = SYS_BUS_DEVICE(s->i2c[0]);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ));
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]);
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C1_RX]);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 5), 0));
+
+    s->i2c[1] = qdev_create(NULL, "omap_i2c");
+    qdev_prop_set_uint8(s->i2c[1], "revision", 0x34);
+    qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk"));
+    qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk"));
+    qdev_init_nofail(s->i2c[1]);
+    busdev = SYS_BUS_DEVICE(s->i2c[1]);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ));
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]);
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C2_RX]);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 6), 0));
+
+    s->gpio = qdev_create(NULL, "omap2-gpio");
+    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
+    qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk"));
+    if (s->mpu_model == omap2430) {
+        qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
+    }
+    qdev_init_nofail(s->gpio);
+    busdev = SYS_BUS_DEVICE(s->gpio);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK1));
+    sysbus_connect_irq(busdev, 3,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK2));
+    sysbus_connect_irq(busdev, 6,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK3));
+    sysbus_connect_irq(busdev, 9,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK4));
+    if (s->mpu_model == omap2430) {
+        sysbus_connect_irq(busdev, 12,
+                           qdev_get_gpio_in(s->ih[0],
+                                            OMAP_INT_243X_GPIO_BANK5));
+    }
+    ta = omap_l4ta(s->l4, 3);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
+    sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
+    sysbus_mmio_map(busdev, 2, omap_l4_region_base(ta, 2));
+    sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
+    sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
+
+    s->sdrc = omap_sdrc_init(sysmem, 0x68009000);
+    s->gpmc = omap_gpmc_init(s, 0x6800a000,
+                             qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPMC_IRQ),
+                             s->drq[OMAP24XX_DMA_GPMC]);
+
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "qemu: missing SecureDigital device\n");
+        exit(1);
+    }
+    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), dinfo->bdrv,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
+                    &s->drq[OMAP24XX_DMA_MMC1_TX],
+                    omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
+
+    s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI1_IRQ),
+                    &s->drq[OMAP24XX_DMA_SPI1_TX0],
+                    omap_findclk(s, "spi1_fclk"),
+                    omap_findclk(s, "spi1_iclk"));
+    s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI2_IRQ),
+                    &s->drq[OMAP24XX_DMA_SPI2_TX0],
+                    omap_findclk(s, "spi2_fclk"),
+                    omap_findclk(s, "spi2_iclk"));
+
+    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), sysmem, 0x68000800,
+                    /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_DSS_IRQ),
+                           s->drq[OMAP24XX_DMA_DSS],
+                    omap_findclk(s, "dss_clk1"), omap_findclk(s, "dss_clk2"),
+                    omap_findclk(s, "dss_54m_clk"),
+                    omap_findclk(s, "dss_l3_iclk"),
+                    omap_findclk(s, "dss_l4_iclk"));
+
+    omap_sti_init(omap_l4ta(s->l4, 18), sysmem, 0x54000000,
+                  qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_STI),
+                  omap_findclk(s, "emul_ck"),
+                    serial_hds[0] && serial_hds[1] && serial_hds[2] ?
+                    serial_hds[3] : NULL);
+
+    s->eac = omap_eac_init(omap_l4ta(s->l4, 32),
+                           qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_EAC_IRQ),
+                    /* Ten consecutive lines */
+                    &s->drq[OMAP24XX_DMA_EAC_AC_RD],
+                    omap_findclk(s, "func_96m_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+
+    /* All register mappings (includin those not currenlty implemented):
+     * SystemControlMod        48000000 - 48000fff
+     * SystemControlL4 48001000 - 48001fff
+     * 32kHz Timer Mod 48004000 - 48004fff
+     * 32kHz Timer L4  48005000 - 48005fff
+     * PRCM ModA       48008000 - 480087ff
+     * PRCM ModB       48008800 - 48008fff
+     * PRCM L4         48009000 - 48009fff
+     * TEST-BCM Mod    48012000 - 48012fff
+     * TEST-BCM L4     48013000 - 48013fff
+     * TEST-TAP Mod    48014000 - 48014fff
+     * TEST-TAP L4     48015000 - 48015fff
+     * GPIO1 Mod       48018000 - 48018fff
+     * GPIO Top                48019000 - 48019fff
+     * GPIO2 Mod       4801a000 - 4801afff
+     * GPIO L4         4801b000 - 4801bfff
+     * GPIO3 Mod       4801c000 - 4801cfff
+     * GPIO4 Mod       4801e000 - 4801efff
+     * WDTIMER1 Mod    48020000 - 48010fff
+     * WDTIMER Top     48021000 - 48011fff
+     * WDTIMER2 Mod    48022000 - 48012fff
+     * WDTIMER L4      48023000 - 48013fff
+     * WDTIMER3 Mod    48024000 - 48014fff
+     * WDTIMER3 L4     48025000 - 48015fff
+     * WDTIMER4 Mod    48026000 - 48016fff
+     * WDTIMER4 L4     48027000 - 48017fff
+     * GPTIMER1 Mod    48028000 - 48018fff
+     * GPTIMER1 L4     48029000 - 48019fff
+     * GPTIMER2 Mod    4802a000 - 4801afff
+     * GPTIMER2 L4     4802b000 - 4801bfff
+     * L4-Config AP    48040000 - 480407ff
+     * L4-Config IP    48040800 - 48040fff
+     * L4-Config LA    48041000 - 48041fff
+     * ARM11ETB Mod    48048000 - 48049fff
+     * ARM11ETB L4     4804a000 - 4804afff
+     * DISPLAY Top     48050000 - 480503ff
+     * DISPLAY DISPC   48050400 - 480507ff
+     * DISPLAY RFBI    48050800 - 48050bff
+     * DISPLAY VENC    48050c00 - 48050fff
+     * DISPLAY L4      48051000 - 48051fff
+     * CAMERA Top      48052000 - 480523ff
+     * CAMERA core     48052400 - 480527ff
+     * CAMERA DMA      48052800 - 48052bff
+     * CAMERA MMU      48052c00 - 48052fff
+     * CAMERA L4       48053000 - 48053fff
+     * SDMA Mod                48056000 - 48056fff
+     * SDMA L4         48057000 - 48057fff
+     * SSI Top         48058000 - 48058fff
+     * SSI GDD         48059000 - 48059fff
+     * SSI Port1       4805a000 - 4805afff
+     * SSI Port2       4805b000 - 4805bfff
+     * SSI L4          4805c000 - 4805cfff
+     * USB Mod         4805e000 - 480fefff
+     * USB L4          4805f000 - 480fffff
+     * WIN_TRACER1 Mod 48060000 - 48060fff
+     * WIN_TRACER1 L4  48061000 - 48061fff
+     * WIN_TRACER2 Mod 48062000 - 48062fff
+     * WIN_TRACER2 L4  48063000 - 48063fff
+     * WIN_TRACER3 Mod 48064000 - 48064fff
+     * WIN_TRACER3 L4  48065000 - 48065fff
+     * WIN_TRACER4 Top 48066000 - 480660ff
+     * WIN_TRACER4 ETT 48066100 - 480661ff
+     * WIN_TRACER4 WT  48066200 - 480662ff
+     * WIN_TRACER4 L4  48067000 - 48067fff
+     * XTI Mod         48068000 - 48068fff
+     * XTI L4          48069000 - 48069fff
+     * UART1 Mod       4806a000 - 4806afff
+     * UART1 L4                4806b000 - 4806bfff
+     * UART2 Mod       4806c000 - 4806cfff
+     * UART2 L4                4806d000 - 4806dfff
+     * UART3 Mod       4806e000 - 4806efff
+     * UART3 L4                4806f000 - 4806ffff
+     * I2C1 Mod                48070000 - 48070fff
+     * I2C1 L4         48071000 - 48071fff
+     * I2C2 Mod                48072000 - 48072fff
+     * I2C2 L4         48073000 - 48073fff
+     * McBSP1 Mod      48074000 - 48074fff
+     * McBSP1 L4       48075000 - 48075fff
+     * McBSP2 Mod      48076000 - 48076fff
+     * McBSP2 L4       48077000 - 48077fff
+     * GPTIMER3 Mod    48078000 - 48078fff
+     * GPTIMER3 L4     48079000 - 48079fff
+     * GPTIMER4 Mod    4807a000 - 4807afff
+     * GPTIMER4 L4     4807b000 - 4807bfff
+     * GPTIMER5 Mod    4807c000 - 4807cfff
+     * GPTIMER5 L4     4807d000 - 4807dfff
+     * GPTIMER6 Mod    4807e000 - 4807efff
+     * GPTIMER6 L4     4807f000 - 4807ffff
+     * GPTIMER7 Mod    48080000 - 48080fff
+     * GPTIMER7 L4     48081000 - 48081fff
+     * GPTIMER8 Mod    48082000 - 48082fff
+     * GPTIMER8 L4     48083000 - 48083fff
+     * GPTIMER9 Mod    48084000 - 48084fff
+     * GPTIMER9 L4     48085000 - 48085fff
+     * GPTIMER10 Mod   48086000 - 48086fff
+     * GPTIMER10 L4    48087000 - 48087fff
+     * GPTIMER11 Mod   48088000 - 48088fff
+     * GPTIMER11 L4    48089000 - 48089fff
+     * GPTIMER12 Mod   4808a000 - 4808afff
+     * GPTIMER12 L4    4808b000 - 4808bfff
+     * EAC Mod         48090000 - 48090fff
+     * EAC L4          48091000 - 48091fff
+     * FAC Mod         48092000 - 48092fff
+     * FAC L4          48093000 - 48093fff
+     * MAILBOX Mod     48094000 - 48094fff
+     * MAILBOX L4      48095000 - 48095fff
+     * SPI1 Mod                48098000 - 48098fff
+     * SPI1 L4         48099000 - 48099fff
+     * SPI2 Mod                4809a000 - 4809afff
+     * SPI2 L4         4809b000 - 4809bfff
+     * MMC/SDIO Mod    4809c000 - 4809cfff
+     * MMC/SDIO L4     4809d000 - 4809dfff
+     * MS_PRO Mod      4809e000 - 4809efff
+     * MS_PRO L4       4809f000 - 4809ffff
+     * RNG Mod         480a0000 - 480a0fff
+     * RNG L4          480a1000 - 480a1fff
+     * DES3DES Mod     480a2000 - 480a2fff
+     * DES3DES L4      480a3000 - 480a3fff
+     * SHA1MD5 Mod     480a4000 - 480a4fff
+     * SHA1MD5 L4      480a5000 - 480a5fff
+     * AES Mod         480a6000 - 480a6fff
+     * AES L4          480a7000 - 480a7fff
+     * PKA Mod         480a8000 - 480a9fff
+     * PKA L4          480aa000 - 480aafff
+     * MG Mod          480b0000 - 480b0fff
+     * MG L4           480b1000 - 480b1fff
+     * HDQ/1-wire Mod  480b2000 - 480b2fff
+     * HDQ/1-wire L4   480b3000 - 480b3fff
+     * MPU interrupt   480fe000 - 480fefff
+     * STI channel base        54000000 - 5400ffff
+     * IVA RAM         5c000000 - 5c01ffff
+     * IVA ROM         5c020000 - 5c027fff
+     * IMG_BUF_A       5c040000 - 5c040fff
+     * IMG_BUF_B       5c042000 - 5c042fff
+     * VLCDS           5c048000 - 5c0487ff
+     * IMX_COEF                5c049000 - 5c04afff
+     * IMX_CMD         5c051000 - 5c051fff
+     * VLCDQ           5c053000 - 5c0533ff
+     * VLCDH           5c054000 - 5c054fff
+     * SEQ_CMD         5c055000 - 5c055fff
+     * IMX_REG         5c056000 - 5c0560ff
+     * VLCD_REG                5c056100 - 5c0561ff
+     * SEQ_REG         5c056200 - 5c0562ff
+     * IMG_BUF_REG     5c056300 - 5c0563ff
+     * SEQIRQ_REG      5c056400 - 5c0564ff
+     * OCP_REG         5c060000 - 5c060fff
+     * SYSC_REG                5c070000 - 5c070fff
+     * MMU_REG         5d000000 - 5d000fff
+     * sDMA R          68000400 - 680005ff
+     * sDMA W          68000600 - 680007ff
+     * Display Control 68000800 - 680009ff
+     * DSP subsystem   68000a00 - 68000bff
+     * MPU subsystem   68000c00 - 68000dff
+     * IVA subsystem   68001000 - 680011ff
+     * USB             68001200 - 680013ff
+     * Camera          68001400 - 680015ff
+     * VLYNQ (firewall)        68001800 - 68001bff
+     * VLYNQ           68001e00 - 68001fff
+     * SSI             68002000 - 680021ff
+     * L4              68002400 - 680025ff
+     * DSP (firewall)  68002800 - 68002bff
+     * DSP subsystem   68002e00 - 68002fff
+     * IVA (firewall)  68003000 - 680033ff
+     * IVA             68003600 - 680037ff
+     * GFX             68003a00 - 68003bff
+     * CMDWR emulation 68003c00 - 68003dff
+     * SMS             68004000 - 680041ff
+     * OCM             68004200 - 680043ff
+     * GPMC            68004400 - 680045ff
+     * RAM (firewall)  68005000 - 680053ff
+     * RAM (err login) 68005400 - 680057ff
+     * ROM (firewall)  68005800 - 68005bff
+     * ROM (err login) 68005c00 - 68005fff
+     * GPMC (firewall) 68006000 - 680063ff
+     * GPMC (err login)        68006400 - 680067ff
+     * SMS (err login) 68006c00 - 68006fff
+     * SMS registers   68008000 - 68008fff
+     * SDRC registers  68009000 - 68009fff
+     * GPMC registers  6800a000   6800afff
+     */
+
+    qemu_register_reset(omap2_mpu_reset, s);
+
+    return s;
+}
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
new file mode 100644 (file)
index 0000000..8598233
--- /dev/null
@@ -0,0 +1,238 @@
+/* omap_sx1.c Support for the Siemens SX1 smartphone emulation.
+ *
+ *   Copyright (C) 2008
+ *     Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *   Copyright (C) 2007 Vladimir Ananiev <vovan888@gmail.com>
+ *
+ *   based on PalmOne's (TM) PDAs support (palm.c)
+ */
+
+/*
+ * PalmOne's (TM) PDAs.
+ *
+ * Copyright (C) 2006-2007 Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * 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 "hw/hw.h"
+#include "ui/console.h"
+#include "hw/omap.h"
+#include "hw/boards.h"
+#include "hw/arm-misc.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+/*****************************************************************************/
+/* Siemens SX1 Cellphone V1 */
+/* - ARM OMAP310 processor
+ * - SRAM                192 kB
+ * - SDRAM                32 MB at 0x10000000
+ * - Boot flash           16 MB at 0x00000000
+ * - Application flash     8 MB at 0x04000000
+ * - 3 serial ports
+ * - 1 SecureDigital
+ * - 1 LCD display
+ * - 1 RTC
+ */
+
+/*****************************************************************************/
+/* Siemens SX1 Cellphone V2 */
+/* - ARM OMAP310 processor
+ * - SRAM                192 kB
+ * - SDRAM                32 MB at 0x10000000
+ * - Boot flash           32 MB at 0x00000000
+ * - 3 serial ports
+ * - 1 SecureDigital
+ * - 1 LCD display
+ * - 1 RTC
+ */
+
+static uint64_t static_read(void *opaque, hwaddr offset,
+                            unsigned size)
+{
+    uint32_t *val = (uint32_t *) opaque;
+    uint32_t mask = (4 / size) - 1;
+
+    return *val >> ((offset & mask) << 3);
+}
+
+static void static_write(void *opaque, hwaddr offset,
+                         uint64_t value, unsigned size)
+{
+#ifdef SPY
+    printf("%s: value %" PRIx64 " %u bytes written at 0x%x\n",
+                    __func__, value, size, (int)offset);
+#endif
+}
+
+static const MemoryRegionOps static_ops = {
+    .read = static_read,
+    .write = static_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+#define sdram_size     0x02000000
+#define sector_size    (128 * 1024)
+#define flash0_size    (16 * 1024 * 1024)
+#define flash1_size    ( 8 * 1024 * 1024)
+#define flash2_size    (32 * 1024 * 1024)
+#define total_ram_v1   (sdram_size + flash0_size + flash1_size + OMAP15XX_SRAM_SIZE)
+#define total_ram_v2   (sdram_size + flash2_size + OMAP15XX_SRAM_SIZE)
+
+static struct arm_boot_info sx1_binfo = {
+    .loader_start = OMAP_EMIFF_BASE,
+    .ram_size = sdram_size,
+    .board_id = 0x265,
+};
+
+static void sx1_init(QEMUMachineInitArgs *args, const int version)
+{
+    struct omap_mpu_state_s *mpu;
+    MemoryRegion *address_space = get_system_memory();
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
+    MemoryRegion *cs = g_new(MemoryRegion, 4);
+    static uint32_t cs0val = 0x00213090;
+    static uint32_t cs1val = 0x00215070;
+    static uint32_t cs2val = 0x00001139;
+    static uint32_t cs3val = 0x00001139;
+    DriveInfo *dinfo;
+    int fl_idx;
+    uint32_t flash_size = flash0_size;
+    int be;
+
+    if (version == 2) {
+        flash_size = flash2_size;
+    }
+
+    mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, args->cpu_model);
+
+    /* External Flash (EMIFS) */
+    memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size);
+    vmstate_register_ram_global(flash);
+    memory_region_set_readonly(flash, true);
+    memory_region_add_subregion(address_space, OMAP_CS0_BASE, flash);
+
+    memory_region_init_io(&cs[0], &static_ops, &cs0val,
+                          "sx1.cs0", OMAP_CS0_SIZE - flash_size);
+    memory_region_add_subregion(address_space,
+                                OMAP_CS0_BASE + flash_size, &cs[0]);
+
+
+    memory_region_init_io(&cs[2], &static_ops, &cs2val,
+                          "sx1.cs2", OMAP_CS2_SIZE);
+    memory_region_add_subregion(address_space,
+                                OMAP_CS2_BASE, &cs[2]);
+
+    memory_region_init_io(&cs[3], &static_ops, &cs3val,
+                          "sx1.cs3", OMAP_CS3_SIZE);
+    memory_region_add_subregion(address_space,
+                                OMAP_CS2_BASE, &cs[3]);
+
+    fl_idx = 0;
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+
+    if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
+        if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL,
+                                   "omap_sx1.flash0-1", flash_size,
+                                   dinfo->bdrv, sector_size,
+                                   flash_size / sector_size,
+                                   4, 0, 0, 0, 0, be)) {
+            fprintf(stderr, "qemu: Error registering flash memory %d.\n",
+                           fl_idx);
+        }
+        fl_idx++;
+    }
+
+    if ((version == 1) &&
+            (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
+        memory_region_init_ram(flash_1, "omap_sx1.flash1-0", flash1_size);
+        vmstate_register_ram_global(flash_1);
+        memory_region_set_readonly(flash_1, true);
+        memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1);
+
+        memory_region_init_io(&cs[1], &static_ops, &cs1val,
+                              "sx1.cs1", OMAP_CS1_SIZE - flash1_size);
+        memory_region_add_subregion(address_space,
+                                OMAP_CS1_BASE + flash1_size, &cs[1]);
+
+        if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
+                                   "omap_sx1.flash1-1", flash1_size,
+                                   dinfo->bdrv, sector_size,
+                                   flash1_size / sector_size,
+                                   4, 0, 0, 0, 0, be)) {
+            fprintf(stderr, "qemu: Error registering flash memory %d.\n",
+                           fl_idx);
+        }
+        fl_idx++;
+    } else {
+        memory_region_init_io(&cs[1], &static_ops, &cs1val,
+                              "sx1.cs1", OMAP_CS1_SIZE);
+        memory_region_add_subregion(address_space,
+                                OMAP_CS1_BASE, &cs[1]);
+    }
+
+    if (!args->kernel_filename && !fl_idx) {
+        fprintf(stderr, "Kernel or Flash image must be specified\n");
+        exit(1);
+    }
+
+    /* Load the kernel.  */
+    if (args->kernel_filename) {
+        sx1_binfo.kernel_filename = args->kernel_filename;
+        sx1_binfo.kernel_cmdline = args->kernel_cmdline;
+        sx1_binfo.initrd_filename = args->initrd_filename;
+        arm_load_kernel(mpu->cpu, &sx1_binfo);
+    }
+
+    /* TODO: fix next line */
+    //~ qemu_console_resize(ds, 640, 480);
+}
+
+static void sx1_init_v1(QEMUMachineInitArgs *args)
+{
+    sx1_init(args, 1);
+}
+
+static void sx1_init_v2(QEMUMachineInitArgs *args)
+{
+    sx1_init(args, 2);
+}
+
+static QEMUMachine sx1_machine_v2 = {
+    .name = "sx1",
+    .desc = "Siemens SX1 (OMAP310) V2",
+    .init = sx1_init_v2,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine sx1_machine_v1 = {
+    .name = "sx1-v1",
+    .desc = "Siemens SX1 (OMAP310) V1",
+    .init = sx1_init_v1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void sx1_machine_init(void)
+{
+    qemu_register_machine(&sx1_machine_v2);
+    qemu_register_machine(&sx1_machine_v1);
+}
+
+machine_init(sx1_machine_init);
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
new file mode 100644 (file)
index 0000000..91bc74a
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * PalmOne's (TM) PDAs.
+ *
+ * Copyright (C) 2006-2007 Andrzej Zaborowski  <balrog@zabor.org>
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * 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 "hw/hw.h"
+#include "audio/audio.h"
+#include "sysemu/sysemu.h"
+#include "ui/console.h"
+#include "hw/omap.h"
+#include "hw/boards.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/loader.h"
+#include "exec/address-spaces.h"
+
+static uint32_t static_readb(void *opaque, hwaddr offset)
+{
+    uint32_t *val = (uint32_t *) opaque;
+    return *val >> ((offset & 3) << 3);
+}
+
+static uint32_t static_readh(void *opaque, hwaddr offset)
+{
+    uint32_t *val = (uint32_t *) opaque;
+    return *val >> ((offset & 1) << 3);
+}
+
+static uint32_t static_readw(void *opaque, hwaddr offset)
+{
+    uint32_t *val = (uint32_t *) opaque;
+    return *val >> ((offset & 0) << 3);
+}
+
+static void static_write(void *opaque, hwaddr offset,
+                uint32_t value)
+{
+#ifdef SPY
+    printf("%s: value %08lx written at " PA_FMT "\n",
+                    __FUNCTION__, value, offset);
+#endif
+}
+
+static const MemoryRegionOps static_ops = {
+    .old_mmio = {
+        .read = { static_readb, static_readh, static_readw, },
+        .write = { static_write, static_write, static_write, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+/* Palm Tunsgten|E support */
+
+/* Shared GPIOs */
+#define PALMTE_USBDETECT_GPIO  0
+#define PALMTE_USB_OR_DC_GPIO  1
+#define PALMTE_TSC_GPIO                4
+#define PALMTE_PINTDAV_GPIO    6
+#define PALMTE_MMC_WP_GPIO     8
+#define PALMTE_MMC_POWER_GPIO  9
+#define PALMTE_HDQ_GPIO                11
+#define PALMTE_HEADPHONES_GPIO 14
+#define PALMTE_SPEAKER_GPIO    15
+/* MPU private GPIOs */
+#define PALMTE_DC_GPIO         2
+#define PALMTE_MMC_SWITCH_GPIO 4
+#define PALMTE_MMC1_GPIO       6
+#define PALMTE_MMC2_GPIO       7
+#define PALMTE_MMC3_GPIO       11
+
+static MouseTransformInfo palmte_pointercal = {
+    .x = 320,
+    .y = 320,
+    .a = { -5909, 8, 22465308, 104, 7644, -1219972, 65536 },
+};
+
+static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
+{
+    uWireSlave *tsc;
+
+    tsc = tsc2102_init(qdev_get_gpio_in(cpu->gpio, PALMTE_PINTDAV_GPIO));
+
+    omap_uwire_attach(cpu->microwire, tsc, 0);
+    omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
+
+    tsc210x_set_transform(tsc, &palmte_pointercal);
+}
+
+static struct {
+    int row;
+    int column;
+} palmte_keymap[0x80] = {
+    [0 ... 0x7f] = { -1, -1 },
+    [0x3b] = { 0, 0 }, /* F1   -> Calendar */
+    [0x3c] = { 1, 0 }, /* F2   -> Contacts */
+    [0x3d] = { 2, 0 }, /* F3   -> Tasks List */
+    [0x3e] = { 3, 0 }, /* F4   -> Note Pad */
+    [0x01] = { 4, 0 }, /* Esc  -> Power */
+    [0x4b] = { 0, 1 }, /*         Left */
+    [0x50] = { 1, 1 }, /*         Down */
+    [0x48] = { 2, 1 }, /*         Up */
+    [0x4d] = { 3, 1 }, /*         Right */
+    [0x4c] = { 4, 1 }, /*         Centre */
+    [0x39] = { 4, 1 }, /* Spc  -> Centre */
+};
+
+static void palmte_button_event(void *opaque, int keycode)
+{
+    struct omap_mpu_state_s *cpu = (struct omap_mpu_state_s *) opaque;
+
+    if (palmte_keymap[keycode & 0x7f].row != -1)
+        omap_mpuio_key(cpu->mpuio,
+                        palmte_keymap[keycode & 0x7f].row,
+                        palmte_keymap[keycode & 0x7f].column,
+                        !(keycode & 0x80));
+}
+
+static void palmte_onoff_gpios(void *opaque, int line, int level)
+{
+    switch (line) {
+    case 0:
+        printf("%s: current to MMC/SD card %sabled.\n",
+                        __FUNCTION__, level ? "dis" : "en");
+        break;
+    case 1:
+        printf("%s: internal speaker amplifier %s.\n",
+                        __FUNCTION__, level ? "down" : "on");
+        break;
+
+    /* These LCD & Audio output signals have not been identified yet.  */
+    case 2:
+    case 3:
+    case 4:
+        printf("%s: LCD GPIO%i %s.\n",
+                        __FUNCTION__, line - 1, level ? "high" : "low");
+        break;
+    case 5:
+    case 6:
+        printf("%s: Audio GPIO%i %s.\n",
+                        __FUNCTION__, line - 4, level ? "high" : "low");
+        break;
+    }
+}
+
+static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
+{
+    qemu_irq *misc_gpio;
+
+    omap_mmc_handlers(cpu->mmc,
+                    qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO),
+                    qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
+                            [PALMTE_MMC_SWITCH_GPIO]));
+
+    misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
+    qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO,    misc_gpio[0]);
+    qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,      misc_gpio[1]);
+    qdev_connect_gpio_out(cpu->gpio, 11,                       misc_gpio[2]);
+    qdev_connect_gpio_out(cpu->gpio, 12,                       misc_gpio[3]);
+    qdev_connect_gpio_out(cpu->gpio, 13,                       misc_gpio[4]);
+    omap_mpuio_out_set(cpu->mpuio, 1,                          misc_gpio[5]);
+    omap_mpuio_out_set(cpu->mpuio, 3,                          misc_gpio[6]);
+
+    /* Reset some inputs to initial state.  */
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USB_OR_DC_GPIO));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, 4));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_HEADPHONES_GPIO));
+    qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]);
+    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]);
+    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]);
+    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[11]);
+}
+
+static struct arm_boot_info palmte_binfo = {
+    .loader_start = OMAP_EMIFF_BASE,
+    .ram_size = 0x02000000,
+    .board_id = 0x331,
+};
+
+static void palmte_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    struct omap_mpu_state_s *mpu;
+    int flash_size = 0x00800000;
+    int sdram_size = palmte_binfo.ram_size;
+    static uint32_t cs0val = 0xffffffff;
+    static uint32_t cs1val = 0x0000e1a0;
+    static uint32_t cs2val = 0x0000e1a0;
+    static uint32_t cs3val = 0xe1a0e1a0;
+    int rom_size, rom_loaded = 0;
+    DisplayState *ds = get_displaystate();
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    MemoryRegion *cs = g_new(MemoryRegion, 4);
+
+    mpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model);
+
+    /* External Flash (EMIFS) */
+    memory_region_init_ram(flash, "palmte.flash", flash_size);
+    vmstate_register_ram_global(flash);
+    memory_region_set_readonly(flash, true);
+    memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash);
+
+    memory_region_init_io(&cs[0], &static_ops, &cs0val, "palmte-cs0",
+                          OMAP_CS0_SIZE - flash_size);
+    memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE + flash_size,
+                                &cs[0]);
+    memory_region_init_io(&cs[1], &static_ops, &cs1val, "palmte-cs1",
+                          OMAP_CS1_SIZE);
+    memory_region_add_subregion(address_space_mem, OMAP_CS1_BASE, &cs[1]);
+    memory_region_init_io(&cs[2], &static_ops, &cs2val, "palmte-cs2",
+                          OMAP_CS2_SIZE);
+    memory_region_add_subregion(address_space_mem, OMAP_CS2_BASE, &cs[2]);
+    memory_region_init_io(&cs[3], &static_ops, &cs3val, "palmte-cs3",
+                          OMAP_CS3_SIZE);
+    memory_region_add_subregion(address_space_mem, OMAP_CS3_BASE, &cs[3]);
+
+    palmte_microwire_setup(mpu);
+
+    qemu_add_kbd_event_handler(palmte_button_event, mpu);
+
+    palmte_gpio_setup(mpu);
+
+    /* Setup initial (reset) machine state */
+    if (nb_option_roms) {
+        rom_size = get_image_size(option_rom[0].name);
+        if (rom_size > flash_size) {
+            fprintf(stderr, "%s: ROM image too big (%x > %x)\n",
+                            __FUNCTION__, rom_size, flash_size);
+            rom_size = 0;
+        }
+        if (rom_size > 0) {
+            rom_size = load_image_targphys(option_rom[0].name, OMAP_CS0_BASE,
+                                           flash_size);
+            rom_loaded = 1;
+        }
+        if (rom_size < 0) {
+            fprintf(stderr, "%s: error loading '%s'\n",
+                            __FUNCTION__, option_rom[0].name);
+        }
+    }
+
+    if (!rom_loaded && !kernel_filename) {
+        fprintf(stderr, "Kernel or ROM image must be specified\n");
+        exit(1);
+    }
+
+    /* Load the kernel.  */
+    if (kernel_filename) {
+        palmte_binfo.kernel_filename = kernel_filename;
+        palmte_binfo.kernel_cmdline = kernel_cmdline;
+        palmte_binfo.initrd_filename = initrd_filename;
+        arm_load_kernel(mpu->cpu, &palmte_binfo);
+    }
+
+    /* FIXME: We shouldn't really be doing this here.  The LCD controller
+       will set the size once configured, so this just sets an initial
+       size until the guest activates the display.  */
+    ds->surface = qemu_resize_displaysurface(ds, 320, 320);
+    dpy_gfx_resize(ds);
+}
+
+static QEMUMachine palmte_machine = {
+    .name = "cheetah",
+    .desc = "Palm Tungsten|E aka. Cheetah PDA (OMAP310)",
+    .init = palmte_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void palmte_machine_init(void)
+{
+    qemu_register_machine(&palmte_machine);
+}
+
+machine_init(palmte_machine_init);
diff --git a/hw/arm/pic_cpu.c b/hw/arm/pic_cpu.c
new file mode 100644 (file)
index 0000000..8223600
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Generic ARM Programmable Interrupt Controller support.
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the LGPL
+ */
+
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
+#include "sysemu/kvm.h"
+
+/* Input 0 is IRQ and input 1 is FIQ.  */
+static void arm_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
+
+    switch (irq) {
+    case ARM_PIC_CPU_IRQ:
+        if (level)
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        else
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        break;
+    case ARM_PIC_CPU_FIQ:
+        if (level)
+            cpu_interrupt(env, CPU_INTERRUPT_FIQ);
+        else
+            cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
+        break;
+    default:
+        hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
+    }
+}
+
+static void kvm_arm_pic_cpu_handler(void *opaque, int irq, int level)
+{
+#ifdef CONFIG_KVM
+    ARMCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
+    int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
+
+    switch (irq) {
+    case ARM_PIC_CPU_IRQ:
+        kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
+        break;
+    case ARM_PIC_CPU_FIQ:
+        kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
+        break;
+    default:
+        hw_error("kvm_arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
+    }
+    kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
+    kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
+#endif
+}
+
+qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
+{
+    if (kvm_enabled()) {
+        return qemu_allocate_irqs(kvm_arm_pic_cpu_handler, cpu, 2);
+    }
+    return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
+}
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
new file mode 100644 (file)
index 0000000..c0f50c9
--- /dev/null
@@ -0,0 +1,2291 @@
+/*
+ * Intel XScale PXA255/270 processor support.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/pxa.h"
+#include "sysemu/sysemu.h"
+#include "hw/serial.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
+#include "char/char.h"
+#include "sysemu/blockdev.h"
+
+static struct {
+    hwaddr io_base;
+    int irqn;
+} pxa255_serial[] = {
+    { 0x40100000, PXA2XX_PIC_FFUART },
+    { 0x40200000, PXA2XX_PIC_BTUART },
+    { 0x40700000, PXA2XX_PIC_STUART },
+    { 0x41600000, PXA25X_PIC_HWUART },
+    { 0, 0 }
+}, pxa270_serial[] = {
+    { 0x40100000, PXA2XX_PIC_FFUART },
+    { 0x40200000, PXA2XX_PIC_BTUART },
+    { 0x40700000, PXA2XX_PIC_STUART },
+    { 0, 0 }
+};
+
+typedef struct PXASSPDef {
+    hwaddr io_base;
+    int irqn;
+} PXASSPDef;
+
+#if 0
+static PXASSPDef pxa250_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0, 0 }
+};
+#endif
+
+static PXASSPDef pxa255_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0x41400000, PXA25X_PIC_NSSP },
+    { 0, 0 }
+};
+
+#if 0
+static PXASSPDef pxa26x_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0x41400000, PXA25X_PIC_NSSP },
+    { 0x41500000, PXA26X_PIC_ASSP },
+    { 0, 0 }
+};
+#endif
+
+static PXASSPDef pxa27x_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0x41700000, PXA27X_PIC_SSP2 },
+    { 0x41900000, PXA2XX_PIC_SSP3 },
+    { 0, 0 }
+};
+
+#define PMCR   0x00    /* Power Manager Control register */
+#define PSSR   0x04    /* Power Manager Sleep Status register */
+#define PSPR   0x08    /* Power Manager Scratch-Pad register */
+#define PWER   0x0c    /* Power Manager Wake-Up Enable register */
+#define PRER   0x10    /* Power Manager Rising-Edge Detect Enable register */
+#define PFER   0x14    /* Power Manager Falling-Edge Detect Enable register */
+#define PEDR   0x18    /* Power Manager Edge-Detect Status register */
+#define PCFR   0x1c    /* Power Manager General Configuration register */
+#define PGSR0  0x20    /* Power Manager GPIO Sleep-State register 0 */
+#define PGSR1  0x24    /* Power Manager GPIO Sleep-State register 1 */
+#define PGSR2  0x28    /* Power Manager GPIO Sleep-State register 2 */
+#define PGSR3  0x2c    /* Power Manager GPIO Sleep-State register 3 */
+#define RCSR   0x30    /* Reset Controller Status register */
+#define PSLR   0x34    /* Power Manager Sleep Configuration register */
+#define PTSR   0x38    /* Power Manager Standby Configuration register */
+#define PVCR   0x40    /* Power Manager Voltage Change Control register */
+#define PUCR   0x4c    /* Power Manager USIM Card Control/Status register */
+#define PKWR   0x50    /* Power Manager Keyboard Wake-Up Enable register */
+#define PKSR   0x54    /* Power Manager Keyboard Level-Detect Status */
+#define PCMD0  0x80    /* Power Manager I2C Command register File 0 */
+#define PCMD31 0xfc    /* Power Manager I2C Command register File 31 */
+
+static uint64_t pxa2xx_pm_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case PMCR ... PCMD31:
+        if (addr & 3)
+            goto fail;
+
+        return s->pm_regs[addr >> 2];
+    default:
+    fail:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_pm_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case PMCR:
+        /* Clear the write-one-to-clear bits... */
+        s->pm_regs[addr >> 2] &= ~(value & 0x2a);
+        /* ...and set the plain r/w bits */
+        s->pm_regs[addr >> 2] &= ~0x15;
+        s->pm_regs[addr >> 2] |= value & 0x15;
+        break;
+
+    case PSSR: /* Read-clean registers */
+    case RCSR:
+    case PKSR:
+        s->pm_regs[addr >> 2] &= ~value;
+        break;
+
+    default:   /* Read-write registers */
+        if (!(addr & 3)) {
+            s->pm_regs[addr >> 2] = value;
+            break;
+        }
+
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps pxa2xx_pm_ops = {
+    .read = pxa2xx_pm_read,
+    .write = pxa2xx_pm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_pxa2xx_pm = {
+    .name = "pxa2xx_pm",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(pm_regs, PXA2xxState, 0x40),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+#define CCCR   0x00    /* Core Clock Configuration register */
+#define CKEN   0x04    /* Clock Enable register */
+#define OSCC   0x08    /* Oscillator Configuration register */
+#define CCSR   0x0c    /* Core Clock Status register */
+
+static uint64_t pxa2xx_cm_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case CCCR:
+    case CKEN:
+    case OSCC:
+        return s->cm_regs[addr >> 2];
+
+    case CCSR:
+        return s->cm_regs[CCCR >> 2] | (3 << 28);
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_cm_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case CCCR:
+    case CKEN:
+        s->cm_regs[addr >> 2] = value;
+        break;
+
+    case OSCC:
+        s->cm_regs[addr >> 2] &= ~0x6c;
+        s->cm_regs[addr >> 2] |= value & 0x6e;
+        if ((value >> 1) & 1)                  /* OON */
+            s->cm_regs[addr >> 2] |= 1 << 0;   /* Oscillator is now stable */
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps pxa2xx_cm_ops = {
+    .read = pxa2xx_cm_read,
+    .write = pxa2xx_cm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_pxa2xx_cm = {
+    .name = "pxa2xx_cm",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(cm_regs, PXA2xxState, 4),
+        VMSTATE_UINT32(clkcfg, PXA2xxState),
+        VMSTATE_UINT32(pmnc, PXA2xxState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int pxa2xx_clkcfg_read(CPUARMState *env, const ARMCPRegInfo *ri,
+                              uint64_t *value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    *value = s->clkcfg;
+    return 0;
+}
+
+static int pxa2xx_clkcfg_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                               uint64_t value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    s->clkcfg = value & 0xf;
+    if (value & 2) {
+        printf("%s: CPU frequency change attempt\n", __func__);
+    }
+    return 0;
+}
+
+static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                uint64_t value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    static const char *pwrmode[8] = {
+        "Normal", "Idle", "Deep-idle", "Standby",
+        "Sleep", "reserved (!)", "reserved (!)", "Deep-sleep",
+    };
+
+    if (value & 8) {
+        printf("%s: CPU voltage change attempt\n", __func__);
+    }
+    switch (value & 7) {
+    case 0:
+        /* Do nothing */
+        break;
+
+    case 1:
+        /* Idle */
+        if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */
+            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+            break;
+        }
+        /* Fall through.  */
+
+    case 2:
+        /* Deep-Idle */
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+        s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
+        goto message;
+
+    case 3:
+        s->cpu->env.uncached_cpsr =
+            ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
+        s->cpu->env.cp15.c1_sys = 0;
+        s->cpu->env.cp15.c1_coproc = 0;
+        s->cpu->env.cp15.c2_base0 = 0;
+        s->cpu->env.cp15.c3 = 0;
+        s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
+        s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
+
+        /*
+         * The scratch-pad register is almost universally used
+         * for storing the return address on suspend.  For the
+         * lack of a resuming bootloader, perform a jump
+         * directly to that address.
+         */
+        memset(s->cpu->env.regs, 0, 4 * 15);
+        s->cpu->env.regs[15] = s->pm_regs[PSPR >> 2];
+
+#if 0
+        buffer = 0xe59ff000; /* ldr     pc, [pc, #0] */
+        cpu_physical_memory_write(0, &buffer, 4);
+        buffer = s->pm_regs[PSPR >> 2];
+        cpu_physical_memory_write(8, &buffer, 4);
+#endif
+
+        /* Suspend */
+        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
+
+        goto message;
+
+    default:
+    message:
+        printf("%s: machine entered %s mode\n", __func__,
+               pwrmode[value & 7]);
+    }
+
+    return 0;
+}
+
+static int pxa2xx_cppmnc_read(CPUARMState *env, const ARMCPRegInfo *ri,
+                              uint64_t *value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    *value = s->pmnc;
+    return 0;
+}
+
+static int pxa2xx_cppmnc_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                               uint64_t value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    s->pmnc = value;
+    return 0;
+}
+
+static int pxa2xx_cpccnt_read(CPUARMState *env, const ARMCPRegInfo *ri,
+                              uint64_t *value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    if (s->pmnc & 1) {
+        *value = qemu_get_clock_ns(vm_clock);
+    } else {
+        *value = 0;
+    }
+    return 0;
+}
+
+static const ARMCPRegInfo pxa_cp_reginfo[] = {
+    /* cp14 crm==1: perf registers */
+    { .name = "CPPMNC", .cp = 14, .crn = 0, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW,
+      .readfn = pxa2xx_cppmnc_read, .writefn = pxa2xx_cppmnc_write },
+    { .name = "CPCCNT", .cp = 14, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW,
+      .readfn = pxa2xx_cpccnt_read, .writefn = arm_cp_write_ignore },
+    { .name = "CPINTEN", .cp = 14, .crn = 4, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPFLAG", .cp = 14, .crn = 5, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPEVTSEL", .cp = 14, .crn = 8, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    /* cp14 crm==2: performance count registers */
+    { .name = "CPPMN0", .cp = 14, .crn = 0, .crm = 2, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPPMN1", .cp = 14, .crn = 1, .crm = 2, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPPMN2", .cp = 14, .crn = 2, .crm = 2, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPPMN3", .cp = 14, .crn = 2, .crm = 3, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    /* cp14 crn==6: CLKCFG */
+    { .name = "CLKCFG", .cp = 14, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW,
+      .readfn = pxa2xx_clkcfg_read, .writefn = pxa2xx_clkcfg_write },
+    /* cp14 crn==7: PWRMODE */
+    { .name = "PWRMODE", .cp = 14, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW,
+      .readfn = arm_cp_read_zero, .writefn = pxa2xx_pwrmode_write },
+    REGINFO_SENTINEL
+};
+
+static void pxa2xx_setup_cp14(PXA2xxState *s)
+{
+    define_arm_cp_regs_with_opaque(s->cpu, pxa_cp_reginfo, s);
+}
+
+#define MDCNFG         0x00    /* SDRAM Configuration register */
+#define MDREFR         0x04    /* SDRAM Refresh Control register */
+#define MSC0           0x08    /* Static Memory Control register 0 */
+#define MSC1           0x0c    /* Static Memory Control register 1 */
+#define MSC2           0x10    /* Static Memory Control register 2 */
+#define MECR           0x14    /* Expansion Memory Bus Config register */
+#define SXCNFG         0x1c    /* Synchronous Static Memory Config register */
+#define MCMEM0         0x28    /* PC Card Memory Socket 0 Timing register */
+#define MCMEM1         0x2c    /* PC Card Memory Socket 1 Timing register */
+#define MCATT0         0x30    /* PC Card Attribute Socket 0 register */
+#define MCATT1         0x34    /* PC Card Attribute Socket 1 register */
+#define MCIO0          0x38    /* PC Card I/O Socket 0 Timing register */
+#define MCIO1          0x3c    /* PC Card I/O Socket 1 Timing register */
+#define MDMRS          0x40    /* SDRAM Mode Register Set Config register */
+#define BOOT_DEF       0x44    /* Boot-time Default Configuration register */
+#define ARB_CNTL       0x48    /* Arbiter Control register */
+#define BSCNTR0                0x4c    /* Memory Buffer Strength Control register 0 */
+#define BSCNTR1                0x50    /* Memory Buffer Strength Control register 1 */
+#define LCDBSCNTR      0x54    /* LCD Buffer Strength Control register */
+#define MDMRSLP                0x58    /* Low Power SDRAM Mode Set Config register */
+#define BSCNTR2                0x5c    /* Memory Buffer Strength Control register 2 */
+#define BSCNTR3                0x60    /* Memory Buffer Strength Control register 3 */
+#define SA1110         0x64    /* SA-1110 Memory Compatibility register */
+
+static uint64_t pxa2xx_mm_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case MDCNFG ... SA1110:
+        if ((addr & 3) == 0)
+            return s->mm_regs[addr >> 2];
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_mm_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case MDCNFG ... SA1110:
+        if ((addr & 3) == 0) {
+            s->mm_regs[addr >> 2] = value;
+            break;
+        }
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps pxa2xx_mm_ops = {
+    .read = pxa2xx_mm_read,
+    .write = pxa2xx_mm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_pxa2xx_mm = {
+    .name = "pxa2xx_mm",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(mm_regs, PXA2xxState, 0x1a),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+/* Synchronous Serial Ports */
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq irq;
+    int enable;
+    SSIBus *bus;
+
+    uint32_t sscr[2];
+    uint32_t sspsp;
+    uint32_t ssto;
+    uint32_t ssitr;
+    uint32_t sssr;
+    uint8_t sstsa;
+    uint8_t ssrsa;
+    uint8_t ssacd;
+
+    uint32_t rx_fifo[16];
+    int rx_level;
+    int rx_start;
+} PXA2xxSSPState;
+
+#define SSCR0  0x00    /* SSP Control register 0 */
+#define SSCR1  0x04    /* SSP Control register 1 */
+#define SSSR   0x08    /* SSP Status register */
+#define SSITR  0x0c    /* SSP Interrupt Test register */
+#define SSDR   0x10    /* SSP Data register */
+#define SSTO   0x28    /* SSP Time-Out register */
+#define SSPSP  0x2c    /* SSP Programmable Serial Protocol register */
+#define SSTSA  0x30    /* SSP TX Time Slot Active register */
+#define SSRSA  0x34    /* SSP RX Time Slot Active register */
+#define SSTSS  0x38    /* SSP Time Slot Status register */
+#define SSACD  0x3c    /* SSP Audio Clock Divider register */
+
+/* Bitfields for above registers */
+#define SSCR0_SPI(x)   (((x) & 0x30) == 0x00)
+#define SSCR0_SSP(x)   (((x) & 0x30) == 0x10)
+#define SSCR0_UWIRE(x) (((x) & 0x30) == 0x20)
+#define SSCR0_PSP(x)   (((x) & 0x30) == 0x30)
+#define SSCR0_SSE      (1 << 7)
+#define SSCR0_RIM      (1 << 22)
+#define SSCR0_TIM      (1 << 23)
+#define SSCR0_MOD      (1 << 31)
+#define SSCR0_DSS(x)   (((((x) >> 16) & 0x10) | ((x) & 0xf)) + 1)
+#define SSCR1_RIE      (1 << 0)
+#define SSCR1_TIE      (1 << 1)
+#define SSCR1_LBM      (1 << 2)
+#define SSCR1_MWDS     (1 << 5)
+#define SSCR1_TFT(x)   ((((x) >> 6) & 0xf) + 1)
+#define SSCR1_RFT(x)   ((((x) >> 10) & 0xf) + 1)
+#define SSCR1_EFWR     (1 << 14)
+#define SSCR1_PINTE    (1 << 18)
+#define SSCR1_TINTE    (1 << 19)
+#define SSCR1_RSRE     (1 << 20)
+#define SSCR1_TSRE     (1 << 21)
+#define SSCR1_EBCEI    (1 << 29)
+#define SSITR_INT      (7 << 5)
+#define SSSR_TNF       (1 << 2)
+#define SSSR_RNE       (1 << 3)
+#define SSSR_TFS       (1 << 5)
+#define SSSR_RFS       (1 << 6)
+#define SSSR_ROR       (1 << 7)
+#define SSSR_PINT      (1 << 18)
+#define SSSR_TINT      (1 << 19)
+#define SSSR_EOC       (1 << 20)
+#define SSSR_TUR       (1 << 21)
+#define SSSR_BCE       (1 << 23)
+#define SSSR_RW                0x00bc0080
+
+static void pxa2xx_ssp_int_update(PXA2xxSSPState *s)
+{
+    int level = 0;
+
+    level |= s->ssitr & SSITR_INT;
+    level |= (s->sssr & SSSR_BCE)  &&  (s->sscr[1] & SSCR1_EBCEI);
+    level |= (s->sssr & SSSR_TUR)  && !(s->sscr[0] & SSCR0_TIM);
+    level |= (s->sssr & SSSR_EOC)  &&  (s->sssr & (SSSR_TINT | SSSR_PINT));
+    level |= (s->sssr & SSSR_TINT) &&  (s->sscr[1] & SSCR1_TINTE);
+    level |= (s->sssr & SSSR_PINT) &&  (s->sscr[1] & SSCR1_PINTE);
+    level |= (s->sssr & SSSR_ROR)  && !(s->sscr[0] & SSCR0_RIM);
+    level |= (s->sssr & SSSR_RFS)  &&  (s->sscr[1] & SSCR1_RIE);
+    level |= (s->sssr & SSSR_TFS)  &&  (s->sscr[1] & SSCR1_TIE);
+    qemu_set_irq(s->irq, !!level);
+}
+
+static void pxa2xx_ssp_fifo_update(PXA2xxSSPState *s)
+{
+    s->sssr &= ~(0xf << 12);   /* Clear RFL */
+    s->sssr &= ~(0xf << 8);    /* Clear TFL */
+    s->sssr &= ~SSSR_TFS;
+    s->sssr &= ~SSSR_TNF;
+    if (s->enable) {
+        s->sssr |= ((s->rx_level - 1) & 0xf) << 12;
+        if (s->rx_level >= SSCR1_RFT(s->sscr[1]))
+            s->sssr |= SSSR_RFS;
+        else
+            s->sssr &= ~SSSR_RFS;
+        if (s->rx_level)
+            s->sssr |= SSSR_RNE;
+        else
+            s->sssr &= ~SSSR_RNE;
+        /* TX FIFO is never filled, so it is always in underrun
+           condition if SSP is enabled */
+        s->sssr |= SSSR_TFS;
+        s->sssr |= SSSR_TNF;
+    }
+
+    pxa2xx_ssp_int_update(s);
+}
+
+static uint64_t pxa2xx_ssp_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
+    uint32_t retval;
+
+    switch (addr) {
+    case SSCR0:
+        return s->sscr[0];
+    case SSCR1:
+        return s->sscr[1];
+    case SSPSP:
+        return s->sspsp;
+    case SSTO:
+        return s->ssto;
+    case SSITR:
+        return s->ssitr;
+    case SSSR:
+        return s->sssr | s->ssitr;
+    case SSDR:
+        if (!s->enable)
+            return 0xffffffff;
+        if (s->rx_level < 1) {
+            printf("%s: SSP Rx Underrun\n", __FUNCTION__);
+            return 0xffffffff;
+        }
+        s->rx_level --;
+        retval = s->rx_fifo[s->rx_start ++];
+        s->rx_start &= 0xf;
+        pxa2xx_ssp_fifo_update(s);
+        return retval;
+    case SSTSA:
+        return s->sstsa;
+    case SSRSA:
+        return s->ssrsa;
+    case SSTSS:
+        return 0;
+    case SSACD:
+        return s->ssacd;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_ssp_write(void *opaque, hwaddr addr,
+                             uint64_t value64, unsigned size)
+{
+    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
+    uint32_t value = value64;
+
+    switch (addr) {
+    case SSCR0:
+        s->sscr[0] = value & 0xc7ffffff;
+        s->enable = value & SSCR0_SSE;
+        if (value & SSCR0_MOD)
+            printf("%s: Attempt to use network mode\n", __FUNCTION__);
+        if (s->enable && SSCR0_DSS(value) < 4)
+            printf("%s: Wrong data size: %i bits\n", __FUNCTION__,
+                            SSCR0_DSS(value));
+        if (!(value & SSCR0_SSE)) {
+            s->sssr = 0;
+            s->ssitr = 0;
+            s->rx_level = 0;
+        }
+        pxa2xx_ssp_fifo_update(s);
+        break;
+
+    case SSCR1:
+        s->sscr[1] = value;
+        if (value & (SSCR1_LBM | SSCR1_EFWR))
+            printf("%s: Attempt to use SSP test mode\n", __FUNCTION__);
+        pxa2xx_ssp_fifo_update(s);
+        break;
+
+    case SSPSP:
+        s->sspsp = value;
+        break;
+
+    case SSTO:
+        s->ssto = value;
+        break;
+
+    case SSITR:
+        s->ssitr = value & SSITR_INT;
+        pxa2xx_ssp_int_update(s);
+        break;
+
+    case SSSR:
+        s->sssr &= ~(value & SSSR_RW);
+        pxa2xx_ssp_int_update(s);
+        break;
+
+    case SSDR:
+        if (SSCR0_UWIRE(s->sscr[0])) {
+            if (s->sscr[1] & SSCR1_MWDS)
+                value &= 0xffff;
+            else
+                value &= 0xff;
+        } else
+            /* Note how 32bits overflow does no harm here */
+            value &= (1 << SSCR0_DSS(s->sscr[0])) - 1;
+
+        /* Data goes from here to the Tx FIFO and is shifted out from
+         * there directly to the slave, no need to buffer it.
+         */
+        if (s->enable) {
+            uint32_t readval;
+            readval = ssi_transfer(s->bus, value);
+            if (s->rx_level < 0x10) {
+                s->rx_fifo[(s->rx_start + s->rx_level ++) & 0xf] = readval;
+            } else {
+                s->sssr |= SSSR_ROR;
+            }
+        }
+        pxa2xx_ssp_fifo_update(s);
+        break;
+
+    case SSTSA:
+        s->sstsa = value;
+        break;
+
+    case SSRSA:
+        s->ssrsa = value;
+        break;
+
+    case SSACD:
+        s->ssacd = value;
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps pxa2xx_ssp_ops = {
+    .read = pxa2xx_ssp_read,
+    .write = pxa2xx_ssp_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void pxa2xx_ssp_save(QEMUFile *f, void *opaque)
+{
+    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
+    int i;
+
+    qemu_put_be32(f, s->enable);
+
+    qemu_put_be32s(f, &s->sscr[0]);
+    qemu_put_be32s(f, &s->sscr[1]);
+    qemu_put_be32s(f, &s->sspsp);
+    qemu_put_be32s(f, &s->ssto);
+    qemu_put_be32s(f, &s->ssitr);
+    qemu_put_be32s(f, &s->sssr);
+    qemu_put_8s(f, &s->sstsa);
+    qemu_put_8s(f, &s->ssrsa);
+    qemu_put_8s(f, &s->ssacd);
+
+    qemu_put_byte(f, s->rx_level);
+    for (i = 0; i < s->rx_level; i ++)
+        qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 0xf]);
+}
+
+static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
+{
+    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
+    int i;
+
+    s->enable = qemu_get_be32(f);
+
+    qemu_get_be32s(f, &s->sscr[0]);
+    qemu_get_be32s(f, &s->sscr[1]);
+    qemu_get_be32s(f, &s->sspsp);
+    qemu_get_be32s(f, &s->ssto);
+    qemu_get_be32s(f, &s->ssitr);
+    qemu_get_be32s(f, &s->sssr);
+    qemu_get_8s(f, &s->sstsa);
+    qemu_get_8s(f, &s->ssrsa);
+    qemu_get_8s(f, &s->ssacd);
+
+    s->rx_level = qemu_get_byte(f);
+    s->rx_start = 0;
+    for (i = 0; i < s->rx_level; i ++)
+        s->rx_fifo[i] = qemu_get_byte(f);
+
+    return 0;
+}
+
+static int pxa2xx_ssp_init(SysBusDevice *dev)
+{
+    PXA2xxSSPState *s = FROM_SYSBUS(PXA2xxSSPState, dev);
+
+    sysbus_init_irq(dev, &s->irq);
+
+    memory_region_init_io(&s->iomem, &pxa2xx_ssp_ops, s, "pxa2xx-ssp", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
+                    pxa2xx_ssp_save, pxa2xx_ssp_load, s);
+
+    s->bus = ssi_create_bus(&dev->qdev, "ssi");
+    return 0;
+}
+
+/* Real-Time Clock */
+#define RCNR           0x00    /* RTC Counter register */
+#define RTAR           0x04    /* RTC Alarm register */
+#define RTSR           0x08    /* RTC Status register */
+#define RTTR           0x0c    /* RTC Timer Trim register */
+#define RDCR           0x10    /* RTC Day Counter register */
+#define RYCR           0x14    /* RTC Year Counter register */
+#define RDAR1          0x18    /* RTC Wristwatch Day Alarm register 1 */
+#define RYAR1          0x1c    /* RTC Wristwatch Year Alarm register 1 */
+#define RDAR2          0x20    /* RTC Wristwatch Day Alarm register 2 */
+#define RYAR2          0x24    /* RTC Wristwatch Year Alarm register 2 */
+#define SWCR           0x28    /* RTC Stopwatch Counter register */
+#define SWAR1          0x2c    /* RTC Stopwatch Alarm register 1 */
+#define SWAR2          0x30    /* RTC Stopwatch Alarm register 2 */
+#define RTCPICR                0x34    /* RTC Periodic Interrupt Counter register */
+#define PIAR           0x38    /* RTC Periodic Interrupt Alarm register */
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t rttr;
+    uint32_t rtsr;
+    uint32_t rtar;
+    uint32_t rdar1;
+    uint32_t rdar2;
+    uint32_t ryar1;
+    uint32_t ryar2;
+    uint32_t swar1;
+    uint32_t swar2;
+    uint32_t piar;
+    uint32_t last_rcnr;
+    uint32_t last_rdcr;
+    uint32_t last_rycr;
+    uint32_t last_swcr;
+    uint32_t last_rtcpicr;
+    int64_t last_hz;
+    int64_t last_sw;
+    int64_t last_pi;
+    QEMUTimer *rtc_hz;
+    QEMUTimer *rtc_rdal1;
+    QEMUTimer *rtc_rdal2;
+    QEMUTimer *rtc_swal1;
+    QEMUTimer *rtc_swal2;
+    QEMUTimer *rtc_pi;
+    qemu_irq rtc_irq;
+} PXA2xxRTCState;
+
+static inline void pxa2xx_rtc_int_update(PXA2xxRTCState *s)
+{
+    qemu_set_irq(s->rtc_irq, !!(s->rtsr & 0x2553));
+}
+
+static void pxa2xx_rtc_hzupdate(PXA2xxRTCState *s)
+{
+    int64_t rt = qemu_get_clock_ms(rtc_clock);
+    s->last_rcnr += ((rt - s->last_hz) << 15) /
+            (1000 * ((s->rttr & 0xffff) + 1));
+    s->last_rdcr += ((rt - s->last_hz) << 15) /
+            (1000 * ((s->rttr & 0xffff) + 1));
+    s->last_hz = rt;
+}
+
+static void pxa2xx_rtc_swupdate(PXA2xxRTCState *s)
+{
+    int64_t rt = qemu_get_clock_ms(rtc_clock);
+    if (s->rtsr & (1 << 12))
+        s->last_swcr += (rt - s->last_sw) / 10;
+    s->last_sw = rt;
+}
+
+static void pxa2xx_rtc_piupdate(PXA2xxRTCState *s)
+{
+    int64_t rt = qemu_get_clock_ms(rtc_clock);
+    if (s->rtsr & (1 << 15))
+        s->last_swcr += rt - s->last_pi;
+    s->last_pi = rt;
+}
+
+static inline void pxa2xx_rtc_alarm_update(PXA2xxRTCState *s,
+                uint32_t rtsr)
+{
+    if ((rtsr & (1 << 2)) && !(rtsr & (1 << 0)))
+        qemu_mod_timer(s->rtc_hz, s->last_hz +
+                (((s->rtar - s->last_rcnr) * 1000 *
+                  ((s->rttr & 0xffff) + 1)) >> 15));
+    else
+        qemu_del_timer(s->rtc_hz);
+
+    if ((rtsr & (1 << 5)) && !(rtsr & (1 << 4)))
+        qemu_mod_timer(s->rtc_rdal1, s->last_hz +
+                (((s->rdar1 - s->last_rdcr) * 1000 *
+                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_rdal1);
+
+    if ((rtsr & (1 << 7)) && !(rtsr & (1 << 6)))
+        qemu_mod_timer(s->rtc_rdal2, s->last_hz +
+                (((s->rdar2 - s->last_rdcr) * 1000 *
+                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_rdal2);
+
+    if ((rtsr & 0x1200) == 0x1200 && !(rtsr & (1 << 8)))
+        qemu_mod_timer(s->rtc_swal1, s->last_sw +
+                        (s->swar1 - s->last_swcr) * 10); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_swal1);
+
+    if ((rtsr & 0x1800) == 0x1800 && !(rtsr & (1 << 10)))
+        qemu_mod_timer(s->rtc_swal2, s->last_sw +
+                        (s->swar2 - s->last_swcr) * 10); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_swal2);
+
+    if ((rtsr & 0xc000) == 0xc000 && !(rtsr & (1 << 13)))
+        qemu_mod_timer(s->rtc_pi, s->last_pi +
+                        (s->piar & 0xffff) - s->last_rtcpicr);
+    else
+        qemu_del_timer(s->rtc_pi);
+}
+
+static inline void pxa2xx_rtc_hz_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 0);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_rdal1_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 4);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_rdal2_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 6);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_swal1_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 8);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_swal2_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 10);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_pi_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 13);
+    pxa2xx_rtc_piupdate(s);
+    s->last_rtcpicr = 0;
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static uint64_t pxa2xx_rtc_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+
+    switch (addr) {
+    case RTTR:
+        return s->rttr;
+    case RTSR:
+        return s->rtsr;
+    case RTAR:
+        return s->rtar;
+    case RDAR1:
+        return s->rdar1;
+    case RDAR2:
+        return s->rdar2;
+    case RYAR1:
+        return s->ryar1;
+    case RYAR2:
+        return s->ryar2;
+    case SWAR1:
+        return s->swar1;
+    case SWAR2:
+        return s->swar2;
+    case PIAR:
+        return s->piar;
+    case RCNR:
+        return s->last_rcnr + ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
+                (1000 * ((s->rttr & 0xffff) + 1));
+    case RDCR:
+        return s->last_rdcr + ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
+                (1000 * ((s->rttr & 0xffff) + 1));
+    case RYCR:
+        return s->last_rycr;
+    case SWCR:
+        if (s->rtsr & (1 << 12))
+            return s->last_swcr + (qemu_get_clock_ms(rtc_clock) - s->last_sw) / 10;
+        else
+            return s->last_swcr;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_rtc_write(void *opaque, hwaddr addr,
+                             uint64_t value64, unsigned size)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    uint32_t value = value64;
+
+    switch (addr) {
+    case RTTR:
+        if (!(s->rttr & (1 << 31))) {
+            pxa2xx_rtc_hzupdate(s);
+            s->rttr = value;
+            pxa2xx_rtc_alarm_update(s, s->rtsr);
+        }
+        break;
+
+    case RTSR:
+        if ((s->rtsr ^ value) & (1 << 15))
+            pxa2xx_rtc_piupdate(s);
+
+        if ((s->rtsr ^ value) & (1 << 12))
+            pxa2xx_rtc_swupdate(s);
+
+        if (((s->rtsr ^ value) & 0x4aac) | (value & ~0xdaac))
+            pxa2xx_rtc_alarm_update(s, value);
+
+        s->rtsr = (value & 0xdaac) | (s->rtsr & ~(value & ~0xdaac));
+        pxa2xx_rtc_int_update(s);
+        break;
+
+    case RTAR:
+        s->rtar = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RDAR1:
+        s->rdar1 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RDAR2:
+        s->rdar2 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RYAR1:
+        s->ryar1 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RYAR2:
+        s->ryar2 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case SWAR1:
+        pxa2xx_rtc_swupdate(s);
+        s->swar1 = value;
+        s->last_swcr = 0;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case SWAR2:
+        s->swar2 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case PIAR:
+        s->piar = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RCNR:
+        pxa2xx_rtc_hzupdate(s);
+        s->last_rcnr = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RDCR:
+        pxa2xx_rtc_hzupdate(s);
+        s->last_rdcr = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RYCR:
+        s->last_rycr = value;
+        break;
+
+    case SWCR:
+        pxa2xx_rtc_swupdate(s);
+        s->last_swcr = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RTCPICR:
+        pxa2xx_rtc_piupdate(s);
+        s->last_rtcpicr = value & 0xffff;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static const MemoryRegionOps pxa2xx_rtc_ops = {
+    .read = pxa2xx_rtc_read,
+    .write = pxa2xx_rtc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int pxa2xx_rtc_init(SysBusDevice *dev)
+{
+    PXA2xxRTCState *s = FROM_SYSBUS(PXA2xxRTCState, dev);
+    struct tm tm;
+    int wom;
+
+    s->rttr = 0x7fff;
+    s->rtsr = 0;
+
+    qemu_get_timedate(&tm, 0);
+    wom = ((tm.tm_mday - 1) / 7) + 1;
+
+    s->last_rcnr = (uint32_t) mktimegm(&tm);
+    s->last_rdcr = (wom << 20) | ((tm.tm_wday + 1) << 17) |
+            (tm.tm_hour << 12) | (tm.tm_min << 6) | tm.tm_sec;
+    s->last_rycr = ((tm.tm_year + 1900) << 9) |
+            ((tm.tm_mon + 1) << 5) | tm.tm_mday;
+    s->last_swcr = (tm.tm_hour << 19) |
+            (tm.tm_min << 13) | (tm.tm_sec << 7);
+    s->last_rtcpicr = 0;
+    s->last_hz = s->last_sw = s->last_pi = qemu_get_clock_ms(rtc_clock);
+
+    s->rtc_hz    = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_hz_tick,    s);
+    s->rtc_rdal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal1_tick, s);
+    s->rtc_rdal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal2_tick, s);
+    s->rtc_swal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal1_tick, s);
+    s->rtc_swal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal2_tick, s);
+    s->rtc_pi    = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_pi_tick,    s);
+
+    sysbus_init_irq(dev, &s->rtc_irq);
+
+    memory_region_init_io(&s->iomem, &pxa2xx_rtc_ops, s, "pxa2xx-rtc", 0x10000);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    return 0;
+}
+
+static void pxa2xx_rtc_pre_save(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+
+    pxa2xx_rtc_hzupdate(s);
+    pxa2xx_rtc_piupdate(s);
+    pxa2xx_rtc_swupdate(s);
+}
+
+static int pxa2xx_rtc_post_load(void *opaque, int version_id)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_pxa2xx_rtc_regs = {
+    .name = "pxa2xx_rtc",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .pre_save = pxa2xx_rtc_pre_save,
+    .post_load = pxa2xx_rtc_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(rttr, PXA2xxRTCState),
+        VMSTATE_UINT32(rtsr, PXA2xxRTCState),
+        VMSTATE_UINT32(rtar, PXA2xxRTCState),
+        VMSTATE_UINT32(rdar1, PXA2xxRTCState),
+        VMSTATE_UINT32(rdar2, PXA2xxRTCState),
+        VMSTATE_UINT32(ryar1, PXA2xxRTCState),
+        VMSTATE_UINT32(ryar2, PXA2xxRTCState),
+        VMSTATE_UINT32(swar1, PXA2xxRTCState),
+        VMSTATE_UINT32(swar2, PXA2xxRTCState),
+        VMSTATE_UINT32(piar, PXA2xxRTCState),
+        VMSTATE_UINT32(last_rcnr, PXA2xxRTCState),
+        VMSTATE_UINT32(last_rdcr, PXA2xxRTCState),
+        VMSTATE_UINT32(last_rycr, PXA2xxRTCState),
+        VMSTATE_UINT32(last_swcr, PXA2xxRTCState),
+        VMSTATE_UINT32(last_rtcpicr, PXA2xxRTCState),
+        VMSTATE_INT64(last_hz, PXA2xxRTCState),
+        VMSTATE_INT64(last_sw, PXA2xxRTCState),
+        VMSTATE_INT64(last_pi, PXA2xxRTCState),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static void pxa2xx_rtc_sysbus_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pxa2xx_rtc_init;
+    dc->desc = "PXA2xx RTC Controller";
+    dc->vmsd = &vmstate_pxa2xx_rtc_regs;
+}
+
+static const TypeInfo pxa2xx_rtc_sysbus_info = {
+    .name          = "pxa2xx_rtc",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PXA2xxRTCState),
+    .class_init    = pxa2xx_rtc_sysbus_class_init,
+};
+
+/* I2C Interface */
+typedef struct {
+    I2CSlave i2c;
+    PXA2xxI2CState *host;
+} PXA2xxI2CSlaveState;
+
+struct PXA2xxI2CState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    PXA2xxI2CSlaveState *slave;
+    i2c_bus *bus;
+    qemu_irq irq;
+    uint32_t offset;
+    uint32_t region_size;
+
+    uint16_t control;
+    uint16_t status;
+    uint8_t ibmr;
+    uint8_t data;
+};
+
+#define IBMR   0x80    /* I2C Bus Monitor register */
+#define IDBR   0x88    /* I2C Data Buffer register */
+#define ICR    0x90    /* I2C Control register */
+#define ISR    0x98    /* I2C Status register */
+#define ISAR   0xa0    /* I2C Slave Address register */
+
+static void pxa2xx_i2c_update(PXA2xxI2CState *s)
+{
+    uint16_t level = 0;
+    level |= s->status & s->control & (1 << 10);               /* BED */
+    level |= (s->status & (1 << 7)) && (s->control & (1 << 9));        /* IRF */
+    level |= (s->status & (1 << 6)) && (s->control & (1 << 8));        /* ITE */
+    level |= s->status & (1 << 9);                             /* SAD */
+    qemu_set_irq(s->irq, !!level);
+}
+
+/* These are only stubs now.  */
+static void pxa2xx_i2c_event(I2CSlave *i2c, enum i2c_event event)
+{
+    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
+    PXA2xxI2CState *s = slave->host;
+
+    switch (event) {
+    case I2C_START_SEND:
+        s->status |= (1 << 9);                         /* set SAD */
+        s->status &= ~(1 << 0);                                /* clear RWM */
+        break;
+    case I2C_START_RECV:
+        s->status |= (1 << 9);                         /* set SAD */
+        s->status |= 1 << 0;                           /* set RWM */
+        break;
+    case I2C_FINISH:
+        s->status |= (1 << 4);                         /* set SSD */
+        break;
+    case I2C_NACK:
+        s->status |= 1 << 1;                           /* set ACKNAK */
+        break;
+    }
+    pxa2xx_i2c_update(s);
+}
+
+static int pxa2xx_i2c_rx(I2CSlave *i2c)
+{
+    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
+    PXA2xxI2CState *s = slave->host;
+    if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
+        return 0;
+
+    if (s->status & (1 << 0)) {                        /* RWM */
+        s->status |= 1 << 6;                   /* set ITE */
+    }
+    pxa2xx_i2c_update(s);
+
+    return s->data;
+}
+
+static int pxa2xx_i2c_tx(I2CSlave *i2c, uint8_t data)
+{
+    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
+    PXA2xxI2CState *s = slave->host;
+    if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
+        return 1;
+
+    if (!(s->status & (1 << 0))) {             /* RWM */
+        s->status |= 1 << 7;                   /* set IRF */
+        s->data = data;
+    }
+    pxa2xx_i2c_update(s);
+
+    return 1;
+}
+
+static uint64_t pxa2xx_i2c_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    PXA2xxI2CState *s = (PXA2xxI2CState *) opaque;
+
+    addr -= s->offset;
+    switch (addr) {
+    case ICR:
+        return s->control;
+    case ISR:
+        return s->status | (i2c_bus_busy(s->bus) << 2);
+    case ISAR:
+        return s->slave->i2c.address;
+    case IDBR:
+        return s->data;
+    case IBMR:
+        if (s->status & (1 << 2))
+            s->ibmr ^= 3;      /* Fake SCL and SDA pin changes */
+        else
+            s->ibmr = 0;
+        return s->ibmr;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_i2c_write(void *opaque, hwaddr addr,
+                             uint64_t value64, unsigned size)
+{
+    PXA2xxI2CState *s = (PXA2xxI2CState *) opaque;
+    uint32_t value = value64;
+    int ack;
+
+    addr -= s->offset;
+    switch (addr) {
+    case ICR:
+        s->control = value & 0xfff7;
+        if ((value & (1 << 3)) && (value & (1 << 6))) {        /* TB and IUE */
+            /* TODO: slave mode */
+            if (value & (1 << 0)) {                    /* START condition */
+                if (s->data & 1)
+                    s->status |= 1 << 0;               /* set RWM */
+                else
+                    s->status &= ~(1 << 0);            /* clear RWM */
+                ack = !i2c_start_transfer(s->bus, s->data >> 1, s->data & 1);
+            } else {
+                if (s->status & (1 << 0)) {            /* RWM */
+                    s->data = i2c_recv(s->bus);
+                    if (value & (1 << 2))              /* ACKNAK */
+                        i2c_nack(s->bus);
+                    ack = 1;
+                } else
+                    ack = !i2c_send(s->bus, s->data);
+            }
+
+            if (value & (1 << 1))                      /* STOP condition */
+                i2c_end_transfer(s->bus);
+
+            if (ack) {
+                if (value & (1 << 0))                  /* START condition */
+                    s->status |= 1 << 6;               /* set ITE */
+                else
+                    if (s->status & (1 << 0))          /* RWM */
+                        s->status |= 1 << 7;           /* set IRF */
+                    else
+                        s->status |= 1 << 6;           /* set ITE */
+                s->status &= ~(1 << 1);                        /* clear ACKNAK */
+            } else {
+                s->status |= 1 << 6;                   /* set ITE */
+                s->status |= 1 << 10;                  /* set BED */
+                s->status |= 1 << 1;                   /* set ACKNAK */
+            }
+        }
+        if (!(value & (1 << 3)) && (value & (1 << 6))) /* !TB and IUE */
+            if (value & (1 << 4))                      /* MA */
+                i2c_end_transfer(s->bus);
+        pxa2xx_i2c_update(s);
+        break;
+
+    case ISR:
+        s->status &= ~(value & 0x07f0);
+        pxa2xx_i2c_update(s);
+        break;
+
+    case ISAR:
+        i2c_set_slave_address(&s->slave->i2c, value & 0x7f);
+        break;
+
+    case IDBR:
+        s->data = value & 0xff;
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static const MemoryRegionOps pxa2xx_i2c_ops = {
+    .read = pxa2xx_i2c_read,
+    .write = pxa2xx_i2c_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_pxa2xx_i2c_slave = {
+    .name = "pxa2xx_i2c_slave",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_I2C_SLAVE(i2c, PXA2xxI2CSlaveState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_pxa2xx_i2c = {
+    .name = "pxa2xx_i2c",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT16(control, PXA2xxI2CState),
+        VMSTATE_UINT16(status, PXA2xxI2CState),
+        VMSTATE_UINT8(ibmr, PXA2xxI2CState),
+        VMSTATE_UINT8(data, PXA2xxI2CState),
+        VMSTATE_STRUCT_POINTER(slave, PXA2xxI2CState,
+                               vmstate_pxa2xx_i2c_slave, PXA2xxI2CSlaveState *),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int pxa2xx_i2c_slave_init(I2CSlave *i2c)
+{
+    /* Nothing to do.  */
+    return 0;
+}
+
+static void pxa2xx_i2c_slave_class_init(ObjectClass *klass, void *data)
+{
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+    k->init = pxa2xx_i2c_slave_init;
+    k->event = pxa2xx_i2c_event;
+    k->recv = pxa2xx_i2c_rx;
+    k->send = pxa2xx_i2c_tx;
+}
+
+static const TypeInfo pxa2xx_i2c_slave_info = {
+    .name          = "pxa2xx-i2c-slave",
+    .parent        = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(PXA2xxI2CSlaveState),
+    .class_init    = pxa2xx_i2c_slave_class_init,
+};
+
+PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
+                qemu_irq irq, uint32_t region_size)
+{
+    DeviceState *dev;
+    SysBusDevice *i2c_dev;
+    PXA2xxI2CState *s;
+
+    i2c_dev = SYS_BUS_DEVICE(qdev_create(NULL, "pxa2xx_i2c"));
+    qdev_prop_set_uint32(&i2c_dev->qdev, "size", region_size + 1);
+    qdev_prop_set_uint32(&i2c_dev->qdev, "offset", base & region_size);
+
+    qdev_init_nofail(&i2c_dev->qdev);
+
+    sysbus_mmio_map(i2c_dev, 0, base & ~region_size);
+    sysbus_connect_irq(i2c_dev, 0, irq);
+
+    s = FROM_SYSBUS(PXA2xxI2CState, i2c_dev);
+    /* FIXME: Should the slave device really be on a separate bus?  */
+    dev = i2c_create_slave(i2c_init_bus(NULL, "dummy"), "pxa2xx-i2c-slave", 0);
+    s->slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, I2C_SLAVE(dev));
+    s->slave->host = s;
+
+    return s;
+}
+
+static int pxa2xx_i2c_initfn(SysBusDevice *dev)
+{
+    PXA2xxI2CState *s = FROM_SYSBUS(PXA2xxI2CState, dev);
+
+    s->bus = i2c_init_bus(&dev->qdev, "i2c");
+
+    memory_region_init_io(&s->iomem, &pxa2xx_i2c_ops, s,
+                          "pxa2xx-i2x", s->region_size);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+
+    return 0;
+}
+
+i2c_bus *pxa2xx_i2c_bus(PXA2xxI2CState *s)
+{
+    return s->bus;
+}
+
+static Property pxa2xx_i2c_properties[] = {
+    DEFINE_PROP_UINT32("size", PXA2xxI2CState, region_size, 0x10000),
+    DEFINE_PROP_UINT32("offset", PXA2xxI2CState, offset, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pxa2xx_i2c_initfn;
+    dc->desc = "PXA2xx I2C Bus Controller";
+    dc->vmsd = &vmstate_pxa2xx_i2c;
+    dc->props = pxa2xx_i2c_properties;
+}
+
+static const TypeInfo pxa2xx_i2c_info = {
+    .name          = "pxa2xx_i2c",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PXA2xxI2CState),
+    .class_init    = pxa2xx_i2c_class_init,
+};
+
+/* PXA Inter-IC Sound Controller */
+static void pxa2xx_i2s_reset(PXA2xxI2SState *i2s)
+{
+    i2s->rx_len = 0;
+    i2s->tx_len = 0;
+    i2s->fifo_len = 0;
+    i2s->clk = 0x1a;
+    i2s->control[0] = 0x00;
+    i2s->control[1] = 0x00;
+    i2s->status = 0x00;
+    i2s->mask = 0x00;
+}
+
+#define SACR_TFTH(val) ((val >> 8) & 0xf)
+#define SACR_RFTH(val) ((val >> 12) & 0xf)
+#define SACR_DREC(val) (val & (1 << 3))
+#define SACR_DPRL(val) (val & (1 << 4))
+
+static inline void pxa2xx_i2s_update(PXA2xxI2SState *i2s)
+{
+    int rfs, tfs;
+    rfs = SACR_RFTH(i2s->control[0]) < i2s->rx_len &&
+            !SACR_DREC(i2s->control[1]);
+    tfs = (i2s->tx_len || i2s->fifo_len < SACR_TFTH(i2s->control[0])) &&
+            i2s->enable && !SACR_DPRL(i2s->control[1]);
+
+    qemu_set_irq(i2s->rx_dma, rfs);
+    qemu_set_irq(i2s->tx_dma, tfs);
+
+    i2s->status &= 0xe0;
+    if (i2s->fifo_len < 16 || !i2s->enable)
+        i2s->status |= 1 << 0;                 /* TNF */
+    if (i2s->rx_len)
+        i2s->status |= 1 << 1;                 /* RNE */
+    if (i2s->enable)
+        i2s->status |= 1 << 2;                 /* BSY */
+    if (tfs)
+        i2s->status |= 1 << 3;                 /* TFS */
+    if (rfs)
+        i2s->status |= 1 << 4;                 /* RFS */
+    if (!(i2s->tx_len && i2s->enable))
+        i2s->status |= i2s->fifo_len << 8;     /* TFL */
+    i2s->status |= MAX(i2s->rx_len, 0xf) << 12;        /* RFL */
+
+    qemu_set_irq(i2s->irq, i2s->status & i2s->mask);
+}
+
+#define SACR0  0x00    /* Serial Audio Global Control register */
+#define SACR1  0x04    /* Serial Audio I2S/MSB-Justified Control register */
+#define SASR0  0x0c    /* Serial Audio Interface and FIFO Status register */
+#define SAIMR  0x14    /* Serial Audio Interrupt Mask register */
+#define SAICR  0x18    /* Serial Audio Interrupt Clear register */
+#define SADIV  0x60    /* Serial Audio Clock Divider register */
+#define SADR   0x80    /* Serial Audio Data register */
+
+static uint64_t pxa2xx_i2s_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
+
+    switch (addr) {
+    case SACR0:
+        return s->control[0];
+    case SACR1:
+        return s->control[1];
+    case SASR0:
+        return s->status;
+    case SAIMR:
+        return s->mask;
+    case SAICR:
+        return 0;
+    case SADIV:
+        return s->clk;
+    case SADR:
+        if (s->rx_len > 0) {
+            s->rx_len --;
+            pxa2xx_i2s_update(s);
+            return s->codec_in(s->opaque);
+        }
+        return 0;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_i2s_write(void *opaque, hwaddr addr,
+                             uint64_t value, unsigned size)
+{
+    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
+    uint32_t *sample;
+
+    switch (addr) {
+    case SACR0:
+        if (value & (1 << 3))                          /* RST */
+            pxa2xx_i2s_reset(s);
+        s->control[0] = value & 0xff3d;
+        if (!s->enable && (value & 1) && s->tx_len) {  /* ENB */
+            for (sample = s->fifo; s->fifo_len > 0; s->fifo_len --, sample ++)
+                s->codec_out(s->opaque, *sample);
+            s->status &= ~(1 << 7);                    /* I2SOFF */
+        }
+        if (value & (1 << 4))                          /* EFWR */
+            printf("%s: Attempt to use special function\n", __FUNCTION__);
+        s->enable = (value & 9) == 1;                  /* ENB && !RST*/
+        pxa2xx_i2s_update(s);
+        break;
+    case SACR1:
+        s->control[1] = value & 0x0039;
+        if (value & (1 << 5))                          /* ENLBF */
+            printf("%s: Attempt to use loopback function\n", __FUNCTION__);
+        if (value & (1 << 4))                          /* DPRL */
+            s->fifo_len = 0;
+        pxa2xx_i2s_update(s);
+        break;
+    case SAIMR:
+        s->mask = value & 0x0078;
+        pxa2xx_i2s_update(s);
+        break;
+    case SAICR:
+        s->status &= ~(value & (3 << 5));
+        pxa2xx_i2s_update(s);
+        break;
+    case SADIV:
+        s->clk = value & 0x007f;
+        break;
+    case SADR:
+        if (s->tx_len && s->enable) {
+            s->tx_len --;
+            pxa2xx_i2s_update(s);
+            s->codec_out(s->opaque, value);
+        } else if (s->fifo_len < 16) {
+            s->fifo[s->fifo_len ++] = value;
+            pxa2xx_i2s_update(s);
+        }
+        break;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static const MemoryRegionOps pxa2xx_i2s_ops = {
+    .read = pxa2xx_i2s_read,
+    .write = pxa2xx_i2s_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_pxa2xx_i2s = {
+    .name = "pxa2xx_i2s",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(control, PXA2xxI2SState, 2),
+        VMSTATE_UINT32(status, PXA2xxI2SState),
+        VMSTATE_UINT32(mask, PXA2xxI2SState),
+        VMSTATE_UINT32(clk, PXA2xxI2SState),
+        VMSTATE_INT32(enable, PXA2xxI2SState),
+        VMSTATE_INT32(rx_len, PXA2xxI2SState),
+        VMSTATE_INT32(tx_len, PXA2xxI2SState),
+        VMSTATE_INT32(fifo_len, PXA2xxI2SState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx)
+{
+    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
+    uint32_t *sample;
+
+    /* Signal FIFO errors */
+    if (s->enable && s->tx_len)
+        s->status |= 1 << 5;           /* TUR */
+    if (s->enable && s->rx_len)
+        s->status |= 1 << 6;           /* ROR */
+
+    /* Should be tx - MIN(tx, s->fifo_len) but we don't really need to
+     * handle the cases where it makes a difference.  */
+    s->tx_len = tx - s->fifo_len;
+    s->rx_len = rx;
+    /* Note that is s->codec_out wasn't set, we wouldn't get called.  */
+    if (s->enable)
+        for (sample = s->fifo; s->fifo_len; s->fifo_len --, sample ++)
+            s->codec_out(s->opaque, *sample);
+    pxa2xx_i2s_update(s);
+}
+
+static PXA2xxI2SState *pxa2xx_i2s_init(MemoryRegion *sysmem,
+                hwaddr base,
+                qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma)
+{
+    PXA2xxI2SState *s = (PXA2xxI2SState *)
+            g_malloc0(sizeof(PXA2xxI2SState));
+
+    s->irq = irq;
+    s->rx_dma = rx_dma;
+    s->tx_dma = tx_dma;
+    s->data_req = pxa2xx_i2s_data_req;
+
+    pxa2xx_i2s_reset(s);
+
+    memory_region_init_io(&s->iomem, &pxa2xx_i2s_ops, s,
+                          "pxa2xx-i2s", 0x100000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
+
+    vmstate_register(NULL, base, &vmstate_pxa2xx_i2s, s);
+
+    return s;
+}
+
+/* PXA Fast Infra-red Communications Port */
+struct PXA2xxFIrState {
+    MemoryRegion iomem;
+    qemu_irq irq;
+    qemu_irq rx_dma;
+    qemu_irq tx_dma;
+    int enable;
+    CharDriverState *chr;
+
+    uint8_t control[3];
+    uint8_t status[2];
+
+    int rx_len;
+    int rx_start;
+    uint8_t rx_fifo[64];
+};
+
+static void pxa2xx_fir_reset(PXA2xxFIrState *s)
+{
+    s->control[0] = 0x00;
+    s->control[1] = 0x00;
+    s->control[2] = 0x00;
+    s->status[0] = 0x00;
+    s->status[1] = 0x00;
+    s->enable = 0;
+}
+
+static inline void pxa2xx_fir_update(PXA2xxFIrState *s)
+{
+    static const int tresh[4] = { 8, 16, 32, 0 };
+    int intr = 0;
+    if ((s->control[0] & (1 << 4)) &&                  /* RXE */
+                    s->rx_len >= tresh[s->control[2] & 3])     /* TRIG */
+        s->status[0] |= 1 << 4;                                /* RFS */
+    else
+        s->status[0] &= ~(1 << 4);                     /* RFS */
+    if (s->control[0] & (1 << 3))                      /* TXE */
+        s->status[0] |= 1 << 3;                                /* TFS */
+    else
+        s->status[0] &= ~(1 << 3);                     /* TFS */
+    if (s->rx_len)
+        s->status[1] |= 1 << 2;                                /* RNE */
+    else
+        s->status[1] &= ~(1 << 2);                     /* RNE */
+    if (s->control[0] & (1 << 4))                      /* RXE */
+        s->status[1] |= 1 << 0;                                /* RSY */
+    else
+        s->status[1] &= ~(1 << 0);                     /* RSY */
+
+    intr |= (s->control[0] & (1 << 5)) &&              /* RIE */
+            (s->status[0] & (1 << 4));                 /* RFS */
+    intr |= (s->control[0] & (1 << 6)) &&              /* TIE */
+            (s->status[0] & (1 << 3));                 /* TFS */
+    intr |= (s->control[2] & (1 << 4)) &&              /* TRAIL */
+            (s->status[0] & (1 << 6));                 /* EOC */
+    intr |= (s->control[0] & (1 << 2)) &&              /* TUS */
+            (s->status[0] & (1 << 1));                 /* TUR */
+    intr |= s->status[0] & 0x25;                       /* FRE, RAB, EIF */
+
+    qemu_set_irq(s->rx_dma, (s->status[0] >> 4) & 1);
+    qemu_set_irq(s->tx_dma, (s->status[0] >> 3) & 1);
+
+    qemu_set_irq(s->irq, intr && s->enable);
+}
+
+#define ICCR0  0x00    /* FICP Control register 0 */
+#define ICCR1  0x04    /* FICP Control register 1 */
+#define ICCR2  0x08    /* FICP Control register 2 */
+#define ICDR   0x0c    /* FICP Data register */
+#define ICSR0  0x14    /* FICP Status register 0 */
+#define ICSR1  0x18    /* FICP Status register 1 */
+#define ICFOR  0x1c    /* FICP FIFO Occupancy Status register */
+
+static uint64_t pxa2xx_fir_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    uint8_t ret;
+
+    switch (addr) {
+    case ICCR0:
+        return s->control[0];
+    case ICCR1:
+        return s->control[1];
+    case ICCR2:
+        return s->control[2];
+    case ICDR:
+        s->status[0] &= ~0x01;
+        s->status[1] &= ~0x72;
+        if (s->rx_len) {
+            s->rx_len --;
+            ret = s->rx_fifo[s->rx_start ++];
+            s->rx_start &= 63;
+            pxa2xx_fir_update(s);
+            return ret;
+        }
+        printf("%s: Rx FIFO underrun.\n", __FUNCTION__);
+        break;
+    case ICSR0:
+        return s->status[0];
+    case ICSR1:
+        return s->status[1] | (1 << 3);                        /* TNF */
+    case ICFOR:
+        return s->rx_len;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_fir_write(void *opaque, hwaddr addr,
+                             uint64_t value64, unsigned size)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    uint32_t value = value64;
+    uint8_t ch;
+
+    switch (addr) {
+    case ICCR0:
+        s->control[0] = value;
+        if (!(value & (1 << 4)))                       /* RXE */
+            s->rx_len = s->rx_start = 0;
+        if (!(value & (1 << 3))) {                      /* TXE */
+            /* Nop */
+        }
+        s->enable = value & 1;                         /* ITR */
+        if (!s->enable)
+            s->status[0] = 0;
+        pxa2xx_fir_update(s);
+        break;
+    case ICCR1:
+        s->control[1] = value;
+        break;
+    case ICCR2:
+        s->control[2] = value & 0x3f;
+        pxa2xx_fir_update(s);
+        break;
+    case ICDR:
+        if (s->control[2] & (1 << 2))                  /* TXP */
+            ch = value;
+        else
+            ch = ~value;
+        if (s->chr && s->enable && (s->control[0] & (1 << 3))) /* TXE */
+            qemu_chr_fe_write(s->chr, &ch, 1);
+        break;
+    case ICSR0:
+        s->status[0] &= ~(value & 0x66);
+        pxa2xx_fir_update(s);
+        break;
+    case ICFOR:
+        break;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static const MemoryRegionOps pxa2xx_fir_ops = {
+    .read = pxa2xx_fir_read,
+    .write = pxa2xx_fir_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int pxa2xx_fir_is_empty(void *opaque)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    return (s->rx_len < 64);
+}
+
+static void pxa2xx_fir_rx(void *opaque, const uint8_t *buf, int size)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    if (!(s->control[0] & (1 << 4)))                   /* RXE */
+        return;
+
+    while (size --) {
+        s->status[1] |= 1 << 4;                                /* EOF */
+        if (s->rx_len >= 64) {
+            s->status[1] |= 1 << 6;                    /* ROR */
+            break;
+        }
+
+        if (s->control[2] & (1 << 3))                  /* RXP */
+            s->rx_fifo[(s->rx_start + s->rx_len ++) & 63] = *(buf ++);
+        else
+            s->rx_fifo[(s->rx_start + s->rx_len ++) & 63] = ~*(buf ++);
+    }
+
+    pxa2xx_fir_update(s);
+}
+
+static void pxa2xx_fir_event(void *opaque, int event)
+{
+}
+
+static void pxa2xx_fir_save(QEMUFile *f, void *opaque)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    int i;
+
+    qemu_put_be32(f, s->enable);
+
+    qemu_put_8s(f, &s->control[0]);
+    qemu_put_8s(f, &s->control[1]);
+    qemu_put_8s(f, &s->control[2]);
+    qemu_put_8s(f, &s->status[0]);
+    qemu_put_8s(f, &s->status[1]);
+
+    qemu_put_byte(f, s->rx_len);
+    for (i = 0; i < s->rx_len; i ++)
+        qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 63]);
+}
+
+static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    int i;
+
+    s->enable = qemu_get_be32(f);
+
+    qemu_get_8s(f, &s->control[0]);
+    qemu_get_8s(f, &s->control[1]);
+    qemu_get_8s(f, &s->control[2]);
+    qemu_get_8s(f, &s->status[0]);
+    qemu_get_8s(f, &s->status[1]);
+
+    s->rx_len = qemu_get_byte(f);
+    s->rx_start = 0;
+    for (i = 0; i < s->rx_len; i ++)
+        s->rx_fifo[i] = qemu_get_byte(f);
+
+    return 0;
+}
+
+static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
+                hwaddr base,
+                qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
+                CharDriverState *chr)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *)
+            g_malloc0(sizeof(PXA2xxFIrState));
+
+    s->irq = irq;
+    s->rx_dma = rx_dma;
+    s->tx_dma = tx_dma;
+    s->chr = chr;
+
+    pxa2xx_fir_reset(s);
+
+    memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
+
+    if (chr)
+        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
+                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
+
+    register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
+                    pxa2xx_fir_load, s);
+
+    return s;
+}
+
+static void pxa2xx_reset(void *opaque, int line, int level)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    if (level && (s->pm_regs[PCFR >> 2] & 0x10)) {     /* GPR_EN */
+        cpu_reset(CPU(s->cpu));
+        /* TODO: reset peripherals */
+    }
+}
+
+/* Initialise a PXA270 integrated chip (ARM based core).  */
+PXA2xxState *pxa270_init(MemoryRegion *address_space,
+                         unsigned int sdram_size, const char *revision)
+{
+    PXA2xxState *s;
+    int i;
+    DriveInfo *dinfo;
+    s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
+
+    if (revision && strncmp(revision, "pxa27", 5)) {
+        fprintf(stderr, "Machine requires a PXA27x processor.\n");
+        exit(1);
+    }
+    if (!revision)
+        revision = "pxa270";
+    
+    s->cpu = cpu_arm_init(revision);
+    if (s->cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
+
+    /* SDRAM & Internal Memory Storage */
+    memory_region_init_ram(&s->sdram, "pxa270.sdram", sdram_size);
+    vmstate_register_ram_global(&s->sdram);
+    memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
+    memory_region_init_ram(&s->internal, "pxa270.internal", 0x40000);
+    vmstate_register_ram_global(&s->internal);
+    memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
+                                &s->internal);
+
+    s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
+
+    s->dma = pxa27x_dma_init(0x40000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
+
+    sysbus_create_varargs("pxa27x-timer", 0x40a00000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 0),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 1),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 2),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3),
+                    qdev_get_gpio_in(s->pic, PXA27X_PIC_OST_4_11),
+                    NULL);
+
+    s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 121);
+
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "qemu: missing SecureDigital device\n");
+        exit(1);
+    }
+    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
+                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
+                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
+
+    for (i = 0; pxa270_serial[i].io_base; i++) {
+        if (serial_hds[i]) {
+            serial_mm_init(address_space, pxa270_serial[i].io_base, 2,
+                           qdev_get_gpio_in(s->pic, pxa270_serial[i].irqn),
+                           14857000 / 16, serial_hds[i],
+                           DEVICE_NATIVE_ENDIAN);
+        } else {
+            break;
+        }
+    }
+    if (serial_hds[i])
+        s->fir = pxa2xx_fir_init(address_space, 0x40800000,
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
+                        qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_ICP),
+                        qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
+                        serial_hds[i]);
+
+    s->lcd = pxa2xx_lcdc_init(address_space, 0x44000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
+
+    s->cm_base = 0x41300000;
+    s->cm_regs[CCCR >> 2] = 0x02000210;        /* 416.0 MHz */
+    s->clkcfg = 0x00000009;            /* Turbo mode active */
+    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
+    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
+
+    pxa2xx_setup_cp14(s);
+
+    s->mm_base = 0x48000000;
+    s->mm_regs[MDMRS >> 2] = 0x00020002;
+    s->mm_regs[MDREFR >> 2] = 0x03ca4000;
+    s->mm_regs[MECR >> 2] = 0x00000001;        /* Two PC Card sockets */
+    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
+    memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
+
+    s->pm_base = 0x40f00000;
+    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
+    memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
+
+    for (i = 0; pxa27x_ssp[i].io_base; i ++);
+    s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
+    for (i = 0; pxa27x_ssp[i].io_base; i ++) {
+        DeviceState *dev;
+        dev = sysbus_create_simple("pxa2xx-ssp", pxa27x_ssp[i].io_base,
+                        qdev_get_gpio_in(s->pic, pxa27x_ssp[i].irqn));
+        s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
+    }
+
+    if (usb_enabled(false)) {
+        sysbus_create_simple("sysbus-ohci", 0x4c000000,
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
+    }
+
+    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
+    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
+
+    sysbus_create_simple("pxa2xx_rtc", 0x40900000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
+
+    s->i2c[0] = pxa2xx_i2c_init(0x40301600,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2C), 0xffff);
+    s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
+
+    s->i2s = pxa2xx_i2s_init(address_space, 0x40400000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S),
+                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_I2S),
+                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_I2S));
+
+    s->kp = pxa27x_keypad_init(address_space, 0x41500000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_KEYPAD));
+
+    /* GPIO1 resets the processor */
+    /* The handler can be overridden by board-specific code */
+    qdev_connect_gpio_out(s->gpio, 1, s->reset);
+    return s;
+}
+
+/* Initialise a PXA255 integrated chip (ARM based core).  */
+PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
+{
+    PXA2xxState *s;
+    int i;
+    DriveInfo *dinfo;
+
+    s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
+
+    s->cpu = cpu_arm_init("pxa255");
+    if (s->cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
+
+    /* SDRAM & Internal Memory Storage */
+    memory_region_init_ram(&s->sdram, "pxa255.sdram", sdram_size);
+    vmstate_register_ram_global(&s->sdram);
+    memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
+    memory_region_init_ram(&s->internal, "pxa255.internal",
+                           PXA2XX_INTERNAL_SIZE);
+    vmstate_register_ram_global(&s->internal);
+    memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
+                                &s->internal);
+
+    s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
+
+    s->dma = pxa255_dma_init(0x40000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
+
+    sysbus_create_varargs("pxa25x-timer", 0x40a00000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 0),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 1),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 2),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3),
+                    NULL);
+
+    s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 85);
+
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "qemu: missing SecureDigital device\n");
+        exit(1);
+    }
+    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
+                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
+                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
+
+    for (i = 0; pxa255_serial[i].io_base; i++) {
+        if (serial_hds[i]) {
+            serial_mm_init(address_space, pxa255_serial[i].io_base, 2,
+                           qdev_get_gpio_in(s->pic, pxa255_serial[i].irqn),
+                           14745600 / 16, serial_hds[i],
+                           DEVICE_NATIVE_ENDIAN);
+        } else {
+            break;
+        }
+    }
+    if (serial_hds[i])
+        s->fir = pxa2xx_fir_init(address_space, 0x40800000,
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
+                        qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_ICP),
+                        qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
+                        serial_hds[i]);
+
+    s->lcd = pxa2xx_lcdc_init(address_space, 0x44000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
+
+    s->cm_base = 0x41300000;
+    s->cm_regs[CCCR >> 2] = 0x02000210;        /* 416.0 MHz */
+    s->clkcfg = 0x00000009;            /* Turbo mode active */
+    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
+    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
+
+    pxa2xx_setup_cp14(s);
+
+    s->mm_base = 0x48000000;
+    s->mm_regs[MDMRS >> 2] = 0x00020002;
+    s->mm_regs[MDREFR >> 2] = 0x03ca4000;
+    s->mm_regs[MECR >> 2] = 0x00000001;        /* Two PC Card sockets */
+    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
+    memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
+
+    s->pm_base = 0x40f00000;
+    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
+    memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
+
+    for (i = 0; pxa255_ssp[i].io_base; i ++);
+    s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
+    for (i = 0; pxa255_ssp[i].io_base; i ++) {
+        DeviceState *dev;
+        dev = sysbus_create_simple("pxa2xx-ssp", pxa255_ssp[i].io_base,
+                        qdev_get_gpio_in(s->pic, pxa255_ssp[i].irqn));
+        s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
+    }
+
+    if (usb_enabled(false)) {
+        sysbus_create_simple("sysbus-ohci", 0x4c000000,
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
+    }
+
+    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
+    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
+
+    sysbus_create_simple("pxa2xx_rtc", 0x40900000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
+
+    s->i2c[0] = pxa2xx_i2c_init(0x40301600,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2C), 0xffff);
+    s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
+
+    s->i2s = pxa2xx_i2s_init(address_space, 0x40400000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S),
+                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_I2S),
+                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_I2S));
+
+    /* GPIO1 resets the processor */
+    /* The handler can be overridden by board-specific code */
+    qdev_connect_gpio_out(s->gpio, 1, s->reset);
+    return s;
+}
+
+static void pxa2xx_ssp_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = pxa2xx_ssp_init;
+}
+
+static const TypeInfo pxa2xx_ssp_info = {
+    .name          = "pxa2xx-ssp",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PXA2xxSSPState),
+    .class_init    = pxa2xx_ssp_class_init,
+};
+
+static void pxa2xx_register_types(void)
+{
+    type_register_static(&pxa2xx_i2c_slave_info);
+    type_register_static(&pxa2xx_ssp_info);
+    type_register_static(&pxa2xx_i2c_info);
+    type_register_static(&pxa2xx_rtc_sysbus_info);
+}
+
+type_init(pxa2xx_register_types)
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
new file mode 100644 (file)
index 0000000..eef8411
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Intel XScale PXA255/270 GPIO controller emulation.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/pxa.h"
+
+#define PXA2XX_GPIO_BANKS      4
+
+typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
+struct PXA2xxGPIOInfo {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq irq0, irq1, irqX;
+    int lines;
+    int ncpu;
+    ARMCPU *cpu;
+
+    /* XXX: GNU C vectors are more suitable */
+    uint32_t ilevel[PXA2XX_GPIO_BANKS];
+    uint32_t olevel[PXA2XX_GPIO_BANKS];
+    uint32_t dir[PXA2XX_GPIO_BANKS];
+    uint32_t rising[PXA2XX_GPIO_BANKS];
+    uint32_t falling[PXA2XX_GPIO_BANKS];
+    uint32_t status[PXA2XX_GPIO_BANKS];
+    uint32_t gpsr[PXA2XX_GPIO_BANKS];
+    uint32_t gafr[PXA2XX_GPIO_BANKS * 2];
+
+    uint32_t prev_level[PXA2XX_GPIO_BANKS];
+    qemu_irq handler[PXA2XX_GPIO_BANKS * 32];
+    qemu_irq read_notify;
+};
+
+static struct {
+    enum {
+        GPIO_NONE,
+        GPLR,
+        GPSR,
+        GPCR,
+        GPDR,
+        GRER,
+        GFER,
+        GEDR,
+        GAFR_L,
+        GAFR_U,
+    } reg;
+    int bank;
+} pxa2xx_gpio_regs[0x200] = {
+    [0 ... 0x1ff] = { GPIO_NONE, 0 },
+#define PXA2XX_REG(reg, a0, a1, a2, a3)        \
+    [a0] = { reg, 0 }, [a1] = { reg, 1 }, [a2] = { reg, 2 }, [a3] = { reg, 3 },
+
+    PXA2XX_REG(GPLR, 0x000, 0x004, 0x008, 0x100)
+    PXA2XX_REG(GPSR, 0x018, 0x01c, 0x020, 0x118)
+    PXA2XX_REG(GPCR, 0x024, 0x028, 0x02c, 0x124)
+    PXA2XX_REG(GPDR, 0x00c, 0x010, 0x014, 0x10c)
+    PXA2XX_REG(GRER, 0x030, 0x034, 0x038, 0x130)
+    PXA2XX_REG(GFER, 0x03c, 0x040, 0x044, 0x13c)
+    PXA2XX_REG(GEDR, 0x048, 0x04c, 0x050, 0x148)
+    PXA2XX_REG(GAFR_L, 0x054, 0x05c, 0x064, 0x06c)
+    PXA2XX_REG(GAFR_U, 0x058, 0x060, 0x068, 0x070)
+};
+
+static void pxa2xx_gpio_irq_update(PXA2xxGPIOInfo *s)
+{
+    if (s->status[0] & (1 << 0))
+        qemu_irq_raise(s->irq0);
+    else
+        qemu_irq_lower(s->irq0);
+
+    if (s->status[0] & (1 << 1))
+        qemu_irq_raise(s->irq1);
+    else
+        qemu_irq_lower(s->irq1);
+
+    if ((s->status[0] & ~3) | s->status[1] | s->status[2] | s->status[3])
+        qemu_irq_raise(s->irqX);
+    else
+        qemu_irq_lower(s->irqX);
+}
+
+/* Bitmap of pins used as standby and sleep wake-up sources.  */
+static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
+    0x8003fe1b, 0x002001fc, 0xec080000, 0x0012007f,
+};
+
+static void pxa2xx_gpio_set(void *opaque, int line, int level)
+{
+    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
+    int bank;
+    uint32_t mask;
+
+    if (line >= s->lines) {
+        printf("%s: No GPIO pin %i\n", __FUNCTION__, line);
+        return;
+    }
+
+    bank = line >> 5;
+    mask = 1 << (line & 31);
+
+    if (level) {
+        s->status[bank] |= s->rising[bank] & mask &
+                ~s->ilevel[bank] & ~s->dir[bank];
+        s->ilevel[bank] |= mask;
+    } else {
+        s->status[bank] |= s->falling[bank] & mask &
+                s->ilevel[bank] & ~s->dir[bank];
+        s->ilevel[bank] &= ~mask;
+    }
+
+    if (s->status[bank] & mask)
+        pxa2xx_gpio_irq_update(s);
+
+    /* Wake-up GPIOs */
+    if (s->cpu->env.halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+    }
+}
+
+static void pxa2xx_gpio_handler_update(PXA2xxGPIOInfo *s) {
+    uint32_t level, diff;
+    int i, bit, line;
+    for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
+        level = s->olevel[i] & s->dir[i];
+
+        for (diff = s->prev_level[i] ^ level; diff; diff ^= 1 << bit) {
+            bit = ffs(diff) - 1;
+            line = bit + 32 * i;
+            qemu_set_irq(s->handler[line], (level >> bit) & 1);
+        }
+
+        s->prev_level[i] = level;
+    }
+}
+
+static uint64_t pxa2xx_gpio_read(void *opaque, hwaddr offset,
+                                 unsigned size)
+{
+    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
+    uint32_t ret;
+    int bank;
+    if (offset >= 0x200)
+        return 0;
+
+    bank = pxa2xx_gpio_regs[offset].bank;
+    switch (pxa2xx_gpio_regs[offset].reg) {
+    case GPDR:         /* GPIO Pin-Direction registers */
+        return s->dir[bank];
+
+    case GPSR:         /* GPIO Pin-Output Set registers */
+        printf("%s: Read from a write-only register " REG_FMT "\n",
+                        __FUNCTION__, offset);
+        return s->gpsr[bank];  /* Return last written value.  */
+
+    case GPCR:         /* GPIO Pin-Output Clear registers */
+        printf("%s: Read from a write-only register " REG_FMT "\n",
+                        __FUNCTION__, offset);
+        return 31337;          /* Specified as unpredictable in the docs.  */
+
+    case GRER:         /* GPIO Rising-Edge Detect Enable registers */
+        return s->rising[bank];
+
+    case GFER:         /* GPIO Falling-Edge Detect Enable registers */
+        return s->falling[bank];
+
+    case GAFR_L:       /* GPIO Alternate Function registers */
+        return s->gafr[bank * 2];
+
+    case GAFR_U:       /* GPIO Alternate Function registers */
+        return s->gafr[bank * 2 + 1];
+
+    case GPLR:         /* GPIO Pin-Level registers */
+        ret = (s->olevel[bank] & s->dir[bank]) |
+                (s->ilevel[bank] & ~s->dir[bank]);
+        qemu_irq_raise(s->read_notify);
+        return ret;
+
+    case GEDR:         /* GPIO Edge Detect Status registers */
+        return s->status[bank];
+
+    default:
+        hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
+    }
+
+    return 0;
+}
+
+static void pxa2xx_gpio_write(void *opaque, hwaddr offset,
+                              uint64_t value, unsigned size)
+{
+    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
+    int bank;
+    if (offset >= 0x200)
+        return;
+
+    bank = pxa2xx_gpio_regs[offset].bank;
+    switch (pxa2xx_gpio_regs[offset].reg) {
+    case GPDR:         /* GPIO Pin-Direction registers */
+        s->dir[bank] = value;
+        pxa2xx_gpio_handler_update(s);
+        break;
+
+    case GPSR:         /* GPIO Pin-Output Set registers */
+        s->olevel[bank] |= value;
+        pxa2xx_gpio_handler_update(s);
+        s->gpsr[bank] = value;
+        break;
+
+    case GPCR:         /* GPIO Pin-Output Clear registers */
+        s->olevel[bank] &= ~value;
+        pxa2xx_gpio_handler_update(s);
+        break;
+
+    case GRER:         /* GPIO Rising-Edge Detect Enable registers */
+        s->rising[bank] = value;
+        break;
+
+    case GFER:         /* GPIO Falling-Edge Detect Enable registers */
+        s->falling[bank] = value;
+        break;
+
+    case GAFR_L:       /* GPIO Alternate Function registers */
+        s->gafr[bank * 2] = value;
+        break;
+
+    case GAFR_U:       /* GPIO Alternate Function registers */
+        s->gafr[bank * 2 + 1] = value;
+        break;
+
+    case GEDR:         /* GPIO Edge Detect Status registers */
+        s->status[bank] &= ~value;
+        pxa2xx_gpio_irq_update(s);
+        break;
+
+    default:
+        hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
+    }
+}
+
+static const MemoryRegionOps pxa_gpio_ops = {
+    .read = pxa2xx_gpio_read,
+    .write = pxa2xx_gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+DeviceState *pxa2xx_gpio_init(hwaddr base,
+                              ARMCPU *cpu, DeviceState *pic, int lines)
+{
+    CPUState *cs = CPU(cpu);
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "pxa2xx-gpio");
+    qdev_prop_set_int32(dev, "lines", lines);
+    qdev_prop_set_int32(dev, "ncpu", cs->cpu_index);
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
+                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_0));
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1,
+                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_1));
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2,
+                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_X));
+
+    return dev;
+}
+
+static int pxa2xx_gpio_initfn(SysBusDevice *dev)
+{
+    PXA2xxGPIOInfo *s;
+
+    s = FROM_SYSBUS(PXA2xxGPIOInfo, dev);
+
+    s->cpu = ARM_CPU(qemu_get_cpu(s->ncpu));
+
+    qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
+    qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
+
+    memory_region_init_io(&s->iomem, &pxa_gpio_ops, s, "pxa2xx-gpio", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq0);
+    sysbus_init_irq(dev, &s->irq1);
+    sysbus_init_irq(dev, &s->irqX);
+
+    return 0;
+}
+
+/*
+ * Registers a callback to notify on GPLR reads.  This normally
+ * shouldn't be needed but it is used for the hack on Spitz machines.
+ */
+void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler)
+{
+    PXA2xxGPIOInfo *s = FROM_SYSBUS(PXA2xxGPIOInfo, SYS_BUS_DEVICE(dev));
+    s->read_notify = handler;
+}
+
+static const VMStateDescription vmstate_pxa2xx_gpio_regs = {
+    .name = "pxa2xx-gpio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_INT32(lines, PXA2xxGPIOInfo),
+        VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(olevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(dir, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(rising, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(falling, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(status, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(gafr, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS * 2),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static Property pxa2xx_gpio_properties[] = {
+    DEFINE_PROP_INT32("lines", PXA2xxGPIOInfo, lines, 0),
+    DEFINE_PROP_INT32("ncpu", PXA2xxGPIOInfo, ncpu, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pxa2xx_gpio_initfn;
+    dc->desc = "PXA2xx GPIO controller";
+    dc->props = pxa2xx_gpio_properties;
+}
+
+static const TypeInfo pxa2xx_gpio_info = {
+    .name          = "pxa2xx-gpio",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PXA2xxGPIOInfo),
+    .class_init    = pxa2xx_gpio_class_init,
+};
+
+static void pxa2xx_gpio_register_types(void)
+{
+    type_register_static(&pxa2xx_gpio_info);
+}
+
+type_init(pxa2xx_gpio_register_types)
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
new file mode 100644 (file)
index 0000000..145fc78
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * Intel XScale PXA Programmable Interrupt Controller.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Copyright (c) 2006 Thorsten Zitterell
+ * Written by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/sysbus.h"
+
+#define ICIP   0x00    /* Interrupt Controller IRQ Pending register */
+#define ICMR   0x04    /* Interrupt Controller Mask register */
+#define ICLR   0x08    /* Interrupt Controller Level register */
+#define ICFP   0x0c    /* Interrupt Controller FIQ Pending register */
+#define ICPR   0x10    /* Interrupt Controller Pending register */
+#define ICCR   0x14    /* Interrupt Controller Control register */
+#define ICHP   0x18    /* Interrupt Controller Highest Priority register */
+#define IPR0   0x1c    /* Interrupt Controller Priority register 0 */
+#define IPR31  0x98    /* Interrupt Controller Priority register 31 */
+#define ICIP2  0x9c    /* Interrupt Controller IRQ Pending register 2 */
+#define ICMR2  0xa0    /* Interrupt Controller Mask register 2 */
+#define ICLR2  0xa4    /* Interrupt Controller Level register 2 */
+#define ICFP2  0xa8    /* Interrupt Controller FIQ Pending register 2 */
+#define ICPR2  0xac    /* Interrupt Controller Pending register 2 */
+#define IPR32  0xb0    /* Interrupt Controller Priority register 32 */
+#define IPR39  0xcc    /* Interrupt Controller Priority register 39 */
+
+#define PXA2XX_PIC_SRCS        40
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    ARMCPU *cpu;
+    uint32_t int_enabled[2];
+    uint32_t int_pending[2];
+    uint32_t is_fiq[2];
+    uint32_t int_idle;
+    uint32_t priority[PXA2XX_PIC_SRCS];
+} PXA2xxPICState;
+
+static void pxa2xx_pic_update(void *opaque)
+{
+    uint32_t mask[2];
+    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
+
+    if (s->cpu->env.halted) {
+        mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
+        mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
+        if (mask[0] || mask[1]) {
+            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+        }
+    }
+
+    mask[0] = s->int_pending[0] & s->int_enabled[0];
+    mask[1] = s->int_pending[1] & s->int_enabled[1];
+
+    if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) {
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+    } else {
+        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+    }
+
+    if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) {
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+    }
+}
+
+/* Note: Here level means state of the signal on a pin, not
+ * IRQ/FIQ distinction as in PXA Developer Manual.  */
+static void pxa2xx_pic_set_irq(void *opaque, int irq, int level)
+{
+    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
+    int int_set = (irq >= 32);
+    irq &= 31;
+
+    if (level)
+        s->int_pending[int_set] |= 1 << irq;
+    else
+        s->int_pending[int_set] &= ~(1 << irq);
+
+    pxa2xx_pic_update(opaque);
+}
+
+static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
+    int i, int_set, irq;
+    uint32_t bit, mask[2];
+    uint32_t ichp = 0x003f003f;        /* Both IDs invalid */
+
+    mask[0] = s->int_pending[0] & s->int_enabled[0];
+    mask[1] = s->int_pending[1] & s->int_enabled[1];
+
+    for (i = PXA2XX_PIC_SRCS - 1; i >= 0; i --) {
+        irq = s->priority[i] & 0x3f;
+        if ((s->priority[i] & (1 << 31)) && irq < PXA2XX_PIC_SRCS) {
+            /* Source peripheral ID is valid.  */
+            bit = 1 << (irq & 31);
+            int_set = (irq >= 32);
+
+            if (mask[int_set] & bit & s->is_fiq[int_set]) {
+                /* FIQ asserted */
+                ichp &= 0xffff0000;
+                ichp |= (1 << 15) | irq;
+            }
+
+            if (mask[int_set] & bit & ~s->is_fiq[int_set]) {
+                /* IRQ asserted */
+                ichp &= 0x0000ffff;
+                ichp |= (1 << 31) | (irq << 16);
+            }
+        }
+    }
+
+    return ichp;
+}
+
+static uint64_t pxa2xx_pic_mem_read(void *opaque, hwaddr offset,
+                                    unsigned size)
+{
+    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
+
+    switch (offset) {
+    case ICIP: /* IRQ Pending register */
+        return s->int_pending[0] & ~s->is_fiq[0] & s->int_enabled[0];
+    case ICIP2:        /* IRQ Pending register 2 */
+        return s->int_pending[1] & ~s->is_fiq[1] & s->int_enabled[1];
+    case ICMR: /* Mask register */
+        return s->int_enabled[0];
+    case ICMR2:        /* Mask register 2 */
+        return s->int_enabled[1];
+    case ICLR: /* Level register */
+        return s->is_fiq[0];
+    case ICLR2:        /* Level register 2 */
+        return s->is_fiq[1];
+    case ICCR: /* Idle mask */
+        return (s->int_idle == 0);
+    case ICFP: /* FIQ Pending register */
+        return s->int_pending[0] & s->is_fiq[0] & s->int_enabled[0];
+    case ICFP2:        /* FIQ Pending register 2 */
+        return s->int_pending[1] & s->is_fiq[1] & s->int_enabled[1];
+    case ICPR: /* Pending register */
+        return s->int_pending[0];
+    case ICPR2:        /* Pending register 2 */
+        return s->int_pending[1];
+    case IPR0  ... IPR31:
+        return s->priority[0  + ((offset - IPR0 ) >> 2)];
+    case IPR32 ... IPR39:
+        return s->priority[32 + ((offset - IPR32) >> 2)];
+    case ICHP: /* Highest Priority register */
+        return pxa2xx_pic_highest(s);
+    default:
+        printf("%s: Bad register offset " REG_FMT "\n", __FUNCTION__, offset);
+        return 0;
+    }
+}
+
+static void pxa2xx_pic_mem_write(void *opaque, hwaddr offset,
+                                 uint64_t value, unsigned size)
+{
+    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
+
+    switch (offset) {
+    case ICMR: /* Mask register */
+        s->int_enabled[0] = value;
+        break;
+    case ICMR2:        /* Mask register 2 */
+        s->int_enabled[1] = value;
+        break;
+    case ICLR: /* Level register */
+        s->is_fiq[0] = value;
+        break;
+    case ICLR2:        /* Level register 2 */
+        s->is_fiq[1] = value;
+        break;
+    case ICCR: /* Idle mask */
+        s->int_idle = (value & 1) ? 0 : ~0;
+        break;
+    case IPR0  ... IPR31:
+        s->priority[0  + ((offset - IPR0 ) >> 2)] = value & 0x8000003f;
+        break;
+    case IPR32 ... IPR39:
+        s->priority[32 + ((offset - IPR32) >> 2)] = value & 0x8000003f;
+        break;
+    default:
+        printf("%s: Bad register offset " REG_FMT "\n", __FUNCTION__, offset);
+        return;
+    }
+    pxa2xx_pic_update(opaque);
+}
+
+/* Interrupt Controller Coprocessor Space Register Mapping */
+static const int pxa2xx_cp_reg_map[0x10] = {
+    [0x0 ... 0xf] = -1,
+    [0x0] = ICIP,
+    [0x1] = ICMR,
+    [0x2] = ICLR,
+    [0x3] = ICFP,
+    [0x4] = ICPR,
+    [0x5] = ICHP,
+    [0x6] = ICIP2,
+    [0x7] = ICMR2,
+    [0x8] = ICLR2,
+    [0x9] = ICFP2,
+    [0xa] = ICPR2,
+};
+
+static int pxa2xx_pic_cp_read(CPUARMState *env, const ARMCPRegInfo *ri,
+                              uint64_t *value)
+{
+    int offset = pxa2xx_cp_reg_map[ri->crn];
+    *value = pxa2xx_pic_mem_read(ri->opaque, offset, 4);
+    return 0;
+}
+
+static int pxa2xx_pic_cp_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                               uint64_t value)
+{
+    int offset = pxa2xx_cp_reg_map[ri->crn];
+    pxa2xx_pic_mem_write(ri->opaque, offset, value, 4);
+    return 0;
+}
+
+#define REGINFO_FOR_PIC_CP(NAME, CRN) \
+    { .name = NAME, .cp = 6, .crn = CRN, .crm = 0, .opc1 = 0, .opc2 = 0, \
+      .access = PL1_RW, \
+      .readfn = pxa2xx_pic_cp_read, .writefn = pxa2xx_pic_cp_write }
+
+static const ARMCPRegInfo pxa_pic_cp_reginfo[] = {
+    REGINFO_FOR_PIC_CP("ICIP", 0),
+    REGINFO_FOR_PIC_CP("ICMR", 1),
+    REGINFO_FOR_PIC_CP("ICLR", 2),
+    REGINFO_FOR_PIC_CP("ICFP", 3),
+    REGINFO_FOR_PIC_CP("ICPR", 4),
+    REGINFO_FOR_PIC_CP("ICHP", 5),
+    REGINFO_FOR_PIC_CP("ICIP2", 6),
+    REGINFO_FOR_PIC_CP("ICMR2", 7),
+    REGINFO_FOR_PIC_CP("ICLR2", 8),
+    REGINFO_FOR_PIC_CP("ICFP2", 9),
+    REGINFO_FOR_PIC_CP("ICPR2", 0xa),
+    REGINFO_SENTINEL
+};
+
+static const MemoryRegionOps pxa2xx_pic_ops = {
+    .read = pxa2xx_pic_mem_read,
+    .write = pxa2xx_pic_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int pxa2xx_pic_post_load(void *opaque, int version_id)
+{
+    pxa2xx_pic_update(opaque);
+    return 0;
+}
+
+DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu)
+{
+    CPUARMState *env = &cpu->env;
+    DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
+    PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, SYS_BUS_DEVICE(dev));
+
+    s->cpu = cpu;
+
+    s->int_pending[0] = 0;
+    s->int_pending[1] = 0;
+    s->int_enabled[0] = 0;
+    s->int_enabled[1] = 0;
+    s->is_fiq[0] = 0;
+    s->is_fiq[1] = 0;
+
+    qdev_init_nofail(dev);
+
+    qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS);
+
+    /* Enable IC memory-mapped registers access.  */
+    memory_region_init_io(&s->iomem, &pxa2xx_pic_ops, s,
+                          "pxa2xx-pic", 0x00100000);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+
+    /* Enable IC coprocessor access.  */
+    define_arm_cp_regs_with_opaque(arm_env_get_cpu(env), pxa_pic_cp_reginfo, s);
+
+    return dev;
+}
+
+static VMStateDescription vmstate_pxa2xx_pic_regs = {
+    .name = "pxa2xx_pic",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = pxa2xx_pic_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(int_enabled, PXA2xxPICState, 2),
+        VMSTATE_UINT32_ARRAY(int_pending, PXA2xxPICState, 2),
+        VMSTATE_UINT32_ARRAY(is_fiq, PXA2xxPICState, 2),
+        VMSTATE_UINT32(int_idle, PXA2xxPICState),
+        VMSTATE_UINT32_ARRAY(priority, PXA2xxPICState, PXA2XX_PIC_SRCS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static int pxa2xx_pic_initfn(SysBusDevice *dev)
+{
+    return 0;
+}
+
+static void pxa2xx_pic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pxa2xx_pic_initfn;
+    dc->desc = "PXA2xx PIC";
+    dc->vmsd = &vmstate_pxa2xx_pic_regs;
+}
+
+static const TypeInfo pxa2xx_pic_info = {
+    .name          = "pxa2xx_pic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PXA2xxPICState),
+    .class_init    = pxa2xx_pic_class_init,
+};
+
+static void pxa2xx_pic_register_types(void)
+{
+    type_register_static(&pxa2xx_pic_info);
+}
+
+type_init(pxa2xx_pic_register_types)
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
new file mode 100644 (file)
index 0000000..5fb490c
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * ARM RealView Baseboard System emulation.
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/primecell.h"
+#include "hw/devices.h"
+#include "hw/pci/pci.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/i2c.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define SMP_BOOT_ADDR 0xe0000000
+#define SMP_BOOTREG_ADDR 0x10000030
+
+/* Board init.  */
+
+static struct arm_boot_info realview_binfo = {
+    .smp_loader_start = SMP_BOOT_ADDR,
+    .smp_bootreg_addr = SMP_BOOTREG_ADDR,
+};
+
+/* The following two lists must be consistent.  */
+enum realview_board_type {
+    BOARD_EB,
+    BOARD_EB_MPCORE,
+    BOARD_PB_A8,
+    BOARD_PBX_A9,
+};
+
+static const int realview_board_id[] = {
+    0x33b,
+    0x33b,
+    0x769,
+    0x76d
+};
+
+static void realview_init(QEMUMachineInitArgs *args,
+                          enum realview_board_type board_type)
+{
+    ARMCPU *cpu = NULL;
+    CPUARMState *env;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_hack = g_new(MemoryRegion, 1);
+    DeviceState *dev, *sysctl, *gpio2, *pl041;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[64];
+    qemu_irq mmc_irq[2];
+    PCIBus *pci_bus;
+    NICInfo *nd;
+    i2c_bus *i2c;
+    int n;
+    int done_nic = 0;
+    qemu_irq cpu_irq[4];
+    int is_mpcore = 0;
+    int is_pb = 0;
+    uint32_t proc_id = 0;
+    uint32_t sys_id;
+    ram_addr_t low_ram_size;
+    ram_addr_t ram_size = args->ram_size;
+
+    switch (board_type) {
+    case BOARD_EB:
+        break;
+    case BOARD_EB_MPCORE:
+        is_mpcore = 1;
+        break;
+    case BOARD_PB_A8:
+        is_pb = 1;
+        break;
+    case BOARD_PBX_A9:
+        is_mpcore = 1;
+        is_pb = 1;
+        break;
+    }
+    for (n = 0; n < smp_cpus; n++) {
+        cpu = cpu_arm_init(args->cpu_model);
+        if (!cpu) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(cpu);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+    env = &cpu->env;
+    if (arm_feature(env, ARM_FEATURE_V7)) {
+        if (is_mpcore) {
+            proc_id = 0x0c000000;
+        } else {
+            proc_id = 0x0e000000;
+        }
+    } else if (arm_feature(env, ARM_FEATURE_V6K)) {
+        proc_id = 0x06000000;
+    } else if (arm_feature(env, ARM_FEATURE_V6)) {
+        proc_id = 0x04000000;
+    } else {
+        proc_id = 0x02000000;
+    }
+
+    if (is_pb && ram_size > 0x20000000) {
+        /* Core tile RAM.  */
+        low_ram_size = ram_size - 0x20000000;
+        ram_size = 0x20000000;
+        memory_region_init_ram(ram_lo, "realview.lowmem", low_ram_size);
+        vmstate_register_ram_global(ram_lo);
+        memory_region_add_subregion(sysmem, 0x20000000, ram_lo);
+    }
+
+    memory_region_init_ram(ram_hi, "realview.highmem", ram_size);
+    vmstate_register_ram_global(ram_hi);
+    low_ram_size = ram_size;
+    if (low_ram_size > 0x10000000)
+      low_ram_size = 0x10000000;
+    /* SDRAM at address zero.  */
+    memory_region_init_alias(ram_alias, "realview.alias",
+                             ram_hi, 0, low_ram_size);
+    memory_region_add_subregion(sysmem, 0, ram_alias);
+    if (is_pb) {
+        /* And again at a high address.  */
+        memory_region_add_subregion(sysmem, 0x70000000, ram_hi);
+    } else {
+        ram_size = low_ram_size;
+    }
+
+    sys_id = is_pb ? 0x01780500 : 0xc1400400;
+    sysctl = qdev_create(NULL, "realview_sysctl");
+    qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
+    qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
+    qdev_init_nofail(sysctl);
+    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
+
+    if (is_mpcore) {
+        hwaddr periphbase;
+        dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
+        qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+        qdev_init_nofail(dev);
+        busdev = SYS_BUS_DEVICE(dev);
+        if (is_pb) {
+            periphbase = 0x1f000000;
+        } else {
+            periphbase = 0x10100000;
+        }
+        sysbus_mmio_map(busdev, 0, periphbase);
+        for (n = 0; n < smp_cpus; n++) {
+            sysbus_connect_irq(busdev, n, cpu_irq[n]);
+        }
+        sysbus_create_varargs("l2x0", periphbase + 0x2000, NULL);
+        /* Both A9 and 11MPCore put the GIC CPU i/f at base + 0x100 */
+        realview_binfo.gic_cpu_if_addr = periphbase + 0x100;
+    } else {
+        uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000;
+        /* For now just create the nIRQ GIC, and ignore the others.  */
+        dev = sysbus_create_simple("realview_gic", gic_addr, cpu_irq[0]);
+    }
+    for (n = 0; n < 64; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    pl041 = qdev_create(NULL, "pl041");
+    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
+    qdev_init_nofail(pl041);
+    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[19]);
+
+    sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]);
+    sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]);
+
+    sysbus_create_simple("pl011", 0x10009000, pic[12]);
+    sysbus_create_simple("pl011", 0x1000a000, pic[13]);
+    sysbus_create_simple("pl011", 0x1000b000, pic[14]);
+    sysbus_create_simple("pl011", 0x1000c000, pic[15]);
+
+    /* DMA controller is optional, apparently.  */
+    sysbus_create_simple("pl081", 0x10030000, pic[24]);
+
+    sysbus_create_simple("sp804", 0x10011000, pic[4]);
+    sysbus_create_simple("sp804", 0x10012000, pic[5]);
+
+    sysbus_create_simple("pl061", 0x10013000, pic[6]);
+    sysbus_create_simple("pl061", 0x10014000, pic[7]);
+    gpio2 = sysbus_create_simple("pl061", 0x10015000, pic[8]);
+
+    sysbus_create_simple("pl111", 0x10020000, pic[23]);
+
+    dev = sysbus_create_varargs("pl181", 0x10005000, pic[17], pic[18], NULL);
+    /* Wire up MMC card detect and read-only signals. These have
+     * to go to both the PL061 GPIO and the sysctl register.
+     * Note that the PL181 orders these lines (readonly,inserted)
+     * and the PL061 has them the other way about. Also the card
+     * detect line is inverted.
+     */
+    mmc_irq[0] = qemu_irq_split(
+        qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
+        qdev_get_gpio_in(gpio2, 1));
+    mmc_irq[1] = qemu_irq_split(
+        qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
+        qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
+    qdev_connect_gpio_out(dev, 0, mmc_irq[0]);
+    qdev_connect_gpio_out(dev, 1, mmc_irq[1]);
+
+    sysbus_create_simple("pl031", 0x10017000, pic[10]);
+
+    if (!is_pb) {
+        dev = qdev_create(NULL, "realview_pci");
+        busdev = SYS_BUS_DEVICE(dev);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(busdev, 0, 0x61000000); /* PCI self-config */
+        sysbus_mmio_map(busdev, 1, 0x62000000); /* PCI config */
+        sysbus_mmio_map(busdev, 2, 0x63000000); /* PCI I/O */
+        sysbus_connect_irq(busdev, 0, pic[48]);
+        sysbus_connect_irq(busdev, 1, pic[49]);
+        sysbus_connect_irq(busdev, 2, pic[50]);
+        sysbus_connect_irq(busdev, 3, pic[51]);
+        pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
+        if (usb_enabled(false)) {
+            pci_create_simple(pci_bus, -1, "pci-ohci");
+        }
+        n = drive_get_max_bus(IF_SCSI);
+        while (n >= 0) {
+            pci_create_simple(pci_bus, -1, "lsi53c895a");
+            n--;
+        }
+    }
+    for(n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+
+        if (!done_nic && (!nd->model ||
+                    strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0)) {
+            if (is_pb) {
+                lan9118_init(nd, 0x4e000000, pic[28]);
+            } else {
+                smc91c111_init(nd, 0x4e000000, pic[28]);
+            }
+            done_nic = 1;
+        } else {
+            pci_nic_init_nofail(nd, "rtl8139", NULL);
+        }
+    }
+
+    dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
+    i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
+    i2c_create_slave(i2c, "ds1338", 0x68);
+
+    /* Memory map for RealView Emulation Baseboard:  */
+    /* 0x10000000 System registers.  */
+    /*  0x10001000 System controller.  */
+    /* 0x10002000 Two-Wire Serial Bus.  */
+    /* 0x10003000 Reserved.  */
+    /*  0x10004000 AACI.  */
+    /*  0x10005000 MCI.  */
+    /* 0x10006000 KMI0.  */
+    /* 0x10007000 KMI1.  */
+    /*  0x10008000 Character LCD. (EB) */
+    /* 0x10009000 UART0.  */
+    /* 0x1000a000 UART1.  */
+    /* 0x1000b000 UART2.  */
+    /* 0x1000c000 UART3.  */
+    /*  0x1000d000 SSPI.  */
+    /*  0x1000e000 SCI.  */
+    /* 0x1000f000 Reserved.  */
+    /*  0x10010000 Watchdog.  */
+    /* 0x10011000 Timer 0+1.  */
+    /* 0x10012000 Timer 2+3.  */
+    /*  0x10013000 GPIO 0.  */
+    /*  0x10014000 GPIO 1.  */
+    /*  0x10015000 GPIO 2.  */
+    /*  0x10002000 Two-Wire Serial Bus - DVI. (PB) */
+    /* 0x10017000 RTC.  */
+    /*  0x10018000 DMC.  */
+    /*  0x10019000 PCI controller config.  */
+    /*  0x10020000 CLCD.  */
+    /* 0x10030000 DMA Controller.  */
+    /* 0x10040000 GIC1. (EB) */
+    /*  0x10050000 GIC2. (EB) */
+    /*  0x10060000 GIC3. (EB) */
+    /*  0x10070000 GIC4. (EB) */
+    /*  0x10080000 SMC.  */
+    /* 0x1e000000 GIC1. (PB) */
+    /*  0x1e001000 GIC2. (PB) */
+    /*  0x1e002000 GIC3. (PB) */
+    /*  0x1e003000 GIC4. (PB) */
+    /*  0x40000000 NOR flash.  */
+    /*  0x44000000 DoC flash.  */
+    /*  0x48000000 SRAM.  */
+    /*  0x4c000000 Configuration flash.  */
+    /* 0x4e000000 Ethernet.  */
+    /*  0x4f000000 USB.  */
+    /*  0x50000000 PISMO.  */
+    /*  0x54000000 PISMO.  */
+    /*  0x58000000 PISMO.  */
+    /*  0x5c000000 PISMO.  */
+    /* 0x60000000 PCI.  */
+    /* 0x61000000 PCI Self Config.  */
+    /* 0x62000000 PCI Config.  */
+    /* 0x63000000 PCI IO.  */
+    /* 0x64000000 PCI mem 0.  */
+    /* 0x68000000 PCI mem 1.  */
+    /* 0x6c000000 PCI mem 2.  */
+
+    /* ??? Hack to map an additional page of ram for the secondary CPU
+       startup code.  I guess this works on real hardware because the
+       BootROM happens to be in ROM/flash or in memory that isn't clobbered
+       until after Linux boots the secondary CPUs.  */
+    memory_region_init_ram(ram_hack, "realview.hack", 0x1000);
+    vmstate_register_ram_global(ram_hack);
+    memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
+
+    realview_binfo.ram_size = ram_size;
+    realview_binfo.kernel_filename = args->kernel_filename;
+    realview_binfo.kernel_cmdline = args->kernel_cmdline;
+    realview_binfo.initrd_filename = args->initrd_filename;
+    realview_binfo.nb_cpus = smp_cpus;
+    realview_binfo.board_id = realview_board_id[board_type];
+    realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo);
+}
+
+static void realview_eb_init(QEMUMachineInitArgs *args)
+{
+    if (!args->cpu_model) {
+        args->cpu_model = "arm926";
+    }
+    realview_init(args, BOARD_EB);
+}
+
+static void realview_eb_mpcore_init(QEMUMachineInitArgs *args)
+{
+    if (!args->cpu_model) {
+        args->cpu_model = "arm11mpcore";
+    }
+    realview_init(args, BOARD_EB_MPCORE);
+}
+
+static void realview_pb_a8_init(QEMUMachineInitArgs *args)
+{
+    if (!args->cpu_model) {
+        args->cpu_model = "cortex-a8";
+    }
+    realview_init(args, BOARD_PB_A8);
+}
+
+static void realview_pbx_a9_init(QEMUMachineInitArgs *args)
+{
+    if (!args->cpu_model) {
+        args->cpu_model = "cortex-a9";
+    }
+    realview_init(args, BOARD_PBX_A9);
+}
+
+static QEMUMachine realview_eb_machine = {
+    .name = "realview-eb",
+    .desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)",
+    .init = realview_eb_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine realview_eb_mpcore_machine = {
+    .name = "realview-eb-mpcore",
+    .desc = "ARM RealView Emulation Baseboard (ARM11MPCore)",
+    .init = realview_eb_mpcore_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine realview_pb_a8_machine = {
+    .name = "realview-pb-a8",
+    .desc = "ARM RealView Platform Baseboard for Cortex-A8",
+    .init = realview_pb_a8_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine realview_pbx_a9_machine = {
+    .name = "realview-pbx-a9",
+    .desc = "ARM RealView Platform Baseboard Explore for Cortex-A9",
+    .init = realview_pbx_a9_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void realview_machine_init(void)
+{
+    qemu_register_machine(&realview_eb_machine);
+    qemu_register_machine(&realview_eb_mpcore_machine);
+    qemu_register_machine(&realview_pb_a8_machine);
+    qemu_register_machine(&realview_pbx_a9_machine);
+}
+
+machine_init(realview_machine_init);
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
new file mode 100644 (file)
index 0000000..f5832be
--- /dev/null
@@ -0,0 +1,1138 @@
+/*
+ * PXA270-based Clamshell PDA platforms.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
+#include "sysemu/sysemu.h"
+#include "hw/pcmcia.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
+#include "hw/flash.h"
+#include "qemu/timer.h"
+#include "hw/devices.h"
+#include "hw/sharpsl.h"
+#include "ui/console.h"
+#include "block/block.h"
+#include "audio/audio.h"
+#include "hw/boards.h"
+#include "sysemu/blockdev.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+#undef REG_FMT
+#define REG_FMT                        "0x%02lx"
+
+/* Spitz Flash */
+#define FLASH_BASE             0x0c000000
+#define FLASH_ECCLPLB          0x00    /* Line parity 7 - 0 bit */
+#define FLASH_ECCLPUB          0x04    /* Line parity 15 - 8 bit */
+#define FLASH_ECCCP            0x08    /* Column parity 5 - 0 bit */
+#define FLASH_ECCCNTR          0x0c    /* ECC byte counter */
+#define FLASH_ECCCLRR          0x10    /* Clear ECC */
+#define FLASH_FLASHIO          0x14    /* Flash I/O */
+#define FLASH_FLASHCTL         0x18    /* Flash Control */
+
+#define FLASHCTL_CE0           (1 << 0)
+#define FLASHCTL_CLE           (1 << 1)
+#define FLASHCTL_ALE           (1 << 2)
+#define FLASHCTL_WP            (1 << 3)
+#define FLASHCTL_CE1           (1 << 4)
+#define FLASHCTL_RYBY          (1 << 5)
+#define FLASHCTL_NCE           (FLASHCTL_CE0 | FLASHCTL_CE1)
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    DeviceState *nand;
+    uint8_t ctl;
+    uint8_t manf_id;
+    uint8_t chip_id;
+    ECCState ecc;
+} SLNANDState;
+
+static uint64_t sl_read(void *opaque, hwaddr addr, unsigned size)
+{
+    SLNANDState *s = (SLNANDState *) opaque;
+    int ryby;
+
+    switch (addr) {
+#define BSHR(byte, from, to)   ((s->ecc.lp[byte] >> (from - to)) & (1 << to))
+    case FLASH_ECCLPLB:
+        return BSHR(0, 4, 0) | BSHR(0, 5, 2) | BSHR(0, 6, 4) | BSHR(0, 7, 6) |
+                BSHR(1, 4, 1) | BSHR(1, 5, 3) | BSHR(1, 6, 5) | BSHR(1, 7, 7);
+
+#define BSHL(byte, from, to)   ((s->ecc.lp[byte] << (to - from)) & (1 << to))
+    case FLASH_ECCLPUB:
+        return BSHL(0, 0, 0) | BSHL(0, 1, 2) | BSHL(0, 2, 4) | BSHL(0, 3, 6) |
+                BSHL(1, 0, 1) | BSHL(1, 1, 3) | BSHL(1, 2, 5) | BSHL(1, 3, 7);
+
+    case FLASH_ECCCP:
+        return s->ecc.cp;
+
+    case FLASH_ECCCNTR:
+        return s->ecc.count & 0xff;
+
+    case FLASH_FLASHCTL:
+        nand_getpins(s->nand, &ryby);
+        if (ryby)
+            return s->ctl | FLASHCTL_RYBY;
+        else
+            return s->ctl;
+
+    case FLASH_FLASHIO:
+        if (size == 4) {
+            return ecc_digest(&s->ecc, nand_getio(s->nand)) |
+                (ecc_digest(&s->ecc, nand_getio(s->nand)) << 16);
+        }
+        return ecc_digest(&s->ecc, nand_getio(s->nand));
+
+    default:
+        zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
+    }
+    return 0;
+}
+
+static void sl_write(void *opaque, hwaddr addr,
+                     uint64_t value, unsigned size)
+{
+    SLNANDState *s = (SLNANDState *) opaque;
+
+    switch (addr) {
+    case FLASH_ECCCLRR:
+        /* Value is ignored.  */
+        ecc_reset(&s->ecc);
+        break;
+
+    case FLASH_FLASHCTL:
+        s->ctl = value & 0xff & ~FLASHCTL_RYBY;
+        nand_setpins(s->nand,
+                        s->ctl & FLASHCTL_CLE,
+                        s->ctl & FLASHCTL_ALE,
+                        s->ctl & FLASHCTL_NCE,
+                        s->ctl & FLASHCTL_WP,
+                        0);
+        break;
+
+    case FLASH_FLASHIO:
+        nand_setio(s->nand, ecc_digest(&s->ecc, value & 0xff));
+        break;
+
+    default:
+        zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
+    }
+}
+
+enum {
+    FLASH_128M,
+    FLASH_1024M,
+};
+
+static const MemoryRegionOps sl_ops = {
+    .read = sl_read,
+    .write = sl_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void sl_flash_register(PXA2xxState *cpu, int size)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "sl-nand");
+
+    qdev_prop_set_uint8(dev, "manf_id", NAND_MFR_SAMSUNG);
+    if (size == FLASH_128M)
+        qdev_prop_set_uint8(dev, "chip_id", 0x73);
+    else if (size == FLASH_1024M)
+        qdev_prop_set_uint8(dev, "chip_id", 0xf1);
+
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, FLASH_BASE);
+}
+
+static int sl_nand_init(SysBusDevice *dev) {
+    SLNANDState *s;
+    DriveInfo *nand;
+
+    s = FROM_SYSBUS(SLNANDState, dev);
+
+    s->ctl = 0;
+    nand = drive_get(IF_MTD, 0, 0);
+    s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
+
+    memory_region_init_io(&s->iomem, &sl_ops, s, "sl", 0x40);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    return 0;
+}
+
+/* Spitz Keyboard */
+
+#define SPITZ_KEY_STROBE_NUM   11
+#define SPITZ_KEY_SENSE_NUM    7
+
+static const int spitz_gpio_key_sense[SPITZ_KEY_SENSE_NUM] = {
+    12, 17, 91, 34, 36, 38, 39
+};
+
+static const int spitz_gpio_key_strobe[SPITZ_KEY_STROBE_NUM] = {
+    88, 23, 24, 25, 26, 27, 52, 103, 107, 108, 114
+};
+
+/* Eighth additional row maps the special keys */
+static int spitz_keymap[SPITZ_KEY_SENSE_NUM + 1][SPITZ_KEY_STROBE_NUM] = {
+    { 0x1d, 0x02, 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0e, 0x3f, 0x40 },
+    {  -1 , 0x03, 0x05, 0x13, 0x15, 0x09, 0x17, 0x18, 0x19, 0x41, 0x42 },
+    { 0x0f, 0x10, 0x12, 0x14, 0x22, 0x16, 0x24, 0x25,  -1 ,  -1 ,  -1  },
+    { 0x3c, 0x11, 0x1f, 0x21, 0x2f, 0x23, 0x32, 0x26,  -1 , 0x36,  -1  },
+    { 0x3b, 0x1e, 0x20, 0x2e, 0x30, 0x31, 0x34,  -1 , 0x1c, 0x2a,  -1  },
+    { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33,  -1 , 0x48,  -1 ,  -1 , 0x38 },
+    { 0x37, 0x3d,  -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d,  -1 ,  -1  },
+    { 0x52, 0x43, 0x01, 0x47, 0x49,  -1 ,  -1 ,  -1 ,  -1 ,  -1 ,  -1  },
+};
+
+#define SPITZ_GPIO_AK_INT      13      /* Remote control */
+#define SPITZ_GPIO_SYNC                16      /* Sync button */
+#define SPITZ_GPIO_ON_KEY      95      /* Power button */
+#define SPITZ_GPIO_SWA         97      /* Lid */
+#define SPITZ_GPIO_SWB         96      /* Tablet mode */
+
+/* The special buttons are mapped to unused keys */
+static const int spitz_gpiomap[5] = {
+    SPITZ_GPIO_AK_INT, SPITZ_GPIO_SYNC, SPITZ_GPIO_ON_KEY,
+    SPITZ_GPIO_SWA, SPITZ_GPIO_SWB,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    qemu_irq sense[SPITZ_KEY_SENSE_NUM];
+    qemu_irq gpiomap[5];
+    int keymap[0x80];
+    uint16_t keyrow[SPITZ_KEY_SENSE_NUM];
+    uint16_t strobe_state;
+    uint16_t sense_state;
+
+    uint16_t pre_map[0x100];
+    uint16_t modifiers;
+    uint16_t imodifiers;
+    uint8_t fifo[16];
+    int fifopos, fifolen;
+    QEMUTimer *kbdtimer;
+} SpitzKeyboardState;
+
+static void spitz_keyboard_sense_update(SpitzKeyboardState *s)
+{
+    int i;
+    uint16_t strobe, sense = 0;
+    for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++) {
+        strobe = s->keyrow[i] & s->strobe_state;
+        if (strobe) {
+            sense |= 1 << i;
+            if (!(s->sense_state & (1 << i)))
+                qemu_irq_raise(s->sense[i]);
+        } else if (s->sense_state & (1 << i))
+            qemu_irq_lower(s->sense[i]);
+    }
+
+    s->sense_state = sense;
+}
+
+static void spitz_keyboard_strobe(void *opaque, int line, int level)
+{
+    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
+
+    if (level)
+        s->strobe_state |= 1 << line;
+    else
+        s->strobe_state &= ~(1 << line);
+    spitz_keyboard_sense_update(s);
+}
+
+static void spitz_keyboard_keydown(SpitzKeyboardState *s, int keycode)
+{
+    int spitz_keycode = s->keymap[keycode & 0x7f];
+    if (spitz_keycode == -1)
+        return;
+
+    /* Handle the additional keys */
+    if ((spitz_keycode >> 4) == SPITZ_KEY_SENSE_NUM) {
+        qemu_set_irq(s->gpiomap[spitz_keycode & 0xf], (keycode < 0x80));
+        return;
+    }
+
+    if (keycode & 0x80)
+        s->keyrow[spitz_keycode >> 4] &= ~(1 << (spitz_keycode & 0xf));
+    else
+        s->keyrow[spitz_keycode >> 4] |= 1 << (spitz_keycode & 0xf);
+
+    spitz_keyboard_sense_update(s);
+}
+
+#define SHIFT  (1 << 7)
+#define CTRL   (1 << 8)
+#define FN     (1 << 9)
+
+#define QUEUE_KEY(c)   s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
+
+static void spitz_keyboard_handler(void *opaque, int keycode)
+{
+    SpitzKeyboardState *s = opaque;
+    uint16_t code;
+    int mapcode;
+    switch (keycode) {
+    case 0x2a: /* Left Shift */
+        s->modifiers |= 1;
+        break;
+    case 0xaa:
+        s->modifiers &= ~1;
+        break;
+    case 0x36: /* Right Shift */
+        s->modifiers |= 2;
+        break;
+    case 0xb6:
+        s->modifiers &= ~2;
+        break;
+    case 0x1d: /* Control */
+        s->modifiers |= 4;
+        break;
+    case 0x9d:
+        s->modifiers &= ~4;
+        break;
+    case 0x38: /* Alt */
+        s->modifiers |= 8;
+        break;
+    case 0xb8:
+        s->modifiers &= ~8;
+        break;
+    }
+
+    code = s->pre_map[mapcode = ((s->modifiers & 3) ?
+            (keycode | SHIFT) :
+            (keycode & ~SHIFT))];
+
+    if (code != mapcode) {
+#if 0
+        if ((code & SHIFT) && !(s->modifiers & 1))
+            QUEUE_KEY(0x2a | (keycode & 0x80));
+        if ((code & CTRL ) && !(s->modifiers & 4))
+            QUEUE_KEY(0x1d | (keycode & 0x80));
+        if ((code & FN   ) && !(s->modifiers & 8))
+            QUEUE_KEY(0x38 | (keycode & 0x80));
+        if ((code & FN   ) && (s->modifiers & 1))
+            QUEUE_KEY(0x2a | (~keycode & 0x80));
+        if ((code & FN   ) && (s->modifiers & 2))
+            QUEUE_KEY(0x36 | (~keycode & 0x80));
+#else
+        if (keycode & 0x80) {
+            if ((s->imodifiers & 1   ) && !(s->modifiers & 1))
+                QUEUE_KEY(0x2a | 0x80);
+            if ((s->imodifiers & 4   ) && !(s->modifiers & 4))
+                QUEUE_KEY(0x1d | 0x80);
+            if ((s->imodifiers & 8   ) && !(s->modifiers & 8))
+                QUEUE_KEY(0x38 | 0x80);
+            if ((s->imodifiers & 0x10) && (s->modifiers & 1))
+                QUEUE_KEY(0x2a);
+            if ((s->imodifiers & 0x20) && (s->modifiers & 2))
+                QUEUE_KEY(0x36);
+            s->imodifiers = 0;
+        } else {
+            if ((code & SHIFT) && !((s->modifiers | s->imodifiers) & 1)) {
+                QUEUE_KEY(0x2a);
+                s->imodifiers |= 1;
+            }
+            if ((code & CTRL ) && !((s->modifiers | s->imodifiers) & 4)) {
+                QUEUE_KEY(0x1d);
+                s->imodifiers |= 4;
+            }
+            if ((code & FN   ) && !((s->modifiers | s->imodifiers) & 8)) {
+                QUEUE_KEY(0x38);
+                s->imodifiers |= 8;
+            }
+            if ((code & FN   ) && (s->modifiers & 1) &&
+                            !(s->imodifiers & 0x10)) {
+                QUEUE_KEY(0x2a | 0x80);
+                s->imodifiers |= 0x10;
+            }
+            if ((code & FN   ) && (s->modifiers & 2) &&
+                            !(s->imodifiers & 0x20)) {
+                QUEUE_KEY(0x36 | 0x80);
+                s->imodifiers |= 0x20;
+            }
+        }
+#endif
+    }
+
+    QUEUE_KEY((code & 0x7f) | (keycode & 0x80));
+}
+
+static void spitz_keyboard_tick(void *opaque)
+{
+    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
+
+    if (s->fifolen) {
+        spitz_keyboard_keydown(s, s->fifo[s->fifopos ++]);
+        s->fifolen --;
+        if (s->fifopos >= 16)
+            s->fifopos = 0;
+    }
+
+    qemu_mod_timer(s->kbdtimer, qemu_get_clock_ns(vm_clock) +
+                   get_ticks_per_sec() / 32);
+}
+
+static void spitz_keyboard_pre_map(SpitzKeyboardState *s)
+{
+    int i;
+    for (i = 0; i < 0x100; i ++)
+        s->pre_map[i] = i;
+    s->pre_map[0x02 | SHIFT    ] = 0x02 | SHIFT;       /* exclam */
+    s->pre_map[0x28 | SHIFT    ] = 0x03 | SHIFT;       /* quotedbl */
+    s->pre_map[0x04 | SHIFT    ] = 0x04 | SHIFT;       /* numbersign */
+    s->pre_map[0x05 | SHIFT    ] = 0x05 | SHIFT;       /* dollar */
+    s->pre_map[0x06 | SHIFT    ] = 0x06 | SHIFT;       /* percent */
+    s->pre_map[0x08 | SHIFT    ] = 0x07 | SHIFT;       /* ampersand */
+    s->pre_map[0x28            ] = 0x08 | SHIFT;       /* apostrophe */
+    s->pre_map[0x0a | SHIFT    ] = 0x09 | SHIFT;       /* parenleft */
+    s->pre_map[0x0b | SHIFT    ] = 0x0a | SHIFT;       /* parenright */
+    s->pre_map[0x29 | SHIFT    ] = 0x0b | SHIFT;       /* asciitilde */
+    s->pre_map[0x03 | SHIFT    ] = 0x0c | SHIFT;       /* at */
+    s->pre_map[0xd3            ] = 0x0e | FN;          /* Delete */
+    s->pre_map[0x3a            ] = 0x0f | FN;          /* Caps_Lock */
+    s->pre_map[0x07 | SHIFT    ] = 0x11 | FN;          /* asciicircum */
+    s->pre_map[0x0d            ] = 0x12 | FN;          /* equal */
+    s->pre_map[0x0d | SHIFT    ] = 0x13 | FN;          /* plus */
+    s->pre_map[0x1a            ] = 0x14 | FN;          /* bracketleft */
+    s->pre_map[0x1b            ] = 0x15 | FN;          /* bracketright */
+    s->pre_map[0x1a | SHIFT    ] = 0x16 | FN;          /* braceleft */
+    s->pre_map[0x1b | SHIFT    ] = 0x17 | FN;          /* braceright */
+    s->pre_map[0x27            ] = 0x22 | FN;          /* semicolon */
+    s->pre_map[0x27 | SHIFT    ] = 0x23 | FN;          /* colon */
+    s->pre_map[0x09 | SHIFT    ] = 0x24 | FN;          /* asterisk */
+    s->pre_map[0x2b            ] = 0x25 | FN;          /* backslash */
+    s->pre_map[0x2b | SHIFT    ] = 0x26 | FN;          /* bar */
+    s->pre_map[0x0c | SHIFT    ] = 0x30 | FN;          /* underscore */
+    s->pre_map[0x33 | SHIFT    ] = 0x33 | FN;          /* less */
+    s->pre_map[0x35            ] = 0x33 | SHIFT;       /* slash */
+    s->pre_map[0x34 | SHIFT    ] = 0x34 | FN;          /* greater */
+    s->pre_map[0x35 | SHIFT    ] = 0x34 | SHIFT;       /* question */
+    s->pre_map[0x49            ] = 0x48 | FN;          /* Page_Up */
+    s->pre_map[0x51            ] = 0x50 | FN;          /* Page_Down */
+
+    s->modifiers = 0;
+    s->imodifiers = 0;
+    s->fifopos = 0;
+    s->fifolen = 0;
+}
+
+#undef SHIFT
+#undef CTRL
+#undef FN
+
+static int spitz_keyboard_post_load(void *opaque, int version_id)
+{
+    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
+
+    /* Release all pressed keys */
+    memset(s->keyrow, 0, sizeof(s->keyrow));
+    spitz_keyboard_sense_update(s);
+    s->modifiers = 0;
+    s->imodifiers = 0;
+    s->fifopos = 0;
+    s->fifolen = 0;
+
+    return 0;
+}
+
+static void spitz_keyboard_register(PXA2xxState *cpu)
+{
+    int i;
+    DeviceState *dev;
+    SpitzKeyboardState *s;
+
+    dev = sysbus_create_simple("spitz-keyboard", -1, NULL);
+    s = FROM_SYSBUS(SpitzKeyboardState, SYS_BUS_DEVICE(dev));
+
+    for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++)
+        qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(cpu->gpio, spitz_gpio_key_sense[i]));
+
+    for (i = 0; i < 5; i ++)
+        s->gpiomap[i] = qdev_get_gpio_in(cpu->gpio, spitz_gpiomap[i]);
+
+    if (!graphic_rotate)
+        s->gpiomap[4] = qemu_irq_invert(s->gpiomap[4]);
+
+    for (i = 0; i < 5; i++)
+        qemu_set_irq(s->gpiomap[i], 0);
+
+    for (i = 0; i < SPITZ_KEY_STROBE_NUM; i ++)
+        qdev_connect_gpio_out(cpu->gpio, spitz_gpio_key_strobe[i],
+                qdev_get_gpio_in(dev, i));
+
+    qemu_mod_timer(s->kbdtimer, qemu_get_clock_ns(vm_clock));
+
+    qemu_add_kbd_event_handler(spitz_keyboard_handler, s);
+}
+
+static int spitz_keyboard_init(SysBusDevice *dev)
+{
+    SpitzKeyboardState *s;
+    int i, j;
+
+    s = FROM_SYSBUS(SpitzKeyboardState, dev);
+
+    for (i = 0; i < 0x80; i ++)
+        s->keymap[i] = -1;
+    for (i = 0; i < SPITZ_KEY_SENSE_NUM + 1; i ++)
+        for (j = 0; j < SPITZ_KEY_STROBE_NUM; j ++)
+            if (spitz_keymap[i][j] != -1)
+                s->keymap[spitz_keymap[i][j]] = (i << 4) | j;
+
+    spitz_keyboard_pre_map(s);
+
+    s->kbdtimer = qemu_new_timer_ns(vm_clock, spitz_keyboard_tick, s);
+    qdev_init_gpio_in(&dev->qdev, spitz_keyboard_strobe, SPITZ_KEY_STROBE_NUM);
+    qdev_init_gpio_out(&dev->qdev, s->sense, SPITZ_KEY_SENSE_NUM);
+
+    return 0;
+}
+
+/* LCD backlight controller */
+
+#define LCDTG_RESCTL   0x00
+#define LCDTG_PHACTRL  0x01
+#define LCDTG_DUTYCTRL 0x02
+#define LCDTG_POWERREG0        0x03
+#define LCDTG_POWERREG1        0x04
+#define LCDTG_GPOR3    0x05
+#define LCDTG_PICTRL   0x06
+#define LCDTG_POLCTRL  0x07
+
+typedef struct {
+    SSISlave ssidev;
+    uint32_t bl_intensity;
+    uint32_t bl_power;
+} SpitzLCDTG;
+
+static void spitz_bl_update(SpitzLCDTG *s)
+{
+    if (s->bl_power && s->bl_intensity)
+        zaurus_printf("LCD Backlight now at %i/63\n", s->bl_intensity);
+    else
+        zaurus_printf("LCD Backlight now off\n");
+}
+
+/* FIXME: Implement GPIO properly and remove this hack.  */
+static SpitzLCDTG *spitz_lcdtg;
+
+static inline void spitz_bl_bit5(void *opaque, int line, int level)
+{
+    SpitzLCDTG *s = spitz_lcdtg;
+    int prev = s->bl_intensity;
+
+    if (level)
+        s->bl_intensity &= ~0x20;
+    else
+        s->bl_intensity |= 0x20;
+
+    if (s->bl_power && prev != s->bl_intensity)
+        spitz_bl_update(s);
+}
+
+static inline void spitz_bl_power(void *opaque, int line, int level)
+{
+    SpitzLCDTG *s = spitz_lcdtg;
+    s->bl_power = !!level;
+    spitz_bl_update(s);
+}
+
+static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value)
+{
+    SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
+    int addr;
+    addr = value >> 5;
+    value &= 0x1f;
+
+    switch (addr) {
+    case LCDTG_RESCTL:
+        if (value)
+            zaurus_printf("LCD in QVGA mode\n");
+        else
+            zaurus_printf("LCD in VGA mode\n");
+        break;
+
+    case LCDTG_DUTYCTRL:
+        s->bl_intensity &= ~0x1f;
+        s->bl_intensity |= value;
+        if (s->bl_power)
+            spitz_bl_update(s);
+        break;
+
+    case LCDTG_POWERREG0:
+        /* Set common voltage to M62332FP */
+        break;
+    }
+    return 0;
+}
+
+static int spitz_lcdtg_init(SSISlave *dev)
+{
+    SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
+
+    spitz_lcdtg = s;
+    s->bl_power = 0;
+    s->bl_intensity = 0x20;
+
+    return 0;
+}
+
+/* SSP devices */
+
+#define CORGI_SSP_PORT         2
+
+#define SPITZ_GPIO_LCDCON_CS   53
+#define SPITZ_GPIO_ADS7846_CS  14
+#define SPITZ_GPIO_MAX1111_CS  20
+#define SPITZ_GPIO_TP_INT      11
+
+static DeviceState *max1111;
+
+/* "Demux" the signal based on current chipselect */
+typedef struct {
+    SSISlave ssidev;
+    SSIBus *bus[3];
+    uint32_t enable[3];
+} CorgiSSPState;
+
+static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
+{
+    CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
+    int i;
+
+    for (i = 0; i < 3; i++) {
+        if (s->enable[i]) {
+            return ssi_transfer(s->bus[i], value);
+        }
+    }
+    return 0;
+}
+
+static void corgi_ssp_gpio_cs(void *opaque, int line, int level)
+{
+    CorgiSSPState *s = (CorgiSSPState *)opaque;
+    assert(line >= 0 && line < 3);
+    s->enable[line] = !level;
+}
+
+#define MAX1111_BATT_VOLT      1
+#define MAX1111_BATT_TEMP      2
+#define MAX1111_ACIN_VOLT      3
+
+#define SPITZ_BATTERY_TEMP     0xe0    /* About 2.9V */
+#define SPITZ_BATTERY_VOLT     0xd0    /* About 4.0V */
+#define SPITZ_CHARGEON_ACIN    0x80    /* About 5.0V */
+
+static void spitz_adc_temp_on(void *opaque, int line, int level)
+{
+    if (!max1111)
+        return;
+
+    if (level)
+        max111x_set_input(max1111, MAX1111_BATT_TEMP, SPITZ_BATTERY_TEMP);
+    else
+        max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
+}
+
+static int corgi_ssp_init(SSISlave *dev)
+{
+    CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
+
+    qdev_init_gpio_in(&dev->qdev, corgi_ssp_gpio_cs, 3);
+    s->bus[0] = ssi_create_bus(&dev->qdev, "ssi0");
+    s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
+    s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2");
+
+    return 0;
+}
+
+static void spitz_ssp_attach(PXA2xxState *cpu)
+{
+    DeviceState *mux;
+    DeviceState *dev;
+    void *bus;
+
+    mux = ssi_create_slave(cpu->ssp[CORGI_SSP_PORT - 1], "corgi-ssp");
+
+    bus = qdev_get_child_bus(mux, "ssi0");
+    ssi_create_slave(bus, "spitz-lcdtg");
+
+    bus = qdev_get_child_bus(mux, "ssi1");
+    dev = ssi_create_slave(bus, "ads7846");
+    qdev_connect_gpio_out(dev, 0,
+                          qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_TP_INT));
+
+    bus = qdev_get_child_bus(mux, "ssi2");
+    max1111 = ssi_create_slave(bus, "max1111");
+    max111x_set_input(max1111, MAX1111_BATT_VOLT, SPITZ_BATTERY_VOLT);
+    max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
+    max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
+
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_LCDCON_CS,
+                        qdev_get_gpio_in(mux, 0));
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ADS7846_CS,
+                        qdev_get_gpio_in(mux, 1));
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_MAX1111_CS,
+                        qdev_get_gpio_in(mux, 2));
+}
+
+/* CF Microdrive */
+
+static void spitz_microdrive_attach(PXA2xxState *cpu, int slot)
+{
+    PCMCIACardState *md;
+    DriveInfo *dinfo;
+
+    dinfo = drive_get(IF_IDE, 0, 0);
+    if (!dinfo || dinfo->media_cd)
+        return;
+    md = dscm1xxxx_init(dinfo);
+    pxa2xx_pcmcia_attach(cpu->pcmcia[slot], md);
+}
+
+/* Wm8750 and Max7310 on I2C */
+
+#define AKITA_MAX_ADDR 0x18
+#define SPITZ_WM_ADDRL 0x1b
+#define SPITZ_WM_ADDRH 0x1a
+
+#define SPITZ_GPIO_WM  5
+
+static void spitz_wm8750_addr(void *opaque, int line, int level)
+{
+    I2CSlave *wm = (I2CSlave *) opaque;
+    if (level)
+        i2c_set_slave_address(wm, SPITZ_WM_ADDRH);
+    else
+        i2c_set_slave_address(wm, SPITZ_WM_ADDRL);
+}
+
+static void spitz_i2c_setup(PXA2xxState *cpu)
+{
+    /* Attach the CPU on one end of our I2C bus.  */
+    i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+
+    DeviceState *wm;
+
+    /* Attach a WM8750 to the bus */
+    wm = i2c_create_slave(bus, "wm8750", 0);
+
+    spitz_wm8750_addr(wm, 0, 0);
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_WM,
+                    qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
+    /* .. and to the sound interface.  */
+    cpu->i2s->opaque = wm;
+    cpu->i2s->codec_out = wm8750_dac_dat;
+    cpu->i2s->codec_in = wm8750_adc_dat;
+    wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
+}
+
+static void spitz_akita_i2c_setup(PXA2xxState *cpu)
+{
+    /* Attach a Max7310 to Akita I2C bus.  */
+    i2c_create_slave(pxa2xx_i2c_bus(cpu->i2c[0]), "max7310",
+                     AKITA_MAX_ADDR);
+}
+
+/* Other peripherals */
+
+static void spitz_out_switch(void *opaque, int line, int level)
+{
+    switch (line) {
+    case 0:
+        zaurus_printf("Charging %s.\n", level ? "off" : "on");
+        break;
+    case 1:
+        zaurus_printf("Discharging %s.\n", level ? "on" : "off");
+        break;
+    case 2:
+        zaurus_printf("Green LED %s.\n", level ? "on" : "off");
+        break;
+    case 3:
+        zaurus_printf("Orange LED %s.\n", level ? "on" : "off");
+        break;
+    case 4:
+        spitz_bl_bit5(opaque, line, level);
+        break;
+    case 5:
+        spitz_bl_power(opaque, line, level);
+        break;
+    case 6:
+        spitz_adc_temp_on(opaque, line, level);
+        break;
+    }
+}
+
+#define SPITZ_SCP_LED_GREEN            1
+#define SPITZ_SCP_JK_B                 2
+#define SPITZ_SCP_CHRG_ON              3
+#define SPITZ_SCP_MUTE_L               4
+#define SPITZ_SCP_MUTE_R               5
+#define SPITZ_SCP_CF_POWER             6
+#define SPITZ_SCP_LED_ORANGE           7
+#define SPITZ_SCP_JK_A                 8
+#define SPITZ_SCP_ADC_TEMP_ON          9
+#define SPITZ_SCP2_IR_ON               1
+#define SPITZ_SCP2_AKIN_PULLUP         2
+#define SPITZ_SCP2_BACKLIGHT_CONT      7
+#define SPITZ_SCP2_BACKLIGHT_ON                8
+#define SPITZ_SCP2_MIC_BIAS            9
+
+static void spitz_scoop_gpio_setup(PXA2xxState *cpu,
+                DeviceState *scp0, DeviceState *scp1)
+{
+    qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, cpu, 8);
+
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_CHRG_ON, outsignals[0]);
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_JK_B, outsignals[1]);
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_GREEN, outsignals[2]);
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]);
+
+    if (scp1) {
+        qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]);
+        qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]);
+    }
+
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
+}
+
+#define SPITZ_GPIO_HSYNC               22
+#define SPITZ_GPIO_SD_DETECT           9
+#define SPITZ_GPIO_SD_WP               81
+#define SPITZ_GPIO_ON_RESET            89
+#define SPITZ_GPIO_BAT_COVER           90
+#define SPITZ_GPIO_CF1_IRQ             105
+#define SPITZ_GPIO_CF1_CD              94
+#define SPITZ_GPIO_CF2_IRQ             106
+#define SPITZ_GPIO_CF2_CD              93
+
+static int spitz_hsync;
+
+static void spitz_lcd_hsync_handler(void *opaque, int line, int level)
+{
+    PXA2xxState *cpu = (PXA2xxState *) opaque;
+    qemu_set_irq(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_HSYNC), spitz_hsync);
+    spitz_hsync ^= 1;
+}
+
+static void spitz_gpio_setup(PXA2xxState *cpu, int slots)
+{
+    qemu_irq lcd_hsync;
+    /*
+     * Bad hack: We toggle the LCD hsync GPIO on every GPIO status
+     * read to satisfy broken guests that poll-wait for hsync.
+     * Simulating a real hsync event would be less practical and
+     * wouldn't guarantee that a guest ever exits the loop.
+     */
+    spitz_hsync = 0;
+    lcd_hsync = qemu_allocate_irqs(spitz_lcd_hsync_handler, cpu, 1)[0];
+    pxa2xx_gpio_read_notifier(cpu->gpio, lcd_hsync);
+    pxa2xx_lcd_vsync_notifier(cpu->lcd, lcd_hsync);
+
+    /* MMC/SD host */
+    pxa2xx_mmci_handlers(cpu->mmc,
+                    qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_WP),
+                    qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_DETECT));
+
+    /* Battery lock always closed */
+    qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_BAT_COVER));
+
+    /* Handle reset */
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ON_RESET, cpu->reset);
+
+    /* PCMCIA signals: card's IRQ and Card-Detect */
+    if (slots >= 1)
+        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_IRQ),
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_CD));
+    if (slots >= 2)
+        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_IRQ),
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_CD));
+}
+
+/* Board init.  */
+enum spitz_model_e { spitz, akita, borzoi, terrier };
+
+#define SPITZ_RAM      0x04000000
+#define SPITZ_ROM      0x00800000
+
+static struct arm_boot_info spitz_binfo = {
+    .loader_start = PXA2XX_SDRAM_BASE,
+    .ram_size = 0x04000000,
+};
+
+static void spitz_common_init(QEMUMachineInitArgs *args,
+                              enum spitz_model_e model, int arm_id)
+{
+    PXA2xxState *mpu;
+    DeviceState *scp0, *scp1 = NULL;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    const char *cpu_model = args->cpu_model;
+
+    if (!cpu_model)
+        cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
+
+    /* Setup CPU & memory */
+    mpu = pxa270_init(address_space_mem, spitz_binfo.ram_size, cpu_model);
+
+    sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
+
+    memory_region_init_ram(rom, "spitz.rom", SPITZ_ROM);
+    vmstate_register_ram_global(rom);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(address_space_mem, 0, rom);
+
+    /* Setup peripherals */
+    spitz_keyboard_register(mpu);
+
+    spitz_ssp_attach(mpu);
+
+    scp0 = sysbus_create_simple("scoop", 0x10800000, NULL);
+    if (model != akita) {
+        scp1 = sysbus_create_simple("scoop", 0x08800040, NULL);
+    }
+
+    spitz_scoop_gpio_setup(mpu, scp0, scp1);
+
+    spitz_gpio_setup(mpu, (model == akita) ? 1 : 2);
+
+    spitz_i2c_setup(mpu);
+
+    if (model == akita)
+        spitz_akita_i2c_setup(mpu);
+
+    if (model == terrier)
+        /* A 6.0 GB microdrive is permanently sitting in CF slot 1.  */
+        spitz_microdrive_attach(mpu, 1);
+    else if (model != akita)
+        /* A 4.0 GB microdrive is permanently sitting in CF slot 0.  */
+        spitz_microdrive_attach(mpu, 0);
+
+    spitz_binfo.kernel_filename = args->kernel_filename;
+    spitz_binfo.kernel_cmdline = args->kernel_cmdline;
+    spitz_binfo.initrd_filename = args->initrd_filename;
+    spitz_binfo.board_id = arm_id;
+    arm_load_kernel(mpu->cpu, &spitz_binfo);
+    sl_bootparam_write(SL_PXA_PARAM_BASE);
+}
+
+static void spitz_init(QEMUMachineInitArgs *args)
+{
+    spitz_common_init(args, spitz, 0x2c9);
+}
+
+static void borzoi_init(QEMUMachineInitArgs *args)
+{
+    spitz_common_init(args, borzoi, 0x33f);
+}
+
+static void akita_init(QEMUMachineInitArgs *args)
+{
+    spitz_common_init(args, akita, 0x2e8);
+}
+
+static void terrier_init(QEMUMachineInitArgs *args)
+{
+    spitz_common_init(args, terrier, 0x33f);
+}
+
+static QEMUMachine akitapda_machine = {
+    .name = "akita",
+    .desc = "Akita PDA (PXA270)",
+    .init = akita_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine spitzpda_machine = {
+    .name = "spitz",
+    .desc = "Spitz PDA (PXA270)",
+    .init = spitz_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine borzoipda_machine = {
+    .name = "borzoi",
+    .desc = "Borzoi PDA (PXA270)",
+    .init = borzoi_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine terrierpda_machine = {
+    .name = "terrier",
+    .desc = "Terrier PDA (PXA270)",
+    .init = terrier_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void spitz_machine_init(void)
+{
+    qemu_register_machine(&akitapda_machine);
+    qemu_register_machine(&spitzpda_machine);
+    qemu_register_machine(&borzoipda_machine);
+    qemu_register_machine(&terrierpda_machine);
+}
+
+machine_init(spitz_machine_init);
+
+static bool is_version_0(void *opaque, int version_id)
+{
+    return version_id == 0;
+}
+
+static VMStateDescription vmstate_sl_nand_info = {
+    .name = "sl-nand",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT8(ctl, SLNANDState),
+        VMSTATE_STRUCT(ecc, SLNANDState, 0, vmstate_ecc_state, ECCState),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static Property sl_nand_properties[] = {
+    DEFINE_PROP_UINT8("manf_id", SLNANDState, manf_id, NAND_MFR_SAMSUNG),
+    DEFINE_PROP_UINT8("chip_id", SLNANDState, chip_id, 0xf1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sl_nand_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = sl_nand_init;
+    dc->vmsd = &vmstate_sl_nand_info;
+    dc->props = sl_nand_properties;
+}
+
+static const TypeInfo sl_nand_info = {
+    .name          = "sl-nand",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SLNANDState),
+    .class_init    = sl_nand_class_init,
+};
+
+static VMStateDescription vmstate_spitz_kbd = {
+    .name = "spitz-keyboard",
+    .version_id = 1,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = spitz_keyboard_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT16(sense_state, SpitzKeyboardState),
+        VMSTATE_UINT16(strobe_state, SpitzKeyboardState),
+        VMSTATE_UNUSED_TEST(is_version_0, 5),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static Property spitz_keyboard_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void spitz_keyboard_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = spitz_keyboard_init;
+    dc->vmsd = &vmstate_spitz_kbd;
+    dc->props = spitz_keyboard_properties;
+}
+
+static const TypeInfo spitz_keyboard_info = {
+    .name          = "spitz-keyboard",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SpitzKeyboardState),
+    .class_init    = spitz_keyboard_class_init,
+};
+
+static const VMStateDescription vmstate_corgi_ssp_regs = {
+    .name = "corgi-ssp",
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .fields = (VMStateField []) {
+        VMSTATE_SSI_SLAVE(ssidev, CorgiSSPState),
+        VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void corgi_ssp_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+    k->init = corgi_ssp_init;
+    k->transfer = corgi_ssp_transfer;
+    dc->vmsd = &vmstate_corgi_ssp_regs;
+}
+
+static const TypeInfo corgi_ssp_info = {
+    .name          = "corgi-ssp",
+    .parent        = TYPE_SSI_SLAVE,
+    .instance_size = sizeof(CorgiSSPState),
+    .class_init    = corgi_ssp_class_init,
+};
+
+static const VMStateDescription vmstate_spitz_lcdtg_regs = {
+    .name = "spitz-lcdtg",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_SSI_SLAVE(ssidev, SpitzLCDTG),
+        VMSTATE_UINT32(bl_intensity, SpitzLCDTG),
+        VMSTATE_UINT32(bl_power, SpitzLCDTG),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void spitz_lcdtg_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+    k->init = spitz_lcdtg_init;
+    k->transfer = spitz_lcdtg_transfer;
+    dc->vmsd = &vmstate_spitz_lcdtg_regs;
+}
+
+static const TypeInfo spitz_lcdtg_info = {
+    .name          = "spitz-lcdtg",
+    .parent        = TYPE_SSI_SLAVE,
+    .instance_size = sizeof(SpitzLCDTG),
+    .class_init    = spitz_lcdtg_class_init,
+};
+
+static void spitz_register_types(void)
+{
+    type_register_static(&corgi_ssp_info);
+    type_register_static(&spitz_lcdtg_info);
+    type_register_static(&spitz_keyboard_info);
+    type_register_static(&sl_nand_info);
+}
+
+type_init(spitz_register_types)
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
new file mode 100644 (file)
index 0000000..f4ce794
--- /dev/null
@@ -0,0 +1,1401 @@
+/*
+ * Luminary Micro Stellaris peripherals
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/ssi.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "qemu/timer.h"
+#include "hw/i2c.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "exec/address-spaces.h"
+
+#define GPIO_A 0
+#define GPIO_B 1
+#define GPIO_C 2
+#define GPIO_D 3
+#define GPIO_E 4
+#define GPIO_F 5
+#define GPIO_G 6
+
+#define BP_OLED_I2C  0x01
+#define BP_OLED_SSI  0x02
+#define BP_GAMEPAD   0x04
+
+typedef const struct {
+    const char *name;
+    uint32_t did0;
+    uint32_t did1;
+    uint32_t dc0;
+    uint32_t dc1;
+    uint32_t dc2;
+    uint32_t dc3;
+    uint32_t dc4;
+    uint32_t peripherals;
+} stellaris_board_info;
+
+/* General purpose timer module.  */
+
+typedef struct gptm_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t config;
+    uint32_t mode[2];
+    uint32_t control;
+    uint32_t state;
+    uint32_t mask;
+    uint32_t load[2];
+    uint32_t match[2];
+    uint32_t prescale[2];
+    uint32_t match_prescale[2];
+    uint32_t rtc;
+    int64_t tick[2];
+    struct gptm_state *opaque[2];
+    QEMUTimer *timer[2];
+    /* The timers have an alternate output used to trigger the ADC.  */
+    qemu_irq trigger;
+    qemu_irq irq;
+} gptm_state;
+
+static void gptm_update_irq(gptm_state *s)
+{
+    int level;
+    level = (s->state & s->mask) != 0;
+    qemu_set_irq(s->irq, level);
+}
+
+static void gptm_stop(gptm_state *s, int n)
+{
+    qemu_del_timer(s->timer[n]);
+}
+
+static void gptm_reload(gptm_state *s, int n, int reset)
+{
+    int64_t tick;
+    if (reset)
+        tick = qemu_get_clock_ns(vm_clock);
+    else
+        tick = s->tick[n];
+
+    if (s->config == 0) {
+        /* 32-bit CountDown.  */
+        uint32_t count;
+        count = s->load[0] | (s->load[1] << 16);
+        tick += (int64_t)count * system_clock_scale;
+    } else if (s->config == 1) {
+        /* 32-bit RTC.  1Hz tick.  */
+        tick += get_ticks_per_sec();
+    } else if (s->mode[n] == 0xa) {
+        /* PWM mode.  Not implemented.  */
+    } else {
+        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
+    }
+    s->tick[n] = tick;
+    qemu_mod_timer(s->timer[n], tick);
+}
+
+static void gptm_tick(void *opaque)
+{
+    gptm_state **p = (gptm_state **)opaque;
+    gptm_state *s;
+    int n;
+
+    s = *p;
+    n = p - s->opaque;
+    if (s->config == 0) {
+        s->state |= 1;
+        if ((s->control & 0x20)) {
+            /* Output trigger.  */
+           qemu_irq_pulse(s->trigger);
+        }
+        if (s->mode[0] & 1) {
+            /* One-shot.  */
+            s->control &= ~1;
+        } else {
+            /* Periodic.  */
+            gptm_reload(s, 0, 0);
+        }
+    } else if (s->config == 1) {
+        /* RTC.  */
+        uint32_t match;
+        s->rtc++;
+        match = s->match[0] | (s->match[1] << 16);
+        if (s->rtc > match)
+            s->rtc = 0;
+        if (s->rtc == 0) {
+            s->state |= 8;
+        }
+        gptm_reload(s, 0, 0);
+    } else if (s->mode[n] == 0xa) {
+        /* PWM mode.  Not implemented.  */
+    } else {
+        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
+    }
+    gptm_update_irq(s);
+}
+
+static uint64_t gptm_read(void *opaque, hwaddr offset,
+                          unsigned size)
+{
+    gptm_state *s = (gptm_state *)opaque;
+
+    switch (offset) {
+    case 0x00: /* CFG */
+        return s->config;
+    case 0x04: /* TAMR */
+        return s->mode[0];
+    case 0x08: /* TBMR */
+        return s->mode[1];
+    case 0x0c: /* CTL */
+        return s->control;
+    case 0x18: /* IMR */
+        return s->mask;
+    case 0x1c: /* RIS */
+        return s->state;
+    case 0x20: /* MIS */
+        return s->state & s->mask;
+    case 0x24: /* CR */
+        return 0;
+    case 0x28: /* TAILR */
+        return s->load[0] | ((s->config < 4) ? (s->load[1] << 16) : 0);
+    case 0x2c: /* TBILR */
+        return s->load[1];
+    case 0x30: /* TAMARCHR */
+        return s->match[0] | ((s->config < 4) ? (s->match[1] << 16) : 0);
+    case 0x34: /* TBMATCHR */
+        return s->match[1];
+    case 0x38: /* TAPR */
+        return s->prescale[0];
+    case 0x3c: /* TBPR */
+        return s->prescale[1];
+    case 0x40: /* TAPMR */
+        return s->match_prescale[0];
+    case 0x44: /* TBPMR */
+        return s->match_prescale[1];
+    case 0x48: /* TAR */
+        if (s->control == 1)
+            return s->rtc;
+    case 0x4c: /* TBR */
+        hw_error("TODO: Timer value read\n");
+    default:
+        hw_error("gptm_read: Bad offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void gptm_write(void *opaque, hwaddr offset,
+                       uint64_t value, unsigned size)
+{
+    gptm_state *s = (gptm_state *)opaque;
+    uint32_t oldval;
+
+    /* The timers should be disabled before changing the configuration.
+       We take advantage of this and defer everything until the timer
+       is enabled.  */
+    switch (offset) {
+    case 0x00: /* CFG */
+        s->config = value;
+        break;
+    case 0x04: /* TAMR */
+        s->mode[0] = value;
+        break;
+    case 0x08: /* TBMR */
+        s->mode[1] = value;
+        break;
+    case 0x0c: /* CTL */
+        oldval = s->control;
+        s->control = value;
+        /* TODO: Implement pause.  */
+        if ((oldval ^ value) & 1) {
+            if (value & 1) {
+                gptm_reload(s, 0, 1);
+            } else {
+                gptm_stop(s, 0);
+            }
+        }
+        if (((oldval ^ value) & 0x100) && s->config >= 4) {
+            if (value & 0x100) {
+                gptm_reload(s, 1, 1);
+            } else {
+                gptm_stop(s, 1);
+            }
+        }
+        break;
+    case 0x18: /* IMR */
+        s->mask = value & 0x77;
+        gptm_update_irq(s);
+        break;
+    case 0x24: /* CR */
+        s->state &= ~value;
+        break;
+    case 0x28: /* TAILR */
+        s->load[0] = value & 0xffff;
+        if (s->config < 4) {
+            s->load[1] = value >> 16;
+        }
+        break;
+    case 0x2c: /* TBILR */
+        s->load[1] = value & 0xffff;
+        break;
+    case 0x30: /* TAMARCHR */
+        s->match[0] = value & 0xffff;
+        if (s->config < 4) {
+            s->match[1] = value >> 16;
+        }
+        break;
+    case 0x34: /* TBMATCHR */
+        s->match[1] = value >> 16;
+        break;
+    case 0x38: /* TAPR */
+        s->prescale[0] = value;
+        break;
+    case 0x3c: /* TBPR */
+        s->prescale[1] = value;
+        break;
+    case 0x40: /* TAPMR */
+        s->match_prescale[0] = value;
+        break;
+    case 0x44: /* TBPMR */
+        s->match_prescale[0] = value;
+        break;
+    default:
+        hw_error("gptm_write: Bad offset 0x%x\n", (int)offset);
+    }
+    gptm_update_irq(s);
+}
+
+static const MemoryRegionOps gptm_ops = {
+    .read = gptm_read,
+    .write = gptm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_stellaris_gptm = {
+    .name = "stellaris_gptm",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(config, gptm_state),
+        VMSTATE_UINT32_ARRAY(mode, gptm_state, 2),
+        VMSTATE_UINT32(control, gptm_state),
+        VMSTATE_UINT32(state, gptm_state),
+        VMSTATE_UINT32(mask, gptm_state),
+        VMSTATE_UNUSED(8),
+        VMSTATE_UINT32_ARRAY(load, gptm_state, 2),
+        VMSTATE_UINT32_ARRAY(match, gptm_state, 2),
+        VMSTATE_UINT32_ARRAY(prescale, gptm_state, 2),
+        VMSTATE_UINT32_ARRAY(match_prescale, gptm_state, 2),
+        VMSTATE_UINT32(rtc, gptm_state),
+        VMSTATE_INT64_ARRAY(tick, gptm_state, 2),
+        VMSTATE_TIMER_ARRAY(timer, gptm_state, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int stellaris_gptm_init(SysBusDevice *dev)
+{
+    gptm_state *s = FROM_SYSBUS(gptm_state, dev);
+
+    sysbus_init_irq(dev, &s->irq);
+    qdev_init_gpio_out(&dev->qdev, &s->trigger, 1);
+
+    memory_region_init_io(&s->iomem, &gptm_ops, s,
+                          "gptm", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    s->opaque[0] = s->opaque[1] = s;
+    s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]);
+    s->timer[1] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[1]);
+    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_gptm, s);
+    return 0;
+}
+
+
+/* System controller.  */
+
+typedef struct {
+    MemoryRegion iomem;
+    uint32_t pborctl;
+    uint32_t ldopctl;
+    uint32_t int_status;
+    uint32_t int_mask;
+    uint32_t resc;
+    uint32_t rcc;
+    uint32_t rcc2;
+    uint32_t rcgc[3];
+    uint32_t scgc[3];
+    uint32_t dcgc[3];
+    uint32_t clkvclr;
+    uint32_t ldoarst;
+    uint32_t user0;
+    uint32_t user1;
+    qemu_irq irq;
+    stellaris_board_info *board;
+} ssys_state;
+
+static void ssys_update(ssys_state *s)
+{
+  qemu_set_irq(s->irq, (s->int_status & s->int_mask) != 0);
+}
+
+static uint32_t pllcfg_sandstorm[16] = {
+    0x31c0, /* 1 Mhz */
+    0x1ae0, /* 1.8432 Mhz */
+    0x18c0, /* 2 Mhz */
+    0xd573, /* 2.4576 Mhz */
+    0x37a6, /* 3.57954 Mhz */
+    0x1ae2, /* 3.6864 Mhz */
+    0x0c40, /* 4 Mhz */
+    0x98bc, /* 4.906 Mhz */
+    0x935b, /* 4.9152 Mhz */
+    0x09c0, /* 5 Mhz */
+    0x4dee, /* 5.12 Mhz */
+    0x0c41, /* 6 Mhz */
+    0x75db, /* 6.144 Mhz */
+    0x1ae6, /* 7.3728 Mhz */
+    0x0600, /* 8 Mhz */
+    0x585b /* 8.192 Mhz */
+};
+
+static uint32_t pllcfg_fury[16] = {
+    0x3200, /* 1 Mhz */
+    0x1b20, /* 1.8432 Mhz */
+    0x1900, /* 2 Mhz */
+    0xf42b, /* 2.4576 Mhz */
+    0x37e3, /* 3.57954 Mhz */
+    0x1b21, /* 3.6864 Mhz */
+    0x0c80, /* 4 Mhz */
+    0x98ee, /* 4.906 Mhz */
+    0xd5b4, /* 4.9152 Mhz */
+    0x0a00, /* 5 Mhz */
+    0x4e27, /* 5.12 Mhz */
+    0x1902, /* 6 Mhz */
+    0xec1c, /* 6.144 Mhz */
+    0x1b23, /* 7.3728 Mhz */
+    0x0640, /* 8 Mhz */
+    0xb11c /* 8.192 Mhz */
+};
+
+#define DID0_VER_MASK        0x70000000
+#define DID0_VER_0           0x00000000
+#define DID0_VER_1           0x10000000
+
+#define DID0_CLASS_MASK      0x00FF0000
+#define DID0_CLASS_SANDSTORM 0x00000000
+#define DID0_CLASS_FURY      0x00010000
+
+static int ssys_board_class(const ssys_state *s)
+{
+    uint32_t did0 = s->board->did0;
+    switch (did0 & DID0_VER_MASK) {
+    case DID0_VER_0:
+        return DID0_CLASS_SANDSTORM;
+    case DID0_VER_1:
+        switch (did0 & DID0_CLASS_MASK) {
+        case DID0_CLASS_SANDSTORM:
+        case DID0_CLASS_FURY:
+            return did0 & DID0_CLASS_MASK;
+        }
+        /* for unknown classes, fall through */
+    default:
+        hw_error("ssys_board_class: Unknown class 0x%08x\n", did0);
+    }
+}
+
+static uint64_t ssys_read(void *opaque, hwaddr offset,
+                          unsigned size)
+{
+    ssys_state *s = (ssys_state *)opaque;
+
+    switch (offset) {
+    case 0x000: /* DID0 */
+        return s->board->did0;
+    case 0x004: /* DID1 */
+        return s->board->did1;
+    case 0x008: /* DC0 */
+        return s->board->dc0;
+    case 0x010: /* DC1 */
+        return s->board->dc1;
+    case 0x014: /* DC2 */
+        return s->board->dc2;
+    case 0x018: /* DC3 */
+        return s->board->dc3;
+    case 0x01c: /* DC4 */
+        return s->board->dc4;
+    case 0x030: /* PBORCTL */
+        return s->pborctl;
+    case 0x034: /* LDOPCTL */
+        return s->ldopctl;
+    case 0x040: /* SRCR0 */
+        return 0;
+    case 0x044: /* SRCR1 */
+        return 0;
+    case 0x048: /* SRCR2 */
+        return 0;
+    case 0x050: /* RIS */
+        return s->int_status;
+    case 0x054: /* IMC */
+        return s->int_mask;
+    case 0x058: /* MISC */
+        return s->int_status & s->int_mask;
+    case 0x05c: /* RESC */
+        return s->resc;
+    case 0x060: /* RCC */
+        return s->rcc;
+    case 0x064: /* PLLCFG */
+        {
+            int xtal;
+            xtal = (s->rcc >> 6) & 0xf;
+            switch (ssys_board_class(s)) {
+            case DID0_CLASS_FURY:
+                return pllcfg_fury[xtal];
+            case DID0_CLASS_SANDSTORM:
+                return pllcfg_sandstorm[xtal];
+            default:
+                hw_error("ssys_read: Unhandled class for PLLCFG read.\n");
+                return 0;
+            }
+        }
+    case 0x070: /* RCC2 */
+        return s->rcc2;
+    case 0x100: /* RCGC0 */
+        return s->rcgc[0];
+    case 0x104: /* RCGC1 */
+        return s->rcgc[1];
+    case 0x108: /* RCGC2 */
+        return s->rcgc[2];
+    case 0x110: /* SCGC0 */
+        return s->scgc[0];
+    case 0x114: /* SCGC1 */
+        return s->scgc[1];
+    case 0x118: /* SCGC2 */
+        return s->scgc[2];
+    case 0x120: /* DCGC0 */
+        return s->dcgc[0];
+    case 0x124: /* DCGC1 */
+        return s->dcgc[1];
+    case 0x128: /* DCGC2 */
+        return s->dcgc[2];
+    case 0x150: /* CLKVCLR */
+        return s->clkvclr;
+    case 0x160: /* LDOARST */
+        return s->ldoarst;
+    case 0x1e0: /* USER0 */
+        return s->user0;
+    case 0x1e4: /* USER1 */
+        return s->user1;
+    default:
+        hw_error("ssys_read: Bad offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static bool ssys_use_rcc2(ssys_state *s)
+{
+    return (s->rcc2 >> 31) & 0x1;
+}
+
+/*
+ * Caculate the sys. clock period in ms.
+ */
+static void ssys_calculate_system_clock(ssys_state *s)
+{
+    if (ssys_use_rcc2(s)) {
+        system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
+    } else {
+        system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
+    }
+}
+
+static void ssys_write(void *opaque, hwaddr offset,
+                       uint64_t value, unsigned size)
+{
+    ssys_state *s = (ssys_state *)opaque;
+
+    switch (offset) {
+    case 0x030: /* PBORCTL */
+        s->pborctl = value & 0xffff;
+        break;
+    case 0x034: /* LDOPCTL */
+        s->ldopctl = value & 0x1f;
+        break;
+    case 0x040: /* SRCR0 */
+    case 0x044: /* SRCR1 */
+    case 0x048: /* SRCR2 */
+        fprintf(stderr, "Peripheral reset not implemented\n");
+        break;
+    case 0x054: /* IMC */
+        s->int_mask = value & 0x7f;
+        break;
+    case 0x058: /* MISC */
+        s->int_status &= ~value;
+        break;
+    case 0x05c: /* RESC */
+        s->resc = value & 0x3f;
+        break;
+    case 0x060: /* RCC */
+        if ((s->rcc & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
+            /* PLL enable.  */
+            s->int_status |= (1 << 6);
+        }
+        s->rcc = value;
+        ssys_calculate_system_clock(s);
+        break;
+    case 0x070: /* RCC2 */
+        if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
+            break;
+        }
+
+        if ((s->rcc2 & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
+            /* PLL enable.  */
+            s->int_status |= (1 << 6);
+        }
+        s->rcc2 = value;
+        ssys_calculate_system_clock(s);
+        break;
+    case 0x100: /* RCGC0 */
+        s->rcgc[0] = value;
+        break;
+    case 0x104: /* RCGC1 */
+        s->rcgc[1] = value;
+        break;
+    case 0x108: /* RCGC2 */
+        s->rcgc[2] = value;
+        break;
+    case 0x110: /* SCGC0 */
+        s->scgc[0] = value;
+        break;
+    case 0x114: /* SCGC1 */
+        s->scgc[1] = value;
+        break;
+    case 0x118: /* SCGC2 */
+        s->scgc[2] = value;
+        break;
+    case 0x120: /* DCGC0 */
+        s->dcgc[0] = value;
+        break;
+    case 0x124: /* DCGC1 */
+        s->dcgc[1] = value;
+        break;
+    case 0x128: /* DCGC2 */
+        s->dcgc[2] = value;
+        break;
+    case 0x150: /* CLKVCLR */
+        s->clkvclr = value;
+        break;
+    case 0x160: /* LDOARST */
+        s->ldoarst = value;
+        break;
+    default:
+        hw_error("ssys_write: Bad offset 0x%x\n", (int)offset);
+    }
+    ssys_update(s);
+}
+
+static const MemoryRegionOps ssys_ops = {
+    .read = ssys_read,
+    .write = ssys_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ssys_reset(void *opaque)
+{
+    ssys_state *s = (ssys_state *)opaque;
+
+    s->pborctl = 0x7ffd;
+    s->rcc = 0x078e3ac0;
+
+    if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
+        s->rcc2 = 0;
+    } else {
+        s->rcc2 = 0x07802810;
+    }
+    s->rcgc[0] = 1;
+    s->scgc[0] = 1;
+    s->dcgc[0] = 1;
+    ssys_calculate_system_clock(s);
+}
+
+static int stellaris_sys_post_load(void *opaque, int version_id)
+{
+    ssys_state *s = opaque;
+
+    ssys_calculate_system_clock(s);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_stellaris_sys = {
+    .name = "stellaris_sys",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = stellaris_sys_post_load,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(pborctl, ssys_state),
+        VMSTATE_UINT32(ldopctl, ssys_state),
+        VMSTATE_UINT32(int_mask, ssys_state),
+        VMSTATE_UINT32(int_status, ssys_state),
+        VMSTATE_UINT32(resc, ssys_state),
+        VMSTATE_UINT32(rcc, ssys_state),
+        VMSTATE_UINT32_V(rcc2, ssys_state, 2),
+        VMSTATE_UINT32_ARRAY(rcgc, ssys_state, 3),
+        VMSTATE_UINT32_ARRAY(scgc, ssys_state, 3),
+        VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
+        VMSTATE_UINT32(clkvclr, ssys_state),
+        VMSTATE_UINT32(ldoarst, ssys_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int stellaris_sys_init(uint32_t base, qemu_irq irq,
+                              stellaris_board_info * board,
+                              uint8_t *macaddr)
+{
+    ssys_state *s;
+
+    s = (ssys_state *)g_malloc0(sizeof(ssys_state));
+    s->irq = irq;
+    s->board = board;
+    /* Most devices come preprogrammed with a MAC address in the user data. */
+    s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
+    s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
+
+    memory_region_init_io(&s->iomem, &ssys_ops, s, "ssys", 0x00001000);
+    memory_region_add_subregion(get_system_memory(), base, &s->iomem);
+    ssys_reset(s);
+    vmstate_register(NULL, -1, &vmstate_stellaris_sys, s);
+    return 0;
+}
+
+
+/* I2C controller.  */
+
+typedef struct {
+    SysBusDevice busdev;
+    i2c_bus *bus;
+    qemu_irq irq;
+    MemoryRegion iomem;
+    uint32_t msa;
+    uint32_t mcs;
+    uint32_t mdr;
+    uint32_t mtpr;
+    uint32_t mimr;
+    uint32_t mris;
+    uint32_t mcr;
+} stellaris_i2c_state;
+
+#define STELLARIS_I2C_MCS_BUSY    0x01
+#define STELLARIS_I2C_MCS_ERROR   0x02
+#define STELLARIS_I2C_MCS_ADRACK  0x04
+#define STELLARIS_I2C_MCS_DATACK  0x08
+#define STELLARIS_I2C_MCS_ARBLST  0x10
+#define STELLARIS_I2C_MCS_IDLE    0x20
+#define STELLARIS_I2C_MCS_BUSBSY  0x40
+
+static uint64_t stellaris_i2c_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
+
+    switch (offset) {
+    case 0x00: /* MSA */
+        return s->msa;
+    case 0x04: /* MCS */
+        /* We don't emulate timing, so the controller is never busy.  */
+        return s->mcs | STELLARIS_I2C_MCS_IDLE;
+    case 0x08: /* MDR */
+        return s->mdr;
+    case 0x0c: /* MTPR */
+        return s->mtpr;
+    case 0x10: /* MIMR */
+        return s->mimr;
+    case 0x14: /* MRIS */
+        return s->mris;
+    case 0x18: /* MMIS */
+        return s->mris & s->mimr;
+    case 0x20: /* MCR */
+        return s->mcr;
+    default:
+        hw_error("strllaris_i2c_read: Bad offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void stellaris_i2c_update(stellaris_i2c_state *s)
+{
+    int level;
+
+    level = (s->mris & s->mimr) != 0;
+    qemu_set_irq(s->irq, level);
+}
+
+static void stellaris_i2c_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
+
+    switch (offset) {
+    case 0x00: /* MSA */
+        s->msa = value & 0xff;
+        break;
+    case 0x04: /* MCS */
+        if ((s->mcr & 0x10) == 0) {
+            /* Disabled.  Do nothing.  */
+            break;
+        }
+        /* Grab the bus if this is starting a transfer.  */
+        if ((value & 2) && (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
+            if (i2c_start_transfer(s->bus, s->msa >> 1, s->msa & 1)) {
+                s->mcs |= STELLARIS_I2C_MCS_ARBLST;
+            } else {
+                s->mcs &= ~STELLARIS_I2C_MCS_ARBLST;
+                s->mcs |= STELLARIS_I2C_MCS_BUSBSY;
+            }
+        }
+        /* If we don't have the bus then indicate an error.  */
+        if (!i2c_bus_busy(s->bus)
+                || (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
+            s->mcs |= STELLARIS_I2C_MCS_ERROR;
+            break;
+        }
+        s->mcs &= ~STELLARIS_I2C_MCS_ERROR;
+        if (value & 1) {
+            /* Transfer a byte.  */
+            /* TODO: Handle errors.  */
+            if (s->msa & 1) {
+                /* Recv */
+                s->mdr = i2c_recv(s->bus) & 0xff;
+            } else {
+                /* Send */
+                i2c_send(s->bus, s->mdr);
+            }
+            /* Raise an interrupt.  */
+            s->mris |= 1;
+        }
+        if (value & 4) {
+            /* Finish transfer.  */
+            i2c_end_transfer(s->bus);
+            s->mcs &= ~STELLARIS_I2C_MCS_BUSBSY;
+        }
+        break;
+    case 0x08: /* MDR */
+        s->mdr = value & 0xff;
+        break;
+    case 0x0c: /* MTPR */
+        s->mtpr = value & 0xff;
+        break;
+    case 0x10: /* MIMR */
+        s->mimr = 1;
+        break;
+    case 0x1c: /* MICR */
+        s->mris &= ~value;
+        break;
+    case 0x20: /* MCR */
+        if (value & 1)
+            hw_error(
+                      "stellaris_i2c_write: Loopback not implemented\n");
+        if (value & 0x20)
+            hw_error(
+                      "stellaris_i2c_write: Slave mode not implemented\n");
+        s->mcr = value & 0x31;
+        break;
+    default:
+        hw_error("stellaris_i2c_write: Bad offset 0x%x\n",
+                  (int)offset);
+    }
+    stellaris_i2c_update(s);
+}
+
+static void stellaris_i2c_reset(stellaris_i2c_state *s)
+{
+    if (s->mcs & STELLARIS_I2C_MCS_BUSBSY)
+        i2c_end_transfer(s->bus);
+
+    s->msa = 0;
+    s->mcs = 0;
+    s->mdr = 0;
+    s->mtpr = 1;
+    s->mimr = 0;
+    s->mris = 0;
+    s->mcr = 0;
+    stellaris_i2c_update(s);
+}
+
+static const MemoryRegionOps stellaris_i2c_ops = {
+    .read = stellaris_i2c_read,
+    .write = stellaris_i2c_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_stellaris_i2c = {
+    .name = "stellaris_i2c",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(msa, stellaris_i2c_state),
+        VMSTATE_UINT32(mcs, stellaris_i2c_state),
+        VMSTATE_UINT32(mdr, stellaris_i2c_state),
+        VMSTATE_UINT32(mtpr, stellaris_i2c_state),
+        VMSTATE_UINT32(mimr, stellaris_i2c_state),
+        VMSTATE_UINT32(mris, stellaris_i2c_state),
+        VMSTATE_UINT32(mcr, stellaris_i2c_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int stellaris_i2c_init(SysBusDevice * dev)
+{
+    stellaris_i2c_state *s = FROM_SYSBUS(stellaris_i2c_state, dev);
+    i2c_bus *bus;
+
+    sysbus_init_irq(dev, &s->irq);
+    bus = i2c_init_bus(&dev->qdev, "i2c");
+    s->bus = bus;
+
+    memory_region_init_io(&s->iomem, &stellaris_i2c_ops, s,
+                          "i2c", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    /* ??? For now we only implement the master interface.  */
+    stellaris_i2c_reset(s);
+    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
+    return 0;
+}
+
+/* Analogue to Digital Converter.  This is only partially implemented,
+   enough for applications that use a combined ADC and timer tick.  */
+
+#define STELLARIS_ADC_EM_CONTROLLER 0
+#define STELLARIS_ADC_EM_COMP       1
+#define STELLARIS_ADC_EM_EXTERNAL   4
+#define STELLARIS_ADC_EM_TIMER      5
+#define STELLARIS_ADC_EM_PWM0       6
+#define STELLARIS_ADC_EM_PWM1       7
+#define STELLARIS_ADC_EM_PWM2       8
+
+#define STELLARIS_ADC_FIFO_EMPTY    0x0100
+#define STELLARIS_ADC_FIFO_FULL     0x1000
+
+typedef struct
+{
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t actss;
+    uint32_t ris;
+    uint32_t im;
+    uint32_t emux;
+    uint32_t ostat;
+    uint32_t ustat;
+    uint32_t sspri;
+    uint32_t sac;
+    struct {
+        uint32_t state;
+        uint32_t data[16];
+    } fifo[4];
+    uint32_t ssmux[4];
+    uint32_t ssctl[4];
+    uint32_t noise;
+    qemu_irq irq[4];
+} stellaris_adc_state;
+
+static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
+{
+    int tail;
+
+    tail = s->fifo[n].state & 0xf;
+    if (s->fifo[n].state & STELLARIS_ADC_FIFO_EMPTY) {
+        s->ustat |= 1 << n;
+    } else {
+        s->fifo[n].state = (s->fifo[n].state & ~0xf) | ((tail + 1) & 0xf);
+        s->fifo[n].state &= ~STELLARIS_ADC_FIFO_FULL;
+        if (tail + 1 == ((s->fifo[n].state >> 4) & 0xf))
+            s->fifo[n].state |= STELLARIS_ADC_FIFO_EMPTY;
+    }
+    return s->fifo[n].data[tail];
+}
+
+static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
+                                     uint32_t value)
+{
+    int head;
+
+    /* TODO: Real hardware has limited size FIFOs.  We have a full 16 entry 
+       FIFO fir each sequencer.  */
+    head = (s->fifo[n].state >> 4) & 0xf;
+    if (s->fifo[n].state & STELLARIS_ADC_FIFO_FULL) {
+        s->ostat |= 1 << n;
+        return;
+    }
+    s->fifo[n].data[head] = value;
+    head = (head + 1) & 0xf;
+    s->fifo[n].state &= ~STELLARIS_ADC_FIFO_EMPTY;
+    s->fifo[n].state = (s->fifo[n].state & ~0xf0) | (head << 4);
+    if ((s->fifo[n].state & 0xf) == head)
+        s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;
+}
+
+static void stellaris_adc_update(stellaris_adc_state *s)
+{
+    int level;
+    int n;
+
+    for (n = 0; n < 4; n++) {
+        level = (s->ris & s->im & (1 << n)) != 0;
+        qemu_set_irq(s->irq[n], level);
+    }
+}
+
+static void stellaris_adc_trigger(void *opaque, int irq, int level)
+{
+    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
+    int n;
+
+    for (n = 0; n < 4; n++) {
+        if ((s->actss & (1 << n)) == 0) {
+            continue;
+        }
+
+        if (((s->emux >> (n * 4)) & 0xff) != 5) {
+            continue;
+        }
+
+        /* Some applications use the ADC as a random number source, so introduce
+           some variation into the signal.  */
+        s->noise = s->noise * 314159 + 1;
+        /* ??? actual inputs not implemented.  Return an arbitrary value.  */
+        stellaris_adc_fifo_write(s, n, 0x200 + ((s->noise >> 16) & 7));
+        s->ris |= (1 << n);
+        stellaris_adc_update(s);
+    }
+}
+
+static void stellaris_adc_reset(stellaris_adc_state *s)
+{
+    int n;
+
+    for (n = 0; n < 4; n++) {
+        s->ssmux[n] = 0;
+        s->ssctl[n] = 0;
+        s->fifo[n].state = STELLARIS_ADC_FIFO_EMPTY;
+    }
+}
+
+static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
+
+    /* TODO: Implement this.  */
+    if (offset >= 0x40 && offset < 0xc0) {
+        int n;
+        n = (offset - 0x40) >> 5;
+        switch (offset & 0x1f) {
+        case 0x00: /* SSMUX */
+            return s->ssmux[n];
+        case 0x04: /* SSCTL */
+            return s->ssctl[n];
+        case 0x08: /* SSFIFO */
+            return stellaris_adc_fifo_read(s, n);
+        case 0x0c: /* SSFSTAT */
+            return s->fifo[n].state;
+        default:
+            break;
+        }
+    }
+    switch (offset) {
+    case 0x00: /* ACTSS */
+        return s->actss;
+    case 0x04: /* RIS */
+        return s->ris;
+    case 0x08: /* IM */
+        return s->im;
+    case 0x0c: /* ISC */
+        return s->ris & s->im;
+    case 0x10: /* OSTAT */
+        return s->ostat;
+    case 0x14: /* EMUX */
+        return s->emux;
+    case 0x18: /* USTAT */
+        return s->ustat;
+    case 0x20: /* SSPRI */
+        return s->sspri;
+    case 0x30: /* SAC */
+        return s->sac;
+    default:
+        hw_error("strllaris_adc_read: Bad offset 0x%x\n",
+                  (int)offset);
+        return 0;
+    }
+}
+
+static void stellaris_adc_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
+
+    /* TODO: Implement this.  */
+    if (offset >= 0x40 && offset < 0xc0) {
+        int n;
+        n = (offset - 0x40) >> 5;
+        switch (offset & 0x1f) {
+        case 0x00: /* SSMUX */
+            s->ssmux[n] = value & 0x33333333;
+            return;
+        case 0x04: /* SSCTL */
+            if (value != 6) {
+                hw_error("ADC: Unimplemented sequence %" PRIx64 "\n",
+                          value);
+            }
+            s->ssctl[n] = value;
+            return;
+        default:
+            break;
+        }
+    }
+    switch (offset) {
+    case 0x00: /* ACTSS */
+        s->actss = value & 0xf;
+        break;
+    case 0x08: /* IM */
+        s->im = value;
+        break;
+    case 0x0c: /* ISC */
+        s->ris &= ~value;
+        break;
+    case 0x10: /* OSTAT */
+        s->ostat &= ~value;
+        break;
+    case 0x14: /* EMUX */
+        s->emux = value;
+        break;
+    case 0x18: /* USTAT */
+        s->ustat &= ~value;
+        break;
+    case 0x20: /* SSPRI */
+        s->sspri = value;
+        break;
+    case 0x28: /* PSSI */
+        hw_error("Not implemented:  ADC sample initiate\n");
+        break;
+    case 0x30: /* SAC */
+        s->sac = value;
+        break;
+    default:
+        hw_error("stellaris_adc_write: Bad offset 0x%x\n", (int)offset);
+    }
+    stellaris_adc_update(s);
+}
+
+static const MemoryRegionOps stellaris_adc_ops = {
+    .read = stellaris_adc_read,
+    .write = stellaris_adc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_stellaris_adc = {
+    .name = "stellaris_adc",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(actss, stellaris_adc_state),
+        VMSTATE_UINT32(ris, stellaris_adc_state),
+        VMSTATE_UINT32(im, stellaris_adc_state),
+        VMSTATE_UINT32(emux, stellaris_adc_state),
+        VMSTATE_UINT32(ostat, stellaris_adc_state),
+        VMSTATE_UINT32(ustat, stellaris_adc_state),
+        VMSTATE_UINT32(sspri, stellaris_adc_state),
+        VMSTATE_UINT32(sac, stellaris_adc_state),
+        VMSTATE_UINT32(fifo[0].state, stellaris_adc_state),
+        VMSTATE_UINT32_ARRAY(fifo[0].data, stellaris_adc_state, 16),
+        VMSTATE_UINT32(ssmux[0], stellaris_adc_state),
+        VMSTATE_UINT32(ssctl[0], stellaris_adc_state),
+        VMSTATE_UINT32(fifo[1].state, stellaris_adc_state),
+        VMSTATE_UINT32_ARRAY(fifo[1].data, stellaris_adc_state, 16),
+        VMSTATE_UINT32(ssmux[1], stellaris_adc_state),
+        VMSTATE_UINT32(ssctl[1], stellaris_adc_state),
+        VMSTATE_UINT32(fifo[2].state, stellaris_adc_state),
+        VMSTATE_UINT32_ARRAY(fifo[2].data, stellaris_adc_state, 16),
+        VMSTATE_UINT32(ssmux[2], stellaris_adc_state),
+        VMSTATE_UINT32(ssctl[2], stellaris_adc_state),
+        VMSTATE_UINT32(fifo[3].state, stellaris_adc_state),
+        VMSTATE_UINT32_ARRAY(fifo[3].data, stellaris_adc_state, 16),
+        VMSTATE_UINT32(ssmux[3], stellaris_adc_state),
+        VMSTATE_UINT32(ssctl[3], stellaris_adc_state),
+        VMSTATE_UINT32(noise, stellaris_adc_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int stellaris_adc_init(SysBusDevice *dev)
+{
+    stellaris_adc_state *s = FROM_SYSBUS(stellaris_adc_state, dev);
+    int n;
+
+    for (n = 0; n < 4; n++) {
+        sysbus_init_irq(dev, &s->irq[n]);
+    }
+
+    memory_region_init_io(&s->iomem, &stellaris_adc_ops, s,
+                          "adc", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    stellaris_adc_reset(s);
+    qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
+    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
+    return 0;
+}
+
+/* Board init.  */
+static stellaris_board_info stellaris_boards[] = {
+  { "LM3S811EVB",
+    0,
+    0x0032000e,
+    0x001f001f, /* dc0 */
+    0x001132bf,
+    0x01071013,
+    0x3f0f01ff,
+    0x0000001f,
+    BP_OLED_I2C
+  },
+  { "LM3S6965EVB",
+    0x10010002,
+    0x1073402e,
+    0x00ff007f, /* dc0 */
+    0x001133ff,
+    0x030f5317,
+    0x0f0f87ff,
+    0x5000007f,
+    BP_OLED_SSI | BP_GAMEPAD
+  }
+};
+
+static void stellaris_init(const char *kernel_filename, const char *cpu_model,
+                           stellaris_board_info *board)
+{
+    static const int uart_irq[] = {5, 6, 33, 34};
+    static const int timer_irq[] = {19, 21, 23, 35};
+    static const uint32_t gpio_addr[7] =
+      { 0x40004000, 0x40005000, 0x40006000, 0x40007000,
+        0x40024000, 0x40025000, 0x40026000};
+    static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
+
+    MemoryRegion *address_space_mem = get_system_memory();
+    qemu_irq *pic;
+    DeviceState *gpio_dev[7];
+    qemu_irq gpio_in[7][8];
+    qemu_irq gpio_out[7][8];
+    qemu_irq adc;
+    int sram_size;
+    int flash_size;
+    i2c_bus *i2c;
+    DeviceState *dev;
+    int i;
+    int j;
+
+    flash_size = ((board->dc0 & 0xffff) + 1) << 1;
+    sram_size = (board->dc0 >> 18) + 1;
+    pic = armv7m_init(address_space_mem,
+                      flash_size, sram_size, kernel_filename, cpu_model);
+
+    if (board->dc1 & (1 << 16)) {
+        dev = sysbus_create_varargs("stellaris-adc", 0x40038000,
+                                    pic[14], pic[15], pic[16], pic[17], NULL);
+        adc = qdev_get_gpio_in(dev, 0);
+    } else {
+        adc = NULL;
+    }
+    for (i = 0; i < 4; i++) {
+        if (board->dc2 & (0x10000 << i)) {
+            dev = sysbus_create_simple("stellaris-gptm",
+                                       0x40030000 + i * 0x1000,
+                                       pic[timer_irq[i]]);
+            /* TODO: This is incorrect, but we get away with it because
+               the ADC output is only ever pulsed.  */
+            qdev_connect_gpio_out(dev, 0, adc);
+        }
+    }
+
+    stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr.a);
+
+    for (i = 0; i < 7; i++) {
+        if (board->dc4 & (1 << i)) {
+            gpio_dev[i] = sysbus_create_simple("pl061_luminary", gpio_addr[i],
+                                               pic[gpio_irq[i]]);
+            for (j = 0; j < 8; j++) {
+                gpio_in[i][j] = qdev_get_gpio_in(gpio_dev[i], j);
+                gpio_out[i][j] = NULL;
+            }
+        }
+    }
+
+    if (board->dc2 & (1 << 12)) {
+        dev = sysbus_create_simple("stellaris-i2c", 0x40020000, pic[8]);
+        i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
+        if (board->peripherals & BP_OLED_I2C) {
+            i2c_create_slave(i2c, "ssd0303", 0x3d);
+        }
+    }
+
+    for (i = 0; i < 4; i++) {
+        if (board->dc2 & (1 << i)) {
+            sysbus_create_simple("pl011_luminary", 0x4000c000 + i * 0x1000,
+                                 pic[uart_irq[i]]);
+        }
+    }
+    if (board->dc2 & (1 << 4)) {
+        dev = sysbus_create_simple("pl022", 0x40008000, pic[7]);
+        if (board->peripherals & BP_OLED_SSI) {
+            void *bus;
+            DeviceState *sddev;
+            DeviceState *ssddev;
+
+            /* Some boards have both an OLED controller and SD card connected to
+             * the same SSI port, with the SD card chip select connected to a
+             * GPIO pin.  Technically the OLED chip select is connected to the
+             * SSI Fss pin.  We do not bother emulating that as both devices
+             * should never be selected simultaneously, and our OLED controller
+             * ignores stray 0xff commands that occur when deselecting the SD
+             * card.
+             */
+            bus = qdev_get_child_bus(dev, "ssi");
+
+            sddev = ssi_create_slave(bus, "ssi-sd");
+            ssddev = ssi_create_slave(bus, "ssd0323");
+            gpio_out[GPIO_D][0] = qemu_irq_split(qdev_get_gpio_in(sddev, 0),
+                                                 qdev_get_gpio_in(ssddev, 0));
+            gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 1);
+
+            /* Make sure the select pin is high.  */
+            qemu_irq_raise(gpio_out[GPIO_D][0]);
+        }
+    }
+    if (board->dc4 & (1 << 28)) {
+        DeviceState *enet;
+
+        qemu_check_nic_model(&nd_table[0], "stellaris");
+
+        enet = qdev_create(NULL, "stellaris_enet");
+        qdev_set_nic_properties(enet, &nd_table[0]);
+        qdev_init_nofail(enet);
+        sysbus_mmio_map(SYS_BUS_DEVICE(enet), 0, 0x40048000);
+        sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, pic[42]);
+    }
+    if (board->peripherals & BP_GAMEPAD) {
+        qemu_irq gpad_irq[5];
+        static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };
+
+        gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */
+        gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */
+        gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */
+        gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */
+        gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */
+
+        stellaris_gamepad_init(5, gpad_irq, gpad_keycode);
+    }
+    for (i = 0; i < 7; i++) {
+        if (board->dc4 & (1 << i)) {
+            for (j = 0; j < 8; j++) {
+                if (gpio_out[i][j]) {
+                    qdev_connect_gpio_out(gpio_dev[i], j, gpio_out[i][j]);
+                }
+            }
+        }
+    }
+}
+
+/* FIXME: Figure out how to generate these from stellaris_boards.  */
+static void lm3s811evb_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]);
+}
+
+static void lm3s6965evb_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]);
+}
+
+static QEMUMachine lm3s811evb_machine = {
+    .name = "lm3s811evb",
+    .desc = "Stellaris LM3S811EVB",
+    .init = lm3s811evb_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine lm3s6965evb_machine = {
+    .name = "lm3s6965evb",
+    .desc = "Stellaris LM3S6965EVB",
+    .init = lm3s6965evb_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void stellaris_machine_init(void)
+{
+    qemu_register_machine(&lm3s811evb_machine);
+    qemu_register_machine(&lm3s6965evb_machine);
+}
+
+machine_init(stellaris_machine_init);
+
+static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = stellaris_i2c_init;
+}
+
+static const TypeInfo stellaris_i2c_info = {
+    .name          = "stellaris-i2c",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(stellaris_i2c_state),
+    .class_init    = stellaris_i2c_class_init,
+};
+
+static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = stellaris_gptm_init;
+}
+
+static const TypeInfo stellaris_gptm_info = {
+    .name          = "stellaris-gptm",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(gptm_state),
+    .class_init    = stellaris_gptm_class_init,
+};
+
+static void stellaris_adc_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = stellaris_adc_init;
+}
+
+static const TypeInfo stellaris_adc_info = {
+    .name          = "stellaris-adc",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(stellaris_adc_state),
+    .class_init    = stellaris_adc_class_init,
+};
+
+static void stellaris_register_types(void)
+{
+    type_register_static(&stellaris_i2c_info);
+    type_register_static(&stellaris_gptm_info);
+    type_register_static(&stellaris_adc_info);
+}
+
+type_init(stellaris_register_types)
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
new file mode 100644 (file)
index 0000000..747888c
--- /dev/null
@@ -0,0 +1,302 @@
+/* vim:set shiftwidth=4 ts=4 et: */
+/*
+ * PXA255 Sharp Zaurus SL-6000 PDA platform
+ *
+ * Copyright (c) 2008 Dmitry Baryshkov
+ *
+ * Code based on spitz platform by Andrzej Zaborowski <balrog@zabor.org>
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/sharpsl.h"
+#include "hw/pcmcia.h"
+#include "block/block.h"
+#include "hw/boards.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
+#include "sysemu/blockdev.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+#define TOSA_RAM    0x04000000
+#define TOSA_ROM       0x00800000
+
+#define TOSA_GPIO_USB_IN               (5)
+#define TOSA_GPIO_nSD_DETECT   (9)
+#define TOSA_GPIO_ON_RESET             (19)
+#define TOSA_GPIO_CF_IRQ               (21)    /* CF slot0 Ready */
+#define TOSA_GPIO_CF_CD                        (13)
+#define TOSA_GPIO_TC6393XB_INT  (15)
+#define TOSA_GPIO_JC_CF_IRQ            (36)    /* CF slot1 Ready */
+
+#define TOSA_SCOOP_GPIO_BASE   1
+#define TOSA_GPIO_IR_POWERDWN  (TOSA_SCOOP_GPIO_BASE + 2)
+#define TOSA_GPIO_SD_WP                        (TOSA_SCOOP_GPIO_BASE + 3)
+#define TOSA_GPIO_PWR_ON               (TOSA_SCOOP_GPIO_BASE + 4)
+
+#define TOSA_SCOOP_JC_GPIO_BASE                1
+#define TOSA_GPIO_BT_LED               (TOSA_SCOOP_JC_GPIO_BASE + 0)
+#define TOSA_GPIO_NOTE_LED             (TOSA_SCOOP_JC_GPIO_BASE + 1)
+#define TOSA_GPIO_CHRG_ERR_LED         (TOSA_SCOOP_JC_GPIO_BASE + 2)
+#define TOSA_GPIO_TC6393XB_L3V_ON      (TOSA_SCOOP_JC_GPIO_BASE + 5)
+#define TOSA_GPIO_WLAN_LED             (TOSA_SCOOP_JC_GPIO_BASE + 7)
+
+#define        DAC_BASE        0x4e
+#define DAC_CH1                0
+#define DAC_CH2                1
+
+static void tosa_microdrive_attach(PXA2xxState *cpu)
+{
+    PCMCIACardState *md;
+    DriveInfo *dinfo;
+
+    dinfo = drive_get(IF_IDE, 0, 0);
+    if (!dinfo || dinfo->media_cd)
+        return;
+    md = dscm1xxxx_init(dinfo);
+    pxa2xx_pcmcia_attach(cpu->pcmcia[0], md);
+}
+
+static void tosa_out_switch(void *opaque, int line, int level)
+{
+    switch (line) {
+        case 0:
+            fprintf(stderr, "blue LED %s.\n", level ? "on" : "off");
+            break;
+        case 1:
+            fprintf(stderr, "green LED %s.\n", level ? "on" : "off");
+            break;
+        case 2:
+            fprintf(stderr, "amber LED %s.\n", level ? "on" : "off");
+            break;
+        case 3:
+            fprintf(stderr, "wlan LED %s.\n", level ? "on" : "off");
+            break;
+        default:
+            fprintf(stderr, "Uhandled out event: %d = %d\n", line, level);
+            break;
+    }
+}
+
+
+static void tosa_gpio_setup(PXA2xxState *cpu,
+                DeviceState *scp0,
+                DeviceState *scp1,
+                TC6393xbState *tmio)
+{
+    qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4);
+    /* MMC/SD host */
+    pxa2xx_mmci_handlers(cpu->mmc,
+                    qdev_get_gpio_in(scp0, TOSA_GPIO_SD_WP),
+                    qemu_irq_invert(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_nSD_DETECT)));
+
+    /* Handle reset */
+    qdev_connect_gpio_out(cpu->gpio, TOSA_GPIO_ON_RESET, cpu->reset);
+
+    /* PCMCIA signals: card's IRQ and Card-Detect */
+    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
+                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_IRQ),
+                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_CD));
+
+    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
+                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_JC_CF_IRQ),
+                        NULL);
+
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
+
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio));
+
+    /* UDC Vbus */
+    qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_USB_IN));
+}
+
+static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value)
+{
+    fprintf(stderr, "TG: %d %02x\n", value >> 5, value & 0x1f);
+    return 0;
+}
+
+static int tosa_ssp_init(SSISlave *dev)
+{
+    /* Nothing to do.  */
+    return 0;
+}
+
+typedef struct {
+    I2CSlave i2c;
+    int len;
+    char buf[3];
+} TosaDACState;
+
+static int tosa_dac_send(I2CSlave *i2c, uint8_t data)
+{
+    TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c);
+    s->buf[s->len] = data;
+    if (s->len ++ > 2) {
+#ifdef VERBOSE
+        fprintf(stderr, "%s: message too long (%i bytes)\n", __FUNCTION__, s->len);
+#endif
+        return 1;
+    }
+
+    if (s->len == 2) {
+        fprintf(stderr, "dac: channel %d value 0x%02x\n",
+                s->buf[0], s->buf[1]);
+    }
+
+    return 0;
+}
+
+static void tosa_dac_event(I2CSlave *i2c, enum i2c_event event)
+{
+    TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c);
+    s->len = 0;
+    switch (event) {
+    case I2C_START_SEND:
+        break;
+    case I2C_START_RECV:
+        printf("%s: recv not supported!!!\n", __FUNCTION__);
+        break;
+    case I2C_FINISH:
+#ifdef VERBOSE
+        if (s->len < 2)
+            printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
+        if (s->len > 2)
+            printf("%s: message too long\n", __FUNCTION__);
+#endif
+        break;
+    default:
+        break;
+    }
+}
+
+static int tosa_dac_recv(I2CSlave *s)
+{
+    printf("%s: recv not supported!!!\n", __FUNCTION__);
+    return -1;
+}
+
+static int tosa_dac_init(I2CSlave *i2c)
+{
+    /* Nothing to do.  */
+    return 0;
+}
+
+static void tosa_tg_init(PXA2xxState *cpu)
+{
+    i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+    i2c_create_slave(bus, "tosa_dac", DAC_BASE);
+    ssi_create_slave(cpu->ssp[1], "tosa-ssp");
+}
+
+
+static struct arm_boot_info tosa_binfo = {
+    .loader_start = PXA2XX_SDRAM_BASE,
+    .ram_size = 0x04000000,
+};
+
+static void tosa_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    PXA2xxState *mpu;
+    TC6393xbState *tmio;
+    DeviceState *scp0, *scp1;
+
+    if (!cpu_model)
+        cpu_model = "pxa255";
+
+    mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
+
+    memory_region_init_ram(rom, "tosa.rom", TOSA_ROM);
+    vmstate_register_ram_global(rom);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(address_space_mem, 0, rom);
+
+    tmio = tc6393xb_init(address_space_mem, 0x10000000,
+            qdev_get_gpio_in(mpu->gpio, TOSA_GPIO_TC6393XB_INT));
+
+    scp0 = sysbus_create_simple("scoop", 0x08800000, NULL);
+    scp1 = sysbus_create_simple("scoop", 0x14800040, NULL);
+
+    tosa_gpio_setup(mpu, scp0, scp1, tmio);
+
+    tosa_microdrive_attach(mpu);
+
+    tosa_tg_init(mpu);
+
+    tosa_binfo.kernel_filename = kernel_filename;
+    tosa_binfo.kernel_cmdline = kernel_cmdline;
+    tosa_binfo.initrd_filename = initrd_filename;
+    tosa_binfo.board_id = 0x208;
+    arm_load_kernel(mpu->cpu, &tosa_binfo);
+    sl_bootparam_write(SL_PXA_PARAM_BASE);
+}
+
+static QEMUMachine tosapda_machine = {
+    .name = "tosa",
+    .desc = "Tosa PDA (PXA255)",
+    .init = tosa_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void tosapda_machine_init(void)
+{
+    qemu_register_machine(&tosapda_machine);
+}
+
+machine_init(tosapda_machine_init);
+
+static void tosa_dac_class_init(ObjectClass *klass, void *data)
+{
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+    k->init = tosa_dac_init;
+    k->event = tosa_dac_event;
+    k->recv = tosa_dac_recv;
+    k->send = tosa_dac_send;
+}
+
+static const TypeInfo tosa_dac_info = {
+    .name          = "tosa_dac",
+    .parent        = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(TosaDACState),
+    .class_init    = tosa_dac_class_init,
+};
+
+static void tosa_ssp_class_init(ObjectClass *klass, void *data)
+{
+    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+    k->init = tosa_ssp_init;
+    k->transfer = tosa_ssp_tansfer;
+}
+
+static const TypeInfo tosa_ssp_info = {
+    .name          = "tosa-ssp",
+    .parent        = TYPE_SSI_SLAVE,
+    .instance_size = sizeof(SSISlave),
+    .class_init    = tosa_ssp_class_init,
+};
+
+static void tosa_register_types(void)
+{
+    type_register_static(&tosa_dac_info);
+    type_register_static(&tosa_ssp_info);
+}
+
+type_init(tosa_register_types)
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
new file mode 100644 (file)
index 0000000..baaa265
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * ARM Versatile Platform/Application Baseboard System emulation.
+ *
+ * Copyright (c) 2005-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/pci/pci.h"
+#include "hw/i2c.h"
+#include "hw/boards.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+#include "hw/flash.h"
+
+#define VERSATILE_FLASH_ADDR 0x34000000
+#define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
+#define VERSATILE_FLASH_SECT_SIZE (256 * 1024)
+
+/* Primary interrupt controller.  */
+
+typedef struct vpb_sic_state
+{
+  SysBusDevice busdev;
+  MemoryRegion iomem;
+  uint32_t level;
+  uint32_t mask;
+  uint32_t pic_enable;
+  qemu_irq parent[32];
+  int irq;
+} vpb_sic_state;
+
+static const VMStateDescription vmstate_vpb_sic = {
+    .name = "versatilepb_sic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(level, vpb_sic_state),
+        VMSTATE_UINT32(mask, vpb_sic_state),
+        VMSTATE_UINT32(pic_enable, vpb_sic_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void vpb_sic_update(vpb_sic_state *s)
+{
+    uint32_t flags;
+
+    flags = s->level & s->mask;
+    qemu_set_irq(s->parent[s->irq], flags != 0);
+}
+
+static void vpb_sic_update_pic(vpb_sic_state *s)
+{
+    int i;
+    uint32_t mask;
+
+    for (i = 21; i <= 30; i++) {
+        mask = 1u << i;
+        if (!(s->pic_enable & mask))
+            continue;
+        qemu_set_irq(s->parent[i], (s->level & mask) != 0);
+    }
+}
+
+static void vpb_sic_set_irq(void *opaque, int irq, int level)
+{
+    vpb_sic_state *s = (vpb_sic_state *)opaque;
+    if (level)
+        s->level |= 1u << irq;
+    else
+        s->level &= ~(1u << irq);
+    if (s->pic_enable & (1u << irq))
+        qemu_set_irq(s->parent[irq], level);
+    vpb_sic_update(s);
+}
+
+static uint64_t vpb_sic_read(void *opaque, hwaddr offset,
+                             unsigned size)
+{
+    vpb_sic_state *s = (vpb_sic_state *)opaque;
+
+    switch (offset >> 2) {
+    case 0: /* STATUS */
+        return s->level & s->mask;
+    case 1: /* RAWSTAT */
+        return s->level;
+    case 2: /* ENABLE */
+        return s->mask;
+    case 4: /* SOFTINT */
+        return s->level & 1;
+    case 8: /* PICENABLE */
+        return s->pic_enable;
+    default:
+        printf ("vpb_sic_read: Bad register offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void vpb_sic_write(void *opaque, hwaddr offset,
+                          uint64_t value, unsigned size)
+{
+    vpb_sic_state *s = (vpb_sic_state *)opaque;
+
+    switch (offset >> 2) {
+    case 2: /* ENSET */
+        s->mask |= value;
+        break;
+    case 3: /* ENCLR */
+        s->mask &= ~value;
+        break;
+    case 4: /* SOFTINTSET */
+        if (value)
+            s->mask |= 1;
+        break;
+    case 5: /* SOFTINTCLR */
+        if (value)
+            s->mask &= ~1u;
+        break;
+    case 8: /* PICENSET */
+        s->pic_enable |= (value & 0x7fe00000);
+        vpb_sic_update_pic(s);
+        break;
+    case 9: /* PICENCLR */
+        s->pic_enable &= ~value;
+        vpb_sic_update_pic(s);
+        break;
+    default:
+        printf ("vpb_sic_write: Bad register offset 0x%x\n", (int)offset);
+        return;
+    }
+    vpb_sic_update(s);
+}
+
+static const MemoryRegionOps vpb_sic_ops = {
+    .read = vpb_sic_read,
+    .write = vpb_sic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int vpb_sic_init(SysBusDevice *dev)
+{
+    vpb_sic_state *s = FROM_SYSBUS(vpb_sic_state, dev);
+    int i;
+
+    qdev_init_gpio_in(&dev->qdev, vpb_sic_set_irq, 32);
+    for (i = 0; i < 32; i++) {
+        sysbus_init_irq(dev, &s->parent[i]);
+    }
+    s->irq = 31;
+    memory_region_init_io(&s->iomem, &vpb_sic_ops, s, "vpb-sic", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+/* Board init.  */
+
+/* The AB and PB boards both use the same core, just with different
+   peripherals and expansion busses.  For now we emulate a subset of the
+   PB peripherals and just change the board ID.  */
+
+static struct arm_boot_info versatile_binfo;
+
+static void versatile_init(QEMUMachineInitArgs *args, int board_id)
+{
+    ARMCPU *cpu;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    qemu_irq *cpu_pic;
+    qemu_irq pic[32];
+    qemu_irq sic[32];
+    DeviceState *dev, *sysctl;
+    SysBusDevice *busdev;
+    DeviceState *pl041;
+    PCIBus *pci_bus;
+    NICInfo *nd;
+    i2c_bus *i2c;
+    int n;
+    int done_smc = 0;
+    DriveInfo *dinfo;
+
+    if (!args->cpu_model) {
+        args->cpu_model = "arm926";
+    }
+    cpu = cpu_arm_init(args->cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    memory_region_init_ram(ram, "versatile.ram", args->ram_size);
+    vmstate_register_ram_global(ram);
+    /* ??? RAM should repeat to fill physical memory space.  */
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, ram);
+
+    sysctl = qdev_create(NULL, "realview_sysctl");
+    qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
+    qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000);
+    qdev_init_nofail(sysctl);
+    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
+
+    cpu_pic = arm_pic_init_cpu(cpu);
+    dev = sysbus_create_varargs("pl190", 0x10140000,
+                                cpu_pic[ARM_PIC_CPU_IRQ],
+                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+    for (n = 0; n < 32; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+    dev = sysbus_create_simple("versatilepb_sic", 0x10003000, NULL);
+    for (n = 0; n < 32; n++) {
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), n, pic[n]);
+        sic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]);
+    sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]);
+
+    dev = qdev_create(NULL, "versatile_pci");
+    busdev = SYS_BUS_DEVICE(dev);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(busdev, 0, 0x41000000); /* PCI self-config */
+    sysbus_mmio_map(busdev, 1, 0x42000000); /* PCI config */
+    sysbus_connect_irq(busdev, 0, sic[27]);
+    sysbus_connect_irq(busdev, 1, sic[28]);
+    sysbus_connect_irq(busdev, 2, sic[29]);
+    sysbus_connect_irq(busdev, 3, sic[30]);
+    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
+
+    /* The Versatile PCI bridge does not provide access to PCI IO space,
+       so many of the qemu PCI devices are not useable.  */
+    for(n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+
+        if (!done_smc && (!nd->model || strcmp(nd->model, "smc91c111") == 0)) {
+            smc91c111_init(nd, 0x10010000, sic[25]);
+            done_smc = 1;
+        } else {
+            pci_nic_init_nofail(nd, "rtl8139", NULL);
+        }
+    }
+    if (usb_enabled(false)) {
+        pci_create_simple(pci_bus, -1, "pci-ohci");
+    }
+    n = drive_get_max_bus(IF_SCSI);
+    while (n >= 0) {
+        pci_create_simple(pci_bus, -1, "lsi53c895a");
+        n--;
+    }
+
+    sysbus_create_simple("pl011", 0x101f1000, pic[12]);
+    sysbus_create_simple("pl011", 0x101f2000, pic[13]);
+    sysbus_create_simple("pl011", 0x101f3000, pic[14]);
+    sysbus_create_simple("pl011", 0x10009000, sic[6]);
+
+    sysbus_create_simple("pl080", 0x10130000, pic[17]);
+    sysbus_create_simple("sp804", 0x101e2000, pic[4]);
+    sysbus_create_simple("sp804", 0x101e3000, pic[5]);
+
+    sysbus_create_simple("pl061", 0x101e4000, pic[6]);
+    sysbus_create_simple("pl061", 0x101e5000, pic[7]);
+    sysbus_create_simple("pl061", 0x101e6000, pic[8]);
+    sysbus_create_simple("pl061", 0x101e7000, pic[9]);
+
+    /* The versatile/PB actually has a modified Color LCD controller
+       that includes hardware cursor support from the PL111.  */
+    dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);
+    /* Wire up the mux control signals from the SYS_CLCD register */
+    qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
+
+    sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
+    sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
+
+    /* Add PL031 Real Time Clock. */
+    sysbus_create_simple("pl031", 0x101e8000, pic[10]);
+
+    dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
+    i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
+    i2c_create_slave(i2c, "ds1338", 0x68);
+
+    /* Add PL041 AACI Interface to the LM4549 codec */
+    pl041 = qdev_create(NULL, "pl041");
+    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
+    qdev_init_nofail(pl041);
+    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, sic[24]);
+
+    /* Memory map for Versatile/PB:  */
+    /* 0x10000000 System registers.  */
+    /* 0x10001000 PCI controller config registers.  */
+    /* 0x10002000 Serial bus interface.  */
+    /*  0x10003000 Secondary interrupt controller.  */
+    /* 0x10004000 AACI (audio).  */
+    /*  0x10005000 MMCI0.  */
+    /*  0x10006000 KMI0 (keyboard).  */
+    /*  0x10007000 KMI1 (mouse).  */
+    /* 0x10008000 Character LCD Interface.  */
+    /*  0x10009000 UART3.  */
+    /* 0x1000a000 Smart card 1.  */
+    /*  0x1000b000 MMCI1.  */
+    /*  0x10010000 Ethernet.  */
+    /* 0x10020000 USB.  */
+    /* 0x10100000 SSMC.  */
+    /* 0x10110000 MPMC.  */
+    /*  0x10120000 CLCD Controller.  */
+    /*  0x10130000 DMA Controller.  */
+    /*  0x10140000 Vectored interrupt controller.  */
+    /* 0x101d0000 AHB Monitor Interface.  */
+    /* 0x101e0000 System Controller.  */
+    /* 0x101e1000 Watchdog Interface.  */
+    /* 0x101e2000 Timer 0/1.  */
+    /* 0x101e3000 Timer 2/3.  */
+    /* 0x101e4000 GPIO port 0.  */
+    /* 0x101e5000 GPIO port 1.  */
+    /* 0x101e6000 GPIO port 2.  */
+    /* 0x101e7000 GPIO port 3.  */
+    /* 0x101e8000 RTC.  */
+    /* 0x101f0000 Smart card 0.  */
+    /*  0x101f1000 UART0.  */
+    /*  0x101f2000 UART1.  */
+    /*  0x101f3000 UART2.  */
+    /* 0x101f4000 SSPI.  */
+    /* 0x34000000 NOR Flash */
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash",
+                          VERSATILE_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
+                          VERSATILE_FLASH_SECT_SIZE,
+                          VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE,
+                          4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+    }
+
+    versatile_binfo.ram_size = args->ram_size;
+    versatile_binfo.kernel_filename = args->kernel_filename;
+    versatile_binfo.kernel_cmdline = args->kernel_cmdline;
+    versatile_binfo.initrd_filename = args->initrd_filename;
+    versatile_binfo.board_id = board_id;
+    arm_load_kernel(cpu, &versatile_binfo);
+}
+
+static void vpb_init(QEMUMachineInitArgs *args)
+{
+    versatile_init(args, 0x183);
+}
+
+static void vab_init(QEMUMachineInitArgs *args)
+{
+    versatile_init(args, 0x25e);
+}
+
+static QEMUMachine versatilepb_machine = {
+    .name = "versatilepb",
+    .desc = "ARM Versatile/PB (ARM926EJ-S)",
+    .init = vpb_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine versatileab_machine = {
+    .name = "versatileab",
+    .desc = "ARM Versatile/AB (ARM926EJ-S)",
+    .init = vab_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void versatile_machine_init(void)
+{
+    qemu_register_machine(&versatilepb_machine);
+    qemu_register_machine(&versatileab_machine);
+}
+
+machine_init(versatile_machine_init);
+
+static void vpb_sic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = vpb_sic_init;
+    dc->no_user = 1;
+    dc->vmsd = &vmstate_vpb_sic;
+}
+
+static const TypeInfo vpb_sic_info = {
+    .name          = "versatilepb_sic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(vpb_sic_state),
+    .class_init    = vpb_sic_class_init,
+};
+
+static void versatilepb_register_types(void)
+{
+    type_register_static(&vpb_sic_info);
+}
+
+type_init(versatilepb_register_types)
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
new file mode 100644 (file)
index 0000000..02922c3
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ * ARM Versatile Express emulation.
+ *
+ * Copyright (c) 2010 - 2011 B Labs Ltd.
+ * Copyright (c) 2011 Linaro Limited
+ * Written by Bahadir Balban, Amit Mahajan, Peter Maydell
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  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/>.
+ *
+ *  Contributions after 2012-01-13 are licensed under the terms of the
+ *  GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/primecell.h"
+#include "hw/devices.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "exec/address-spaces.h"
+#include "sysemu/blockdev.h"
+#include "hw/flash.h"
+
+#define VEXPRESS_BOARD_ID 0x8e0
+#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
+#define VEXPRESS_FLASH_SECT_SIZE (256 * 1024)
+
+static struct arm_boot_info vexpress_binfo;
+
+/* Address maps for peripherals:
+ * the Versatile Express motherboard has two possible maps,
+ * the "legacy" one (used for A9) and the "Cortex-A Series"
+ * map (used for newer cores).
+ * Individual daughterboards can also have different maps for
+ * their peripherals.
+ */
+
+enum {
+    VE_SYSREGS,
+    VE_SP810,
+    VE_SERIALPCI,
+    VE_PL041,
+    VE_MMCI,
+    VE_KMI0,
+    VE_KMI1,
+    VE_UART0,
+    VE_UART1,
+    VE_UART2,
+    VE_UART3,
+    VE_WDT,
+    VE_TIMER01,
+    VE_TIMER23,
+    VE_SERIALDVI,
+    VE_RTC,
+    VE_COMPACTFLASH,
+    VE_CLCD,
+    VE_NORFLASH0,
+    VE_NORFLASH1,
+    VE_SRAM,
+    VE_VIDEORAM,
+    VE_ETHERNET,
+    VE_USB,
+    VE_DAPROM,
+};
+
+static hwaddr motherboard_legacy_map[] = {
+    /* CS7: 0x10000000 .. 0x10020000 */
+    [VE_SYSREGS] = 0x10000000,
+    [VE_SP810] = 0x10001000,
+    [VE_SERIALPCI] = 0x10002000,
+    [VE_PL041] = 0x10004000,
+    [VE_MMCI] = 0x10005000,
+    [VE_KMI0] = 0x10006000,
+    [VE_KMI1] = 0x10007000,
+    [VE_UART0] = 0x10009000,
+    [VE_UART1] = 0x1000a000,
+    [VE_UART2] = 0x1000b000,
+    [VE_UART3] = 0x1000c000,
+    [VE_WDT] = 0x1000f000,
+    [VE_TIMER01] = 0x10011000,
+    [VE_TIMER23] = 0x10012000,
+    [VE_SERIALDVI] = 0x10016000,
+    [VE_RTC] = 0x10017000,
+    [VE_COMPACTFLASH] = 0x1001a000,
+    [VE_CLCD] = 0x1001f000,
+    /* CS0: 0x40000000 .. 0x44000000 */
+    [VE_NORFLASH0] = 0x40000000,
+    /* CS1: 0x44000000 .. 0x48000000 */
+    [VE_NORFLASH1] = 0x44000000,
+    /* CS2: 0x48000000 .. 0x4a000000 */
+    [VE_SRAM] = 0x48000000,
+    /* CS3: 0x4c000000 .. 0x50000000 */
+    [VE_VIDEORAM] = 0x4c000000,
+    [VE_ETHERNET] = 0x4e000000,
+    [VE_USB] = 0x4f000000,
+};
+
+static hwaddr motherboard_aseries_map[] = {
+    /* CS0: 0x08000000 .. 0x0c000000 */
+    [VE_NORFLASH0] = 0x08000000,
+    /* CS4: 0x0c000000 .. 0x10000000 */
+    [VE_NORFLASH1] = 0x0c000000,
+    /* CS5: 0x10000000 .. 0x14000000 */
+    /* CS1: 0x14000000 .. 0x18000000 */
+    [VE_SRAM] = 0x14000000,
+    /* CS2: 0x18000000 .. 0x1c000000 */
+    [VE_VIDEORAM] = 0x18000000,
+    [VE_ETHERNET] = 0x1a000000,
+    [VE_USB] = 0x1b000000,
+    /* CS3: 0x1c000000 .. 0x20000000 */
+    [VE_DAPROM] = 0x1c000000,
+    [VE_SYSREGS] = 0x1c010000,
+    [VE_SP810] = 0x1c020000,
+    [VE_SERIALPCI] = 0x1c030000,
+    [VE_PL041] = 0x1c040000,
+    [VE_MMCI] = 0x1c050000,
+    [VE_KMI0] = 0x1c060000,
+    [VE_KMI1] = 0x1c070000,
+    [VE_UART0] = 0x1c090000,
+    [VE_UART1] = 0x1c0a0000,
+    [VE_UART2] = 0x1c0b0000,
+    [VE_UART3] = 0x1c0c0000,
+    [VE_WDT] = 0x1c0f0000,
+    [VE_TIMER01] = 0x1c110000,
+    [VE_TIMER23] = 0x1c120000,
+    [VE_SERIALDVI] = 0x1c160000,
+    [VE_RTC] = 0x1c170000,
+    [VE_COMPACTFLASH] = 0x1c1a0000,
+    [VE_CLCD] = 0x1c1f0000,
+};
+
+/* Structure defining the peculiarities of a specific daughterboard */
+
+typedef struct VEDBoardInfo VEDBoardInfo;
+
+typedef void DBoardInitFn(const VEDBoardInfo *daughterboard,
+                          ram_addr_t ram_size,
+                          const char *cpu_model,
+                          qemu_irq *pic, uint32_t *proc_id);
+
+struct VEDBoardInfo {
+    const hwaddr *motherboard_map;
+    hwaddr loader_start;
+    const hwaddr gic_cpu_if_addr;
+    DBoardInitFn *init;
+};
+
+static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
+                                  ram_addr_t ram_size,
+                                  const char *cpu_model,
+                                  qemu_irq *pic, uint32_t *proc_id)
+{
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *lowram = g_new(MemoryRegion, 1);
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    int n;
+    qemu_irq cpu_irq[4];
+    ram_addr_t low_ram_size;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    *proc_id = 0x0c000191;
+
+    for (n = 0; n < smp_cpus; n++) {
+        ARMCPU *cpu = cpu_arm_init(cpu_model);
+        if (!cpu) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(cpu);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+
+    if (ram_size > 0x40000000) {
+        /* 1GB is the maximum the address space permits */
+        fprintf(stderr, "vexpress-a9: cannot model more than 1GB RAM\n");
+        exit(1);
+    }
+
+    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
+    vmstate_register_ram_global(ram);
+    low_ram_size = ram_size;
+    if (low_ram_size > 0x4000000) {
+        low_ram_size = 0x4000000;
+    }
+    /* RAM is from 0x60000000 upwards. The bottom 64MB of the
+     * address space should in theory be remappable to various
+     * things including ROM or RAM; we always map the RAM there.
+     */
+    memory_region_init_alias(lowram, "vexpress.lowmem", ram, 0, low_ram_size);
+    memory_region_add_subregion(sysmem, 0x0, lowram);
+    memory_region_add_subregion(sysmem, 0x60000000, ram);
+
+    /* 0x1e000000 A9MPCore (SCU) private memory region */
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0x1e000000);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+    /* Interrupts [42:0] are from the motherboard;
+     * [47:43] are reserved; [63:48] are daughterboard
+     * peripherals. Note that some documentation numbers
+     * external interrupts starting from 32 (because the
+     * A9MP has internal interrupts 0..31).
+     */
+    for (n = 0; n < 64; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
+
+    /* 0x10020000 PL111 CLCD (daughterboard) */
+    sysbus_create_simple("pl111", 0x10020000, pic[44]);
+
+    /* 0x10060000 AXI RAM */
+    /* 0x100e0000 PL341 Dynamic Memory Controller */
+    /* 0x100e1000 PL354 Static Memory Controller */
+    /* 0x100e2000 System Configuration Controller */
+
+    sysbus_create_simple("sp804", 0x100e4000, pic[48]);
+    /* 0x100e5000 SP805 Watchdog module */
+    /* 0x100e6000 BP147 TrustZone Protection Controller */
+    /* 0x100e9000 PL301 'Fast' AXI matrix */
+    /* 0x100ea000 PL301 'Slow' AXI matrix */
+    /* 0x100ec000 TrustZone Address Space Controller */
+    /* 0x10200000 CoreSight debug APB */
+    /* 0x1e00a000 PL310 L2 Cache Controller */
+    sysbus_create_varargs("l2x0", 0x1e00a000, NULL);
+}
+
+static const VEDBoardInfo a9_daughterboard = {
+    .motherboard_map = motherboard_legacy_map,
+    .loader_start = 0x60000000,
+    .gic_cpu_if_addr = 0x1e000100,
+    .init = a9_daughterboard_init,
+};
+
+static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
+                                   ram_addr_t ram_size,
+                                   const char *cpu_model,
+                                   qemu_irq *pic, uint32_t *proc_id)
+{
+    int n;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    qemu_irq cpu_irq[4];
+    DeviceState *dev;
+    SysBusDevice *busdev;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a15";
+    }
+
+    *proc_id = 0x14000237;
+
+    for (n = 0; n < smp_cpus; n++) {
+        ARMCPU *cpu;
+        qemu_irq *irqp;
+
+        cpu = cpu_arm_init(cpu_model);
+        if (!cpu) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(cpu);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+
+    {
+        /* We have to use a separate 64 bit variable here to avoid the gcc
+         * "comparison is always false due to limited range of data type"
+         * warning if we are on a host where ram_addr_t is 32 bits.
+         */
+        uint64_t rsz = ram_size;
+        if (rsz > (30ULL * 1024 * 1024 * 1024)) {
+            fprintf(stderr, "vexpress-a15: cannot model more than 30GB RAM\n");
+            exit(1);
+        }
+    }
+
+    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
+    vmstate_register_ram_global(ram);
+    /* RAM is from 0x80000000 upwards; there is no low-memory alias for it. */
+    memory_region_add_subregion(sysmem, 0x80000000, ram);
+
+    /* 0x2c000000 A15MPCore private memory region (GIC) */
+    dev = qdev_create(NULL, "a15mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0x2c000000);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+    /* Interrupts [42:0] are from the motherboard;
+     * [47:43] are reserved; [63:48] are daughterboard
+     * peripherals. Note that some documentation numbers
+     * external interrupts starting from 32 (because there
+     * are internal interrupts 0..31).
+     */
+    for (n = 0; n < 64; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    /* A15 daughterboard peripherals: */
+
+    /* 0x20000000: CoreSight interfaces: not modelled */
+    /* 0x2a000000: PL301 AXI interconnect: not modelled */
+    /* 0x2a420000: SCC: not modelled */
+    /* 0x2a430000: system counter: not modelled */
+    /* 0x2b000000: HDLCD controller: not modelled */
+    /* 0x2b060000: SP805 watchdog: not modelled */
+    /* 0x2b0a0000: PL341 dynamic memory controller: not modelled */
+    /* 0x2e000000: system SRAM */
+    memory_region_init_ram(sram, "vexpress.a15sram", 0x10000);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(sysmem, 0x2e000000, sram);
+
+    /* 0x7ffb0000: DMA330 DMA controller: not modelled */
+    /* 0x7ffd0000: PL354 static memory controller: not modelled */
+}
+
+static const VEDBoardInfo a15_daughterboard = {
+    .motherboard_map = motherboard_aseries_map,
+    .loader_start = 0x80000000,
+    .gic_cpu_if_addr = 0x2c002000,
+    .init = a15_daughterboard_init,
+};
+
+static void vexpress_common_init(const VEDBoardInfo *daughterboard,
+                                 QEMUMachineInitArgs *args)
+{
+    DeviceState *dev, *sysctl, *pl041;
+    qemu_irq pic[64];
+    uint32_t proc_id;
+    uint32_t sys_id;
+    DriveInfo *dinfo;
+    ram_addr_t vram_size, sram_size;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *vram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    const hwaddr *map = daughterboard->motherboard_map;
+
+    daughterboard->init(daughterboard, args->ram_size, args->cpu_model,
+                        pic, &proc_id);
+
+    /* Motherboard peripherals: the wiring is the same but the
+     * addresses vary between the legacy and A-Series memory maps.
+     */
+
+    sys_id = 0x1190f500;
+
+    sysctl = qdev_create(NULL, "realview_sysctl");
+    qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
+    qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
+    qdev_init_nofail(sysctl);
+    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]);
+
+    /* VE_SP810: not modelled */
+    /* VE_SERIALPCI: not modelled */
+
+    pl041 = qdev_create(NULL, "pl041");
+    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
+    qdev_init_nofail(pl041);
+    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, map[VE_PL041]);
+    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[11]);
+
+    dev = sysbus_create_varargs("pl181", map[VE_MMCI], pic[9], pic[10], NULL);
+    /* Wire up MMC card detect and read-only signals */
+    qdev_connect_gpio_out(dev, 0,
+                          qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT));
+    qdev_connect_gpio_out(dev, 1,
+                          qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN));
+
+    sysbus_create_simple("pl050_keyboard", map[VE_KMI0], pic[12]);
+    sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]);
+
+    sysbus_create_simple("pl011", map[VE_UART0], pic[5]);
+    sysbus_create_simple("pl011", map[VE_UART1], pic[6]);
+    sysbus_create_simple("pl011", map[VE_UART2], pic[7]);
+    sysbus_create_simple("pl011", map[VE_UART3], pic[8]);
+
+    sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
+    sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
+
+    /* VE_SERIALDVI: not modelled */
+
+    sysbus_create_simple("pl031", map[VE_RTC], pic[4]); /* RTC */
+
+    /* VE_COMPACTFLASH: not modelled */
+
+    sysbus_create_simple("pl111", map[VE_CLCD], pic[14]);
+
+    dinfo = drive_get_next(IF_PFLASH);
+    if (!pflash_cfi01_register(map[VE_NORFLASH0], NULL, "vexpress.flash0",
+            VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
+            VEXPRESS_FLASH_SECT_SIZE,
+            VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4,
+            0x00, 0x89, 0x00, 0x18, 0)) {
+        fprintf(stderr, "vexpress: error registering flash 0.\n");
+        exit(1);
+    }
+
+    dinfo = drive_get_next(IF_PFLASH);
+    if (!pflash_cfi01_register(map[VE_NORFLASH1], NULL, "vexpress.flash1",
+            VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
+            VEXPRESS_FLASH_SECT_SIZE,
+            VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4,
+            0x00, 0x89, 0x00, 0x18, 0)) {
+        fprintf(stderr, "vexpress: error registering flash 1.\n");
+        exit(1);
+    }
+
+    sram_size = 0x2000000;
+    memory_region_init_ram(sram, "vexpress.sram", sram_size);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(sysmem, map[VE_SRAM], sram);
+
+    vram_size = 0x800000;
+    memory_region_init_ram(vram, "vexpress.vram", vram_size);
+    vmstate_register_ram_global(vram);
+    memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram);
+
+    /* 0x4e000000 LAN9118 Ethernet */
+    if (nd_table[0].used) {
+        lan9118_init(&nd_table[0], map[VE_ETHERNET], pic[15]);
+    }
+
+    /* VE_USB: not modelled */
+
+    /* VE_DAPROM: not modelled */
+
+    vexpress_binfo.ram_size = args->ram_size;
+    vexpress_binfo.kernel_filename = args->kernel_filename;
+    vexpress_binfo.kernel_cmdline = args->kernel_cmdline;
+    vexpress_binfo.initrd_filename = args->initrd_filename;
+    vexpress_binfo.nb_cpus = smp_cpus;
+    vexpress_binfo.board_id = VEXPRESS_BOARD_ID;
+    vexpress_binfo.loader_start = daughterboard->loader_start;
+    vexpress_binfo.smp_loader_start = map[VE_SRAM];
+    vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
+    vexpress_binfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &vexpress_binfo);
+}
+
+static void vexpress_a9_init(QEMUMachineInitArgs *args)
+{
+    vexpress_common_init(&a9_daughterboard, args);
+}
+
+static void vexpress_a15_init(QEMUMachineInitArgs *args)
+{
+    vexpress_common_init(&a15_daughterboard, args);
+}
+
+static QEMUMachine vexpress_a9_machine = {
+    .name = "vexpress-a9",
+    .desc = "ARM Versatile Express for Cortex-A9",
+    .init = vexpress_a9_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine vexpress_a15_machine = {
+    .name = "vexpress-a15",
+    .desc = "ARM Versatile Express for Cortex-A15",
+    .init = vexpress_a15_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void vexpress_machine_init(void)
+{
+    qemu_register_machine(&vexpress_a9_machine);
+    qemu_register_machine(&vexpress_a15_machine);
+}
+
+machine_init(vexpress_machine_init);
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
new file mode 100644 (file)
index 0000000..f78c47e
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Xilinx Zynq Baseboard System emulation.
+ *
+ * Copyright (c) 2010 Xilinx.
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.croshtwaite@petalogix.com)
+ * Copyright (c) 2012 Petalogix Pty Ltd.
+ * Written by Haibing Ma
+ *
+ * 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.
+ *
+ * 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 "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "net/net.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "hw/loader.h"
+#include "hw/ssi.h"
+
+#define NUM_SPI_FLASHES 4
+#define NUM_QSPI_FLASHES 2
+#define NUM_QSPI_BUSSES 2
+
+#define FLASH_SIZE (64 * 1024 * 1024)
+#define FLASH_SECTOR_SIZE (128 * 1024)
+
+#define IRQ_OFFSET 32 /* pic interrupts start from index 32 */
+
+static struct arm_boot_info zynq_binfo = {};
+
+static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    qemu_check_nic_model(nd, "cadence_gem");
+    dev = qdev_create(NULL, "cadence_gem");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(s, 0, base);
+    sysbus_connect_irq(s, 0, irq);
+}
+
+static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
+                                         bool is_qspi)
+{
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    SSIBus *spi;
+    DeviceState *flash_dev;
+    int i, j;
+    int num_busses =  is_qspi ? NUM_QSPI_BUSSES : 1;
+    int num_ss = is_qspi ? NUM_QSPI_FLASHES : NUM_SPI_FLASHES;
+
+    dev = qdev_create(NULL, "xilinx,spips");
+    qdev_prop_set_uint8(dev, "num-txrx-bytes", is_qspi ? 4 : 1);
+    qdev_prop_set_uint8(dev, "num-ss-bits", num_ss);
+    qdev_prop_set_uint8(dev, "num-busses", num_busses);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, base_addr);
+    if (is_qspi) {
+        sysbus_mmio_map(busdev, 1, 0xFC000000);
+    }
+    sysbus_connect_irq(busdev, 0, irq);
+
+    for (i = 0; i < num_busses; ++i) {
+        char bus_name[16];
+        qemu_irq cs_line;
+
+        snprintf(bus_name, 16, "spi%d", i);
+        spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
+
+        for (j = 0; j < num_ss; ++j) {
+            flash_dev = ssi_create_slave_no_init(spi, "n25q128");
+            qdev_init_nofail(flash_dev);
+
+            cs_line = qdev_get_gpio_in(flash_dev, 0);
+            sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line);
+        }
+    }
+
+}
+
+static void zynq_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    ARMCPU *cpu;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
+    MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[64];
+    NICInfo *nd;
+    int n;
+    qemu_irq cpu_irq;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    irqp = arm_pic_init_cpu(cpu);
+    cpu_irq = irqp[ARM_PIC_CPU_IRQ];
+
+    /* max 2GB ram */
+    if (ram_size > 0x80000000) {
+        ram_size = 0x80000000;
+    }
+
+    /* DDR remapped to address zero.  */
+    memory_region_init_ram(ext_ram, "zynq.ext_ram", ram_size);
+    vmstate_register_ram_global(ext_ram);
+    memory_region_add_subregion(address_space_mem, 0, ext_ram);
+
+    /* 256K of on-chip memory */
+    memory_region_init_ram(ocm_ram, "zynq.ocm_ram", 256 << 10);
+    vmstate_register_ram_global(ocm_ram);
+    memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram);
+
+    DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
+
+    /* AMD */
+    pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE,
+                          FLASH_SIZE/FLASH_SECTOR_SIZE, 1,
+                          1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
+                              0);
+
+    dev = qdev_create(NULL, "xilinx,zynq_slcr");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000);
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", 1);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0xF8F00000);
+    sysbus_connect_irq(busdev, 0, cpu_irq);
+
+    for (n = 0; n < 64; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET], false);
+    zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false);
+    zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true);
+
+    sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]);
+    sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]);
+
+    sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]);
+    sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]);
+
+    sysbus_create_varargs("cadence_ttc", 0xF8001000,
+            pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);
+    sysbus_create_varargs("cadence_ttc", 0xF8002000,
+            pic[69-IRQ_OFFSET], pic[70-IRQ_OFFSET], pic[71-IRQ_OFFSET], NULL);
+
+    for (n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+        if (n == 0) {
+            gem_init(nd, 0xE000B000, pic[54-IRQ_OFFSET]);
+        } else if (n == 1) {
+            gem_init(nd, 0xE000C000, pic[77-IRQ_OFFSET]);
+        }
+    }
+
+    dev = qdev_create(NULL, "generic-sdhci");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
+
+    dev = qdev_create(NULL, "generic-sdhci");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
+
+    zynq_binfo.ram_size = ram_size;
+    zynq_binfo.kernel_filename = kernel_filename;
+    zynq_binfo.kernel_cmdline = kernel_cmdline;
+    zynq_binfo.initrd_filename = initrd_filename;
+    zynq_binfo.nb_cpus = 1;
+    zynq_binfo.board_id = 0xd32;
+    zynq_binfo.loader_start = 0;
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &zynq_binfo);
+}
+
+static QEMUMachine zynq_machine = {
+    .name = "xilinx-zynq-a9",
+    .desc = "Xilinx Zynq Platform Baseboard for Cortex-A9",
+    .init = zynq_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 1,
+    .no_sdcard = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void zynq_machine_init(void)
+{
+    qemu_register_machine(&zynq_machine);
+}
+
+machine_init(zynq_machine_init);
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
new file mode 100644 (file)
index 0000000..cbb6d80
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * PXA270-based Zipit Z2 device
+ *
+ * Copyright (c) 2011 by Vasily Khoruzhick <anarsoul@gmail.com>
+ *
+ * Code is based on mainstone platform.
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
+#include "hw/boards.h"
+#include "sysemu/sysemu.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "ui/console.h"
+#include "audio/audio.h"
+#include "exec/address-spaces.h"
+
+#ifdef DEBUG_Z2
+#define DPRINTF(fmt, ...) \
+        printf(fmt, ## __VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+static struct keymap map[0x100] = {
+    [0 ... 0xff] = { -1, -1 },
+    [0x3b] = {0, 0}, /* Option = F1 */
+    [0xc8] = {0, 1}, /* Up */
+    [0xd0] = {0, 2}, /* Down */
+    [0xcb] = {0, 3}, /* Left */
+    [0xcd] = {0, 4}, /* Right */
+    [0xcf] = {0, 5}, /* End */
+    [0x0d] = {0, 6}, /* KPPLUS */
+    [0xc7] = {1, 0}, /* Home */
+    [0x10] = {1, 1}, /* Q */
+    [0x17] = {1, 2}, /* I */
+    [0x22] = {1, 3}, /* G */
+    [0x2d] = {1, 4}, /* X */
+    [0x1c] = {1, 5}, /* Enter */
+    [0x0c] = {1, 6}, /* KPMINUS */
+    [0xc9] = {2, 0}, /* PageUp */
+    [0x11] = {2, 1}, /* W */
+    [0x18] = {2, 2}, /* O */
+    [0x23] = {2, 3}, /* H */
+    [0x2e] = {2, 4}, /* C */
+    [0x38] = {2, 5}, /* LeftAlt */
+    [0xd1] = {3, 0}, /* PageDown */
+    [0x12] = {3, 1}, /* E */
+    [0x19] = {3, 2}, /* P */
+    [0x24] = {3, 3}, /* J */
+    [0x2f] = {3, 4}, /* V */
+    [0x2a] = {3, 5}, /* LeftShift */
+    [0x01] = {4, 0}, /* Esc */
+    [0x13] = {4, 1}, /* R */
+    [0x1e] = {4, 2}, /* A */
+    [0x25] = {4, 3}, /* K */
+    [0x30] = {4, 4}, /* B */
+    [0x1d] = {4, 5}, /* LeftCtrl */
+    [0x0f] = {5, 0}, /* Tab */
+    [0x14] = {5, 1}, /* T */
+    [0x1f] = {5, 2}, /* S */
+    [0x26] = {5, 3}, /* L */
+    [0x31] = {5, 4}, /* N */
+    [0x39] = {5, 5}, /* Space */
+    [0x3c] = {6, 0}, /* Stop = F2 */
+    [0x15] = {6, 1}, /* Y */
+    [0x20] = {6, 2}, /* D */
+    [0x0e] = {6, 3}, /* Backspace */
+    [0x32] = {6, 4}, /* M */
+    [0x33] = {6, 5}, /* Comma */
+    [0x3d] = {7, 0}, /* Play = F3 */
+    [0x16] = {7, 1}, /* U */
+    [0x21] = {7, 2}, /* F */
+    [0x2c] = {7, 3}, /* Z */
+    [0x27] = {7, 4}, /* Semicolon */
+    [0x34] = {7, 5}, /* Dot */
+};
+
+#define Z2_RAM_SIZE     0x02000000
+#define Z2_FLASH_BASE   0x00000000
+#define Z2_FLASH_SIZE   0x00800000
+
+static struct arm_boot_info z2_binfo = {
+    .loader_start   = PXA2XX_SDRAM_BASE,
+    .ram_size       = Z2_RAM_SIZE,
+};
+
+#define Z2_GPIO_SD_DETECT   96
+#define Z2_GPIO_AC_IN       0
+#define Z2_GPIO_KEY_ON      1
+#define Z2_GPIO_LCD_CS      88
+
+typedef struct {
+    SSISlave ssidev;
+    int32_t selected;
+    int32_t enabled;
+    uint8_t buf[3];
+    uint32_t cur_reg;
+    int pos;
+} ZipitLCD;
+
+static uint32_t zipit_lcd_transfer(SSISlave *dev, uint32_t value)
+{
+    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
+    uint16_t val;
+    if (z->selected) {
+        z->buf[z->pos] = value & 0xff;
+        z->pos++;
+    }
+    if (z->pos == 3) {
+        switch (z->buf[0]) {
+        case 0x74:
+            DPRINTF("%s: reg: 0x%.2x\n", __func__, z->buf[2]);
+            z->cur_reg = z->buf[2];
+            break;
+        case 0x76:
+            val = z->buf[1] << 8 | z->buf[2];
+            DPRINTF("%s: value: 0x%.4x\n", __func__, val);
+            if (z->cur_reg == 0x22 && val == 0x0000) {
+                z->enabled = 1;
+                printf("%s: LCD enabled\n", __func__);
+            } else if (z->cur_reg == 0x10 && val == 0x0000) {
+                z->enabled = 0;
+                printf("%s: LCD disabled\n", __func__);
+            }
+            break;
+        default:
+            DPRINTF("%s: unknown command!\n", __func__);
+            break;
+        }
+        z->pos = 0;
+    }
+    return 0;
+}
+
+static void z2_lcd_cs(void *opaque, int line, int level)
+{
+    ZipitLCD *z2_lcd = opaque;
+    z2_lcd->selected = !level;
+}
+
+static int zipit_lcd_init(SSISlave *dev)
+{
+    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
+    z->selected = 0;
+    z->enabled = 0;
+    z->pos = 0;
+
+    return 0;
+}
+
+static VMStateDescription vmstate_zipit_lcd_state = {
+    .name = "zipit-lcd",
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .fields = (VMStateField[]) {
+        VMSTATE_SSI_SLAVE(ssidev, ZipitLCD),
+        VMSTATE_INT32(selected, ZipitLCD),
+        VMSTATE_INT32(enabled, ZipitLCD),
+        VMSTATE_BUFFER(buf, ZipitLCD),
+        VMSTATE_UINT32(cur_reg, ZipitLCD),
+        VMSTATE_INT32(pos, ZipitLCD),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void zipit_lcd_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+    k->init = zipit_lcd_init;
+    k->transfer = zipit_lcd_transfer;
+    dc->vmsd = &vmstate_zipit_lcd_state;
+}
+
+static const TypeInfo zipit_lcd_info = {
+    .name          = "zipit-lcd",
+    .parent        = TYPE_SSI_SLAVE,
+    .instance_size = sizeof(ZipitLCD),
+    .class_init    = zipit_lcd_class_init,
+};
+
+typedef struct {
+    I2CSlave i2c;
+    int len;
+    uint8_t buf[3];
+} AER915State;
+
+static int aer915_send(I2CSlave *i2c, uint8_t data)
+{
+    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
+    s->buf[s->len] = data;
+    if (s->len++ > 2) {
+        DPRINTF("%s: message too long (%i bytes)\n",
+            __func__, s->len);
+        return 1;
+    }
+
+    if (s->len == 2) {
+        DPRINTF("%s: reg %d value 0x%02x\n", __func__,
+                s->buf[0], s->buf[1]);
+    }
+
+    return 0;
+}
+
+static void aer915_event(I2CSlave *i2c, enum i2c_event event)
+{
+    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
+    switch (event) {
+    case I2C_START_SEND:
+        s->len = 0;
+        break;
+    case I2C_START_RECV:
+        if (s->len != 1) {
+            DPRINTF("%s: short message!?\n", __func__);
+        }
+        break;
+    case I2C_FINISH:
+        break;
+    default:
+        break;
+    }
+}
+
+static int aer915_recv(I2CSlave *slave)
+{
+    int retval = 0x00;
+    AER915State *s = FROM_I2C_SLAVE(AER915State, slave);
+
+    switch (s->buf[0]) {
+    /* Return hardcoded battery voltage,
+     * 0xf0 means ~4.1V
+     */
+    case 0x02:
+        retval = 0xf0;
+        break;
+    /* Return 0x00 for other regs,
+     * we don't know what they are for,
+     * anyway they return 0x00 on real hardware.
+     */
+    default:
+        break;
+    }
+
+    return retval;
+}
+
+static int aer915_init(I2CSlave *i2c)
+{
+    /* Nothing to do.  */
+    return 0;
+}
+
+static VMStateDescription vmstate_aer915_state = {
+    .name = "aer915",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT32(len, AER915State),
+        VMSTATE_BUFFER(buf, AER915State),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void aer915_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+    k->init = aer915_init;
+    k->event = aer915_event;
+    k->recv = aer915_recv;
+    k->send = aer915_send;
+    dc->vmsd = &vmstate_aer915_state;
+}
+
+static const TypeInfo aer915_info = {
+    .name          = "aer915",
+    .parent        = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(AER915State),
+    .class_init    = aer915_class_init,
+};
+
+static void z2_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    uint32_t sector_len = 0x10000;
+    PXA2xxState *mpu;
+    DriveInfo *dinfo;
+    int be;
+    void *z2_lcd;
+    i2c_bus *bus;
+    DeviceState *wm;
+
+    if (!cpu_model) {
+        cpu_model = "pxa270-c5";
+    }
+
+    /* Setup CPU & memory */
+    mpu = pxa270_init(address_space_mem, z2_binfo.ram_size, cpu_model);
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "Flash image must be given with the "
+                "'pflash' parameter\n");
+        exit(1);
+    }
+
+    if (!pflash_cfi01_register(Z2_FLASH_BASE,
+                               NULL, "z2.flash0", Z2_FLASH_SIZE,
+                               dinfo->bdrv, sector_len,
+                               Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
+                               be)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+        exit(1);
+    }
+
+    /* setup keypad */
+    pxa27x_register_keypad(mpu->kp, map, 0x100);
+
+    /* MMC/SD host */
+    pxa2xx_mmci_handlers(mpu->mmc,
+        NULL,
+        qdev_get_gpio_in(mpu->gpio, Z2_GPIO_SD_DETECT));
+
+    type_register_static(&zipit_lcd_info);
+    type_register_static(&aer915_info);
+    z2_lcd = ssi_create_slave(mpu->ssp[1], "zipit-lcd");
+    bus = pxa2xx_i2c_bus(mpu->i2c[0]);
+    i2c_create_slave(bus, "aer915", 0x55);
+    wm = i2c_create_slave(bus, "wm8750", 0x1b);
+    mpu->i2s->opaque = wm;
+    mpu->i2s->codec_out = wm8750_dac_dat;
+    mpu->i2s->codec_in = wm8750_adc_dat;
+    wm8750_data_req_set(wm, mpu->i2s->data_req, mpu->i2s);
+
+    qdev_connect_gpio_out(mpu->gpio, Z2_GPIO_LCD_CS,
+        qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
+
+    if (kernel_filename) {
+        z2_binfo.kernel_filename = kernel_filename;
+        z2_binfo.kernel_cmdline = kernel_cmdline;
+        z2_binfo.initrd_filename = initrd_filename;
+        z2_binfo.board_id = 0x6dd;
+        arm_load_kernel(mpu->cpu, &z2_binfo);
+    }
+}
+
+static QEMUMachine z2_machine = {
+    .name = "z2",
+    .desc = "Zipit Z2 (PXA27x)",
+    .init = z2_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void z2_machine_init(void)
+{
+    qemu_register_machine(&z2_machine);
+}
+
+machine_init(z2_machine_init);
index ca49948ffcefa37ddc217ecd2e96533f1dca9809..90dceade715cbe0f0ba10988de6b0f3da6ceb13a 100644 (file)
@@ -7,7 +7,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 
 /* MPCore private memory region.  */
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
deleted file mode 100644 (file)
index 4065424..0000000
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * ARM kernel loader.
- *
- * Copyright (c) 2006-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "config.h"
-#include "hw.h"
-#include "arm-misc.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "loader.h"
-#include "elf.h"
-#include "sysemu/device_tree.h"
-#include "qemu/config-file.h"
-
-#define KERNEL_ARGS_ADDR 0x100
-#define KERNEL_LOAD_ADDR 0x00010000
-
-/* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
-static uint32_t bootloader[] = {
-  0xe3a00000, /* mov     r0, #0 */
-  0xe59f1004, /* ldr     r1, [pc, #4] */
-  0xe59f2004, /* ldr     r2, [pc, #4] */
-  0xe59ff004, /* ldr     pc, [pc, #4] */
-  0, /* Board ID */
-  0, /* Address of kernel args.  Set by integratorcp_init.  */
-  0  /* Kernel entry point.  Set by integratorcp_init.  */
-};
-
-/* Handling for secondary CPU boot in a multicore system.
- * Unlike the uniprocessor/primary CPU boot, this is platform
- * dependent. The default code here is based on the secondary
- * CPU boot protocol used on realview/vexpress boards, with
- * some parameterisation to increase its flexibility.
- * QEMU platform models for which this code is not appropriate
- * should override write_secondary_boot and secondary_cpu_reset_hook
- * instead.
- *
- * This code enables the interrupt controllers for the secondary
- * CPUs and then puts all the secondary CPUs into a loop waiting
- * for an interprocessor interrupt and polling a configurable
- * location for the kernel secondary CPU entry point.
- */
-#define DSB_INSN 0xf57ff04f
-#define CP15_DSB_INSN 0xee070f9a /* mcr cp15, 0, r0, c7, c10, 4 */
-
-static uint32_t smpboot[] = {
-  0xe59f2028, /* ldr r2, gic_cpu_if */
-  0xe59f0028, /* ldr r0, startaddr */
-  0xe3a01001, /* mov r1, #1 */
-  0xe5821000, /* str r1, [r2] - set GICC_CTLR.Enable */
-  0xe3a010ff, /* mov r1, #0xff */
-  0xe5821004, /* str r1, [r2, 4] - set GIC_PMR.Priority to 0xff */
-  DSB_INSN,   /* dsb */
-  0xe320f003, /* wfi */
-  0xe5901000, /* ldr     r1, [r0] */
-  0xe1110001, /* tst     r1, r1 */
-  0x0afffffb, /* beq     <wfi> */
-  0xe12fff11, /* bx      r1 */
-  0,          /* gic_cpu_if: base address of GIC CPU interface */
-  0           /* bootreg: Boot register address is held here */
-};
-
-static void default_write_secondary(ARMCPU *cpu,
-                                    const struct arm_boot_info *info)
-{
-    int n;
-    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++) {
-        /* Replace DSB with the pre-v7 DSB if necessary. */
-        if (!arm_feature(&cpu->env, ARM_FEATURE_V7) &&
-            smpboot[n] == DSB_INSN) {
-            smpboot[n] = CP15_DSB_INSN;
-        }
-        smpboot[n] = tswap32(smpboot[n]);
-    }
-    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
-                       info->smp_loader_start);
-}
-
-static void default_reset_secondary(ARMCPU *cpu,
-                                    const struct arm_boot_info *info)
-{
-    CPUARMState *env = &cpu->env;
-
-    stl_phys_notdirty(info->smp_bootreg_addr, 0);
-    env->regs[15] = info->smp_loader_start;
-}
-
-#define WRITE_WORD(p, value) do { \
-    stl_phys_notdirty(p, value);  \
-    p += 4;                       \
-} while (0)
-
-static void set_kernel_args(const struct arm_boot_info *info)
-{
-    int initrd_size = info->initrd_size;
-    hwaddr base = info->loader_start;
-    hwaddr p;
-
-    p = base + KERNEL_ARGS_ADDR;
-    /* ATAG_CORE */
-    WRITE_WORD(p, 5);
-    WRITE_WORD(p, 0x54410001);
-    WRITE_WORD(p, 1);
-    WRITE_WORD(p, 0x1000);
-    WRITE_WORD(p, 0);
-    /* ATAG_MEM */
-    /* TODO: handle multiple chips on one ATAG list */
-    WRITE_WORD(p, 4);
-    WRITE_WORD(p, 0x54410002);
-    WRITE_WORD(p, info->ram_size);
-    WRITE_WORD(p, info->loader_start);
-    if (initrd_size) {
-        /* ATAG_INITRD2 */
-        WRITE_WORD(p, 4);
-        WRITE_WORD(p, 0x54420005);
-        WRITE_WORD(p, info->initrd_start);
-        WRITE_WORD(p, initrd_size);
-    }
-    if (info->kernel_cmdline && *info->kernel_cmdline) {
-        /* ATAG_CMDLINE */
-        int cmdline_size;
-
-        cmdline_size = strlen(info->kernel_cmdline);
-        cpu_physical_memory_write(p + 8, (void *)info->kernel_cmdline,
-                                  cmdline_size + 1);
-        cmdline_size = (cmdline_size >> 2) + 1;
-        WRITE_WORD(p, cmdline_size + 2);
-        WRITE_WORD(p, 0x54410009);
-        p += cmdline_size * 4;
-    }
-    if (info->atag_board) {
-        /* ATAG_BOARD */
-        int atag_board_len;
-        uint8_t atag_board_buf[0x1000];
-
-        atag_board_len = (info->atag_board(info, atag_board_buf) + 3) & ~3;
-        WRITE_WORD(p, (atag_board_len + 8) >> 2);
-        WRITE_WORD(p, 0x414f4d50);
-        cpu_physical_memory_write(p, atag_board_buf, atag_board_len);
-        p += atag_board_len;
-    }
-    /* ATAG_END */
-    WRITE_WORD(p, 0);
-    WRITE_WORD(p, 0);
-}
-
-static void set_kernel_args_old(const struct arm_boot_info *info)
-{
-    hwaddr p;
-    const char *s;
-    int initrd_size = info->initrd_size;
-    hwaddr base = info->loader_start;
-
-    /* see linux/include/asm-arm/setup.h */
-    p = base + KERNEL_ARGS_ADDR;
-    /* page_size */
-    WRITE_WORD(p, 4096);
-    /* nr_pages */
-    WRITE_WORD(p, info->ram_size / 4096);
-    /* ramdisk_size */
-    WRITE_WORD(p, 0);
-#define FLAG_READONLY  1
-#define FLAG_RDLOAD    4
-#define FLAG_RDPROMPT  8
-    /* flags */
-    WRITE_WORD(p, FLAG_READONLY | FLAG_RDLOAD | FLAG_RDPROMPT);
-    /* rootdev */
-    WRITE_WORD(p, (31 << 8) | 0);      /* /dev/mtdblock0 */
-    /* video_num_cols */
-    WRITE_WORD(p, 0);
-    /* video_num_rows */
-    WRITE_WORD(p, 0);
-    /* video_x */
-    WRITE_WORD(p, 0);
-    /* video_y */
-    WRITE_WORD(p, 0);
-    /* memc_control_reg */
-    WRITE_WORD(p, 0);
-    /* unsigned char sounddefault */
-    /* unsigned char adfsdrives */
-    /* unsigned char bytes_per_char_h */
-    /* unsigned char bytes_per_char_v */
-    WRITE_WORD(p, 0);
-    /* pages_in_bank[4] */
-    WRITE_WORD(p, 0);
-    WRITE_WORD(p, 0);
-    WRITE_WORD(p, 0);
-    WRITE_WORD(p, 0);
-    /* pages_in_vram */
-    WRITE_WORD(p, 0);
-    /* initrd_start */
-    if (initrd_size) {
-        WRITE_WORD(p, info->initrd_start);
-    } else {
-        WRITE_WORD(p, 0);
-    }
-    /* initrd_size */
-    WRITE_WORD(p, initrd_size);
-    /* rd_start */
-    WRITE_WORD(p, 0);
-    /* system_rev */
-    WRITE_WORD(p, 0);
-    /* system_serial_low */
-    WRITE_WORD(p, 0);
-    /* system_serial_high */
-    WRITE_WORD(p, 0);
-    /* mem_fclk_21285 */
-    WRITE_WORD(p, 0);
-    /* zero unused fields */
-    while (p < base + KERNEL_ARGS_ADDR + 256 + 1024) {
-        WRITE_WORD(p, 0);
-    }
-    s = info->kernel_cmdline;
-    if (s) {
-        cpu_physical_memory_write(p, (void *)s, strlen(s) + 1);
-    } else {
-        WRITE_WORD(p, 0);
-    }
-}
-
-static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
-{
-#ifdef CONFIG_FDT
-    uint32_t *mem_reg_property;
-    uint32_t mem_reg_propsize;
-    void *fdt = NULL;
-    char *filename;
-    int size, rc;
-    uint32_t acells, scells, hival;
-
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
-    if (!filename) {
-        fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
-        return -1;
-    }
-
-    fdt = load_device_tree(filename, &size);
-    if (!fdt) {
-        fprintf(stderr, "Couldn't open dtb file %s\n", filename);
-        g_free(filename);
-        return -1;
-    }
-    g_free(filename);
-
-    acells = qemu_devtree_getprop_cell(fdt, "/", "#address-cells");
-    scells = qemu_devtree_getprop_cell(fdt, "/", "#size-cells");
-    if (acells == 0 || scells == 0) {
-        fprintf(stderr, "dtb file invalid (#address-cells or #size-cells 0)\n");
-        return -1;
-    }
-
-    mem_reg_propsize = acells + scells;
-    mem_reg_property = g_new0(uint32_t, mem_reg_propsize);
-    mem_reg_property[acells - 1] = cpu_to_be32(binfo->loader_start);
-    hival = cpu_to_be32(binfo->loader_start >> 32);
-    if (acells > 1) {
-        mem_reg_property[acells - 2] = hival;
-    } else if (hival != 0) {
-        fprintf(stderr, "qemu: dtb file not compatible with "
-                "RAM start address > 4GB\n");
-        exit(1);
-    }
-    mem_reg_property[acells + scells - 1] = cpu_to_be32(binfo->ram_size);
-    hival = cpu_to_be32(binfo->ram_size >> 32);
-    if (scells > 1) {
-        mem_reg_property[acells + scells - 2] = hival;
-    } else if (hival != 0) {
-        fprintf(stderr, "qemu: dtb file not compatible with "
-                "RAM size > 4GB\n");
-        exit(1);
-    }
-
-    rc = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
-                              mem_reg_propsize * sizeof(uint32_t));
-    if (rc < 0) {
-        fprintf(stderr, "couldn't set /memory/reg\n");
-    }
-
-    if (binfo->kernel_cmdline && *binfo->kernel_cmdline) {
-        rc = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
-                                          binfo->kernel_cmdline);
-        if (rc < 0) {
-            fprintf(stderr, "couldn't set /chosen/bootargs\n");
-        }
-    }
-
-    if (binfo->initrd_size) {
-        rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
-                binfo->initrd_start);
-        if (rc < 0) {
-            fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
-        }
-
-        rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
-                    binfo->initrd_start + binfo->initrd_size);
-        if (rc < 0) {
-            fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
-        }
-    }
-
-    cpu_physical_memory_write(addr, fdt, size);
-
-    return 0;
-
-#else
-    fprintf(stderr, "Device tree requested, "
-                "but qemu was compiled without fdt support\n");
-    return -1;
-#endif
-}
-
-static void do_cpu_reset(void *opaque)
-{
-    ARMCPU *cpu = opaque;
-    CPUARMState *env = &cpu->env;
-    const struct arm_boot_info *info = env->boot_info;
-
-    cpu_reset(CPU(cpu));
-    if (info) {
-        if (!info->is_linux) {
-            /* Jump to the entry point.  */
-            env->regs[15] = info->entry & 0xfffffffe;
-            env->thumb = info->entry & 1;
-        } else {
-            if (env == first_cpu) {
-                env->regs[15] = info->loader_start;
-                if (!info->dtb_filename) {
-                    if (old_param) {
-                        set_kernel_args_old(info);
-                    } else {
-                        set_kernel_args(info);
-                    }
-                }
-            } else {
-                info->secondary_cpu_reset_hook(cpu, info);
-            }
-        }
-    }
-}
-
-void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
-{
-    CPUARMState *env = &cpu->env;
-    int kernel_size;
-    int initrd_size;
-    int n;
-    int is_linux = 0;
-    uint64_t elf_entry;
-    hwaddr entry;
-    int big_endian;
-    QemuOpts *machine_opts;
-
-    /* Load the kernel.  */
-    if (!info->kernel_filename) {
-        fprintf(stderr, "Kernel image must be specified\n");
-        exit(1);
-    }
-
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        info->dtb_filename = qemu_opt_get(machine_opts, "dtb");
-    } else {
-        info->dtb_filename = NULL;
-    }
-
-    if (!info->secondary_cpu_reset_hook) {
-        info->secondary_cpu_reset_hook = default_reset_secondary;
-    }
-    if (!info->write_secondary_boot) {
-        info->write_secondary_boot = default_write_secondary;
-    }
-
-    if (info->nb_cpus == 0)
-        info->nb_cpus = 1;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    big_endian = 1;
-#else
-    big_endian = 0;
-#endif
-
-    /* We want to put the initrd far enough into RAM that when the
-     * kernel is uncompressed it will not clobber the initrd. However
-     * on boards without much RAM we must ensure that we still leave
-     * enough room for a decent sized initrd, and on boards with large
-     * amounts of RAM we must avoid the initrd being so far up in RAM
-     * that it is outside lowmem and inaccessible to the kernel.
-     * So for boards with less  than 256MB of RAM we put the initrd
-     * halfway into RAM, and for boards with 256MB of RAM or more we put
-     * the initrd at 128MB.
-     */
-    info->initrd_start = info->loader_start +
-        MIN(info->ram_size / 2, 128 * 1024 * 1024);
-
-    /* Assume that raw images are linux kernels, and ELF images are not.  */
-    kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
-                           NULL, NULL, big_endian, ELF_MACHINE, 1);
-    entry = elf_entry;
-    if (kernel_size < 0) {
-        kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
-                                  &is_linux);
-    }
-    if (kernel_size < 0) {
-        entry = info->loader_start + KERNEL_LOAD_ADDR;
-        kernel_size = load_image_targphys(info->kernel_filename, entry,
-                                          info->ram_size - KERNEL_LOAD_ADDR);
-        is_linux = 1;
-    }
-    if (kernel_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                info->kernel_filename);
-        exit(1);
-    }
-    info->entry = entry;
-    if (is_linux) {
-        if (info->initrd_filename) {
-            initrd_size = load_image_targphys(info->initrd_filename,
-                                              info->initrd_start,
-                                              info->ram_size -
-                                              info->initrd_start);
-            if (initrd_size < 0) {
-                fprintf(stderr, "qemu: could not load initrd '%s'\n",
-                        info->initrd_filename);
-                exit(1);
-            }
-        } else {
-            initrd_size = 0;
-        }
-        info->initrd_size = initrd_size;
-
-        bootloader[4] = info->board_id;
-
-        /* for device tree boot, we pass the DTB directly in r2. Otherwise
-         * we point to the kernel args.
-         */
-        if (info->dtb_filename) {
-            /* Place the DTB after the initrd in memory. Note that some
-             * kernels will trash anything in the 4K page the initrd
-             * ends in, so make sure the DTB isn't caught up in that.
-             */
-            hwaddr dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size,
-                                             4096);
-            if (load_dtb(dtb_start, info)) {
-                exit(1);
-            }
-            bootloader[5] = dtb_start;
-        } else {
-            bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
-            if (info->ram_size >= (1ULL << 32)) {
-                fprintf(stderr, "qemu: RAM size must be less than 4GB to boot"
-                        " Linux kernel using ATAGS (try passing a device tree"
-                        " using -dtb)\n");
-                exit(1);
-            }
-        }
-        bootloader[6] = entry;
-        for (n = 0; n < sizeof(bootloader) / 4; n++) {
-            bootloader[n] = tswap32(bootloader[n]);
-        }
-        rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
-                           info->loader_start);
-        if (info->nb_cpus > 1) {
-            info->write_secondary_boot(cpu, info);
-        }
-    }
-    info->is_linux = is_linux;
-
-    for (; env; env = env->next_cpu) {
-        cpu = arm_env_get_cpu(env);
-        env->boot_info = info;
-        qemu_register_reset(do_cpu_reset, cpu);
-    }
-}
index 250e720d18efa13e39fed09c97e104dd4337c9d6..bcb072bbcfef064d796e7d32290b9f8f62be25c8 100644 (file)
@@ -18,8 +18,8 @@
  *  armv7m_nvic device.
  */
 
-#include "sysbus.h"
-#include "arm_gic_internal.h"
+#include "hw/sysbus.h"
+#include "hw/arm_gic_internal.h"
 
 //#define DEBUG_GIC
 
index 20da9d2b184572b852b5868b6538c49f09cd30e3..f2dc8bf555a00246a75cb638550386fb822c86a4 100644 (file)
@@ -18,7 +18,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "arm_gic_internal.h"
+#include "hw/arm_gic_internal.h"
 
 static void gic_save(QEMUFile *f, void *opaque)
 {
index 3ba37f30f53fe4d585e40018bc220852b181b6a6..3e1928b7ebe3e4af5558b3e42838365c0cf79788 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef QEMU_ARM_GIC_INTERNAL_H
 #define QEMU_ARM_GIC_INTERNAL_H
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* Maximum number of possible interrupts, determined by the GIC architecture */
 #define GIC_MAXIRQ 1020
index ae1e51d00939790b7145622f48d9eb8408962560..eb4427d9c4937f1857e882393997355fa9e1cc8d 100644 (file)
@@ -18,7 +18,7 @@
  *
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* L2C-310 r3p2 */
 #define CACHE_ID 0x410000c8
index 7b08aa3644bdf73817fd3fb97634a894e0957fa4..f59a9f11f083bf19e37a55c490c70ea10c33a757 100644 (file)
@@ -19,7 +19,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 
 /* This device implements the per-cpu private timer and watchdog block
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
deleted file mode 100644 (file)
index 394bc93..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Generic ARM Programmable Interrupt Controller support.
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the LGPL
- */
-
-#include "hw.h"
-#include "arm-misc.h"
-#include "sysemu/kvm.h"
-
-/* Input 0 is IRQ and input 1 is FIQ.  */
-static void arm_pic_cpu_handler(void *opaque, int irq, int level)
-{
-    ARMCPU *cpu = opaque;
-    CPUARMState *env = &cpu->env;
-
-    switch (irq) {
-    case ARM_PIC_CPU_IRQ:
-        if (level)
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-        break;
-    case ARM_PIC_CPU_FIQ:
-        if (level)
-            cpu_interrupt(env, CPU_INTERRUPT_FIQ);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
-        break;
-    default:
-        hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
-    }
-}
-
-static void kvm_arm_pic_cpu_handler(void *opaque, int irq, int level)
-{
-#ifdef CONFIG_KVM
-    ARMCPU *cpu = opaque;
-    CPUState *cs = CPU(cpu);
-    int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
-
-    switch (irq) {
-    case ARM_PIC_CPU_IRQ:
-        kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
-        break;
-    case ARM_PIC_CPU_FIQ:
-        kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
-        break;
-    default:
-        hw_error("kvm_arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
-    }
-    kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
-    kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
-#endif
-}
-
-qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
-{
-    if (kvm_enabled()) {
-        return qemu_allocate_irqs(kvm_arm_pic_cpu_handler, cpu, 2);
-    }
-    return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
-}
index 7ecb7da54b1e28ad9b59127e1e7f326534476e30..a46f8d450eeb081d479df26c550e5bde33206aa6 100644 (file)
@@ -7,10 +7,10 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "sysbus.h"
-#include "primecell.h"
+#include "hw/sysbus.h"
+#include "hw/primecell.h"
 #include "sysemu/sysemu.h"
 
 #define LOCK_VALUE 0xa05f
index c1e56be74e5cb8cef695f79d0088616ca06068c1..644987046aabf72e325200f9ee5e664afd26a0da 100644 (file)
@@ -7,11 +7,11 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
-#include "qdev.h"
-#include "ptimer.h"
+#include "hw/qdev.h"
+#include "hw/ptimer.h"
 
 /* Common timer implementation.  */
 
diff --git a/hw/armv7m.c b/hw/armv7m.c
deleted file mode 100644 (file)
index 904696c..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * ARMV7M System emulation.
- *
- * Copyright (c) 2006-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "loader.h"
-#include "elf.h"
-
-/* Bitbanded IO.  Each word corresponds to a single bit.  */
-
-/* Get the byte address of the real memory for a bitband access.  */
-static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
-{
-    uint32_t res;
-
-    res = *(uint32_t *)opaque;
-    res |= (addr & 0x1ffffff) >> 5;
-    return res;
-
-}
-
-static uint32_t bitband_readb(void *opaque, hwaddr offset)
-{
-    uint8_t v;
-    cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
-    return (v & (1 << ((offset >> 2) & 7))) != 0;
-}
-
-static void bitband_writeb(void *opaque, hwaddr offset,
-                           uint32_t value)
-{
-    uint32_t addr;
-    uint8_t mask;
-    uint8_t v;
-    addr = bitband_addr(opaque, offset);
-    mask = (1 << ((offset >> 2) & 7));
-    cpu_physical_memory_read(addr, &v, 1);
-    if (value & 1)
-        v |= mask;
-    else
-        v &= ~mask;
-    cpu_physical_memory_write(addr, &v, 1);
-}
-
-static uint32_t bitband_readw(void *opaque, hwaddr offset)
-{
-    uint32_t addr;
-    uint16_t mask;
-    uint16_t v;
-    addr = bitband_addr(opaque, offset) & ~1;
-    mask = (1 << ((offset >> 2) & 15));
-    mask = tswap16(mask);
-    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
-    return (v & mask) != 0;
-}
-
-static void bitband_writew(void *opaque, hwaddr offset,
-                           uint32_t value)
-{
-    uint32_t addr;
-    uint16_t mask;
-    uint16_t v;
-    addr = bitband_addr(opaque, offset) & ~1;
-    mask = (1 << ((offset >> 2) & 15));
-    mask = tswap16(mask);
-    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
-    if (value & 1)
-        v |= mask;
-    else
-        v &= ~mask;
-    cpu_physical_memory_write(addr, (uint8_t *)&v, 2);
-}
-
-static uint32_t bitband_readl(void *opaque, hwaddr offset)
-{
-    uint32_t addr;
-    uint32_t mask;
-    uint32_t v;
-    addr = bitband_addr(opaque, offset) & ~3;
-    mask = (1 << ((offset >> 2) & 31));
-    mask = tswap32(mask);
-    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
-    return (v & mask) != 0;
-}
-
-static void bitband_writel(void *opaque, hwaddr offset,
-                           uint32_t value)
-{
-    uint32_t addr;
-    uint32_t mask;
-    uint32_t v;
-    addr = bitband_addr(opaque, offset) & ~3;
-    mask = (1 << ((offset >> 2) & 31));
-    mask = tswap32(mask);
-    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
-    if (value & 1)
-        v |= mask;
-    else
-        v &= ~mask;
-    cpu_physical_memory_write(addr, (uint8_t *)&v, 4);
-}
-
-static const MemoryRegionOps bitband_ops = {
-    .old_mmio = {
-        .read = { bitband_readb, bitband_readw, bitband_readl, },
-        .write = { bitband_writeb, bitband_writew, bitband_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t base;
-} BitBandState;
-
-static int bitband_init(SysBusDevice *dev)
-{
-    BitBandState *s = FROM_SYSBUS(BitBandState, dev);
-
-    memory_region_init_io(&s->iomem, &bitband_ops, &s->base, "bitband",
-                          0x02000000);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-static void armv7m_bitband_init(void)
-{
-    DeviceState *dev;
-
-    dev = qdev_create(NULL, "ARM,bitband-memory");
-    qdev_prop_set_uint32(dev, "base", 0x20000000);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
-
-    dev = qdev_create(NULL, "ARM,bitband-memory");
-    qdev_prop_set_uint32(dev, "base", 0x40000000);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
-}
-
-/* Board init.  */
-
-static void armv7m_reset(void *opaque)
-{
-    ARMCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-/* Init CPU and memory for a v7-M based board.
-   flash_size and sram_size are in kb.
-   Returns the NVIC array.  */
-
-qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
-                      int flash_size, int sram_size,
-                      const char *kernel_filename, const char *cpu_model)
-{
-    ARMCPU *cpu;
-    CPUARMState *env;
-    DeviceState *nvic;
-    /* FIXME: make this local state.  */
-    static qemu_irq pic[64];
-    qemu_irq *cpu_pic;
-    int image_size;
-    uint64_t entry;
-    uint64_t lowaddr;
-    int i;
-    int big_endian;
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    MemoryRegion *flash = g_new(MemoryRegion, 1);
-    MemoryRegion *hack = g_new(MemoryRegion, 1);
-
-    flash_size *= 1024;
-    sram_size *= 1024;
-
-    if (cpu_model == NULL) {
-       cpu_model = "cortex-m3";
-    }
-    cpu = cpu_arm_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-#if 0
-    /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
-       We don't have proper commandline options, so allocate half of memory
-       as SRAM, up to a maximum of 32Mb, and the rest as code.  */
-    if (ram_size > (512 + 32) * 1024 * 1024)
-        ram_size = (512 + 32) * 1024 * 1024;
-    sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
-    if (sram_size > 32 * 1024 * 1024)
-        sram_size = 32 * 1024 * 1024;
-    code_size = ram_size - sram_size;
-#endif
-
-    /* Flash programming is done via the SCU, so pretend it is ROM.  */
-    memory_region_init_ram(flash, "armv7m.flash", flash_size);
-    vmstate_register_ram_global(flash);
-    memory_region_set_readonly(flash, true);
-    memory_region_add_subregion(address_space_mem, 0, flash);
-    memory_region_init_ram(sram, "armv7m.sram", sram_size);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(address_space_mem, 0x20000000, sram);
-    armv7m_bitband_init();
-
-    nvic = qdev_create(NULL, "armv7m_nvic");
-    env->nvic = nvic;
-    qdev_init_nofail(nvic);
-    cpu_pic = arm_pic_init_cpu(cpu);
-    sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
-    for (i = 0; i < 64; i++) {
-        pic[i] = qdev_get_gpio_in(nvic, i);
-    }
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    big_endian = 1;
-#else
-    big_endian = 0;
-#endif
-
-    if (!kernel_filename) {
-        fprintf(stderr, "Guest image must be specified (using -kernel)\n");
-        exit(1);
-    }
-
-    image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
-                          NULL, big_endian, ELF_MACHINE, 1);
-    if (image_size < 0) {
-        image_size = load_image_targphys(kernel_filename, 0, flash_size);
-       lowaddr = 0;
-    }
-    if (image_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                kernel_filename);
-        exit(1);
-    }
-
-    /* Hack to map an additional page of ram at the top of the address
-       space.  This stops qemu complaining about executing code outside RAM
-       when returning from an exception.  */
-    memory_region_init_ram(hack, "armv7m.hack", 0x1000);
-    vmstate_register_ram_global(hack);
-    memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
-
-    qemu_register_reset(armv7m_reset, cpu);
-    return pic;
-}
-
-static Property bitband_properties[] = {
-    DEFINE_PROP_UINT32("base", BitBandState, base, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void bitband_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = bitband_init;
-    dc->props = bitband_properties;
-}
-
-static const TypeInfo bitband_info = {
-    .name          = "ARM,bitband-memory",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(BitBandState),
-    .class_init    = bitband_class_init,
-};
-
-static void armv7m_register_types(void)
-{
-    type_register_static(&bitband_info);
-}
-
-type_init(armv7m_register_types)
index 3c7967464ae07ffc5fe36ebc23c5d88e72af0abe..d198cfd96e5177b28b85b0d46d635a918aa93099 100644 (file)
  * NVIC.  Much of that is also implemented here.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
-#include "arm-misc.h"
+#include "hw/arm-misc.h"
 #include "exec/address-spaces.h"
-#include "arm_gic_internal.h"
+#include "hw/arm_gic_internal.h"
 
 typedef struct {
     GICState gic;
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
deleted file mode 100644 (file)
index dd37fa1..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * QEMU model for the AXIS devboard 88.
- *
- * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "net/net.h"
-#include "flash.h"
-#include "boards.h"
-#include "etraxfs.h"
-#include "loader.h"
-#include "elf.h"
-#include "cris-boot.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define D(x)
-#define DNAND(x)
-
-struct nand_state_t
-{
-    DeviceState *nand;
-    MemoryRegion iomem;
-    unsigned int rdy:1;
-    unsigned int ale:1;
-    unsigned int cle:1;
-    unsigned int ce:1;
-};
-
-static struct nand_state_t nand_state;
-static uint64_t nand_read(void *opaque, hwaddr addr, unsigned size)
-{
-    struct nand_state_t *s = opaque;
-    uint32_t r;
-    int rdy;
-
-    r = nand_getio(s->nand);
-    nand_getpins(s->nand, &rdy);
-    s->rdy = rdy;
-
-    DNAND(printf("%s addr=%x r=%x\n", __func__, addr, r));
-    return r;
-}
-
-static void
-nand_write(void *opaque, hwaddr addr, uint64_t value,
-           unsigned size)
-{
-    struct nand_state_t *s = opaque;
-    int rdy;
-
-    DNAND(printf("%s addr=%x v=%x\n", __func__, addr, (unsigned)value));
-    nand_setpins(s->nand, s->cle, s->ale, s->ce, 1, 0);
-    nand_setio(s->nand, value);
-    nand_getpins(s->nand, &rdy);
-    s->rdy = rdy;
-}
-
-static const MemoryRegionOps nand_ops = {
-    .read = nand_read,
-    .write = nand_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-struct tempsensor_t
-{
-    unsigned int shiftreg;
-    unsigned int count;
-    enum {
-        ST_OUT, ST_IN, ST_Z
-    } state;
-
-    uint16_t regs[3];
-};
-
-static void tempsensor_clkedge(struct tempsensor_t *s,
-                               unsigned int clk, unsigned int data_in)
-{
-    D(printf("%s clk=%d state=%d sr=%x\n", __func__,
-             clk, s->state, s->shiftreg));
-    if (s->count == 0) {
-        s->count = 16;
-        s->state = ST_OUT;
-    }
-    switch (s->state) {
-        case ST_OUT:
-            /* Output reg is clocked at negedge.  */
-            if (!clk) {
-                s->count--;
-                s->shiftreg <<= 1;
-                if (s->count == 0) {
-                    s->shiftreg = 0;
-                    s->state = ST_IN;
-                    s->count = 16;
-                }
-            }
-            break;
-        case ST_Z:
-            if (clk) {
-                s->count--;
-                if (s->count == 0) {
-                    s->shiftreg = 0;
-                    s->state = ST_OUT;
-                    s->count = 16;
-                }
-            }
-            break;
-        case ST_IN:
-            /* Indata is sampled at posedge.  */
-            if (clk) {
-                s->count--;
-                s->shiftreg <<= 1;
-                s->shiftreg |= data_in & 1;
-                if (s->count == 0) {
-                    D(printf("%s cfgreg=%x\n", __func__, s->shiftreg));
-                    s->regs[0] = s->shiftreg;
-                    s->state = ST_OUT;
-                    s->count = 16;
-
-                    if ((s->regs[0] & 0xff) == 0) {
-                        /* 25 degrees celcius.  */
-                        s->shiftreg = 0x0b9f;
-                    } else if ((s->regs[0] & 0xff) == 0xff) {
-                        /* Sensor ID, 0x8100 LM70.  */
-                        s->shiftreg = 0x8100;
-                    } else
-                        printf("Invalid tempsens state %x\n", s->regs[0]);
-                }
-            }
-            break;
-    }
-}
-
-
-#define RW_PA_DOUT    0x00
-#define R_PA_DIN      0x01
-#define RW_PA_OE      0x02
-#define RW_PD_DOUT    0x10
-#define R_PD_DIN      0x11
-#define RW_PD_OE      0x12
-
-static struct gpio_state_t
-{
-    MemoryRegion iomem;
-    struct nand_state_t *nand;
-    struct tempsensor_t tempsensor;
-    uint32_t regs[0x5c / 4];
-} gpio_state;
-
-static uint64_t gpio_read(void *opaque, hwaddr addr, unsigned size)
-{
-    struct gpio_state_t *s = opaque;
-    uint32_t r = 0;
-
-    addr >>= 2;
-    switch (addr)
-    {
-        case R_PA_DIN:
-            r = s->regs[RW_PA_DOUT] & s->regs[RW_PA_OE];
-
-            /* Encode pins from the nand.  */
-            r |= s->nand->rdy << 7;
-            break;
-        case R_PD_DIN:
-            r = s->regs[RW_PD_DOUT] & s->regs[RW_PD_OE];
-
-            /* Encode temp sensor pins.  */
-            r |= (!!(s->tempsensor.shiftreg & 0x10000)) << 4;
-            break;
-
-        default:
-            r = s->regs[addr];
-            break;
-    }
-    return r;
-    D(printf("%s %x=%x\n", __func__, addr, r));
-}
-
-static void gpio_write(void *opaque, hwaddr addr, uint64_t value,
-                       unsigned size)
-{
-    struct gpio_state_t *s = opaque;
-    D(printf("%s %x=%x\n", __func__, addr, (unsigned)value));
-
-    addr >>= 2;
-    switch (addr)
-    {
-        case RW_PA_DOUT:
-            /* Decode nand pins.  */
-            s->nand->ale = !!(value & (1 << 6));
-            s->nand->cle = !!(value & (1 << 5));
-            s->nand->ce  = !!(value & (1 << 4));
-
-            s->regs[addr] = value;
-            break;
-
-        case RW_PD_DOUT:
-            /* Temp sensor clk.  */
-            if ((s->regs[addr] ^ value) & 2)
-                tempsensor_clkedge(&s->tempsensor, !!(value & 2),
-                                   !!(value & 16));
-            s->regs[addr] = value;
-            break;
-
-        default:
-            s->regs[addr] = value;
-            break;
-    }
-}
-
-static const MemoryRegionOps gpio_ops = {
-    .read = gpio_read,
-    .write = gpio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-#define INTMEM_SIZE (128 * 1024)
-
-static struct cris_load_info li;
-
-static
-void axisdev88_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    CRISCPU *cpu;
-    CPUCRISState *env;
-    DeviceState *dev;
-    SysBusDevice *s;
-    DriveInfo *nand;
-    qemu_irq irq[30], nmi[2], *cpu_irq;
-    void *etraxfs_dmac;
-    struct etraxfs_dma_client *dma_eth;
-    int i;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    MemoryRegion *phys_intmem = g_new(MemoryRegion, 1);
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = "crisv32";
-    }
-    cpu = cpu_cris_init(cpu_model);
-    env = &cpu->env;
-
-    /* allocate RAM */
-    memory_region_init_ram(phys_ram, "axisdev88.ram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram);
-
-    /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
-       internal memory.  */
-    memory_region_init_ram(phys_intmem, "axisdev88.chipram", INTMEM_SIZE);
-    vmstate_register_ram_global(phys_intmem);
-    memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem);
-
-      /* Attach a NAND flash to CS1.  */
-    nand = drive_get(IF_MTD, 0, 0);
-    nand_state.nand = nand_init(nand ? nand->bdrv : NULL,
-                                NAND_MFR_STMICRO, 0x39);
-    memory_region_init_io(&nand_state.iomem, &nand_ops, &nand_state,
-                          "nand", 0x05000000);
-    memory_region_add_subregion(address_space_mem, 0x10000000,
-                                &nand_state.iomem);
-
-    gpio_state.nand = &nand_state;
-    memory_region_init_io(&gpio_state.iomem, &gpio_ops, &gpio_state,
-                          "gpio", 0x5c);
-    memory_region_add_subregion(address_space_mem, 0x3001a000,
-                                &gpio_state.iomem);
-
-
-    cpu_irq = cris_pic_init_cpu(env);
-    dev = qdev_create(NULL, "etraxfs,pic");
-    /* FIXME: Is there a proper way to signal vectors to the CPU core?  */
-    qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(s, 0, 0x3001c000);
-    sysbus_connect_irq(s, 0, cpu_irq[0]);
-    sysbus_connect_irq(s, 1, cpu_irq[1]);
-    for (i = 0; i < 30; i++) {
-        irq[i] = qdev_get_gpio_in(dev, i);
-    }
-    nmi[0] = qdev_get_gpio_in(dev, 30);
-    nmi[1] = qdev_get_gpio_in(dev, 31);
-
-    etraxfs_dmac = etraxfs_dmac_init(0x30000000, 10);
-    for (i = 0; i < 10; i++) {
-        /* On ETRAX, odd numbered channels are inputs.  */
-        etraxfs_dmac_connect(etraxfs_dmac, i, irq + 7 + i, i & 1);
-    }
-
-    /* Add the two ethernet blocks.  */
-    dma_eth = g_malloc0(sizeof dma_eth[0] * 4); /* Allocate 4 channels.  */
-    etraxfs_eth_init(&nd_table[0], 0x30034000, 1, &dma_eth[0], &dma_eth[1]);
-    if (nb_nics > 1) {
-        etraxfs_eth_init(&nd_table[1], 0x30036000, 2, &dma_eth[2], &dma_eth[3]);
-    }
-
-    /* The DMA Connector block is missing, hardwire things for now.  */
-    etraxfs_dmac_connect_client(etraxfs_dmac, 0, &dma_eth[0]);
-    etraxfs_dmac_connect_client(etraxfs_dmac, 1, &dma_eth[1]);
-    if (nb_nics > 1) {
-        etraxfs_dmac_connect_client(etraxfs_dmac, 6, &dma_eth[2]);
-        etraxfs_dmac_connect_client(etraxfs_dmac, 7, &dma_eth[3]);
-    }
-
-    /* 2 timers.  */
-    sysbus_create_varargs("etraxfs,timer", 0x3001e000, irq[0x1b], nmi[1], NULL);
-    sysbus_create_varargs("etraxfs,timer", 0x3005e000, irq[0x1b], nmi[1], NULL);
-
-    for (i = 0; i < 4; i++) {
-        sysbus_create_simple("etraxfs,serial", 0x30026000 + i * 0x2000,
-                             irq[0x14 + i]);
-    }
-
-    if (!kernel_filename) {
-        fprintf(stderr, "Kernel image must be specified\n");
-        exit(1);
-    }
-
-    li.image_filename = kernel_filename;
-    li.cmdline = kernel_cmdline;
-    cris_load_image(cpu, &li);
-}
-
-static QEMUMachine axisdev88_machine = {
-    .name = "axis-dev88",
-    .desc = "AXIS devboard 88",
-    .init = axisdev88_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void axisdev88_machine_init(void)
-{
-    qemu_register_machine(&axisdev88_machine);
-}
-
-machine_init(axisdev88_machine_init);
diff --git a/hw/baum.c b/hw/baum.c
deleted file mode 100644 (file)
index d75b150..0000000
--- a/hw/baum.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * QEMU Baum Braille Device
- *
- * Copyright (c) 2008 Samuel Thibault
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "qemu-common.h"
-#include "char/char.h"
-#include "qemu/timer.h"
-#include "usb.h"
-#include "baum.h"
-#include <brlapi.h>
-#include <brlapi_constants.h>
-#include <brlapi_keycodes.h>
-#ifdef CONFIG_SDL
-#include <SDL_syswm.h>
-#endif
-
-#if 0
-#define DPRINTF(fmt, ...) \
-        printf(fmt, ## __VA_ARGS__)
-#else
-#define DPRINTF(fmt, ...)
-#endif
-
-#define ESC 0x1B
-
-#define BAUM_REQ_DisplayData           0x01
-#define BAUM_REQ_GetVersionNumber      0x05
-#define BAUM_REQ_GetKeys               0x08
-#define BAUM_REQ_SetMode               0x12
-#define BAUM_REQ_SetProtocol           0x15
-#define BAUM_REQ_GetDeviceIdentity     0x84
-#define BAUM_REQ_GetSerialNumber       0x8A
-
-#define BAUM_RSP_CellCount             0x01
-#define BAUM_RSP_VersionNumber         0x05
-#define BAUM_RSP_ModeSetting           0x11
-#define BAUM_RSP_CommunicationChannel  0x16
-#define BAUM_RSP_PowerdownSignal       0x17
-#define BAUM_RSP_HorizontalSensors     0x20
-#define BAUM_RSP_VerticalSensors       0x21
-#define BAUM_RSP_RoutingKeys           0x22
-#define BAUM_RSP_Switches              0x23
-#define BAUM_RSP_TopKeys               0x24
-#define BAUM_RSP_HorizontalSensor      0x25
-#define BAUM_RSP_VerticalSensor                0x26
-#define BAUM_RSP_RoutingKey            0x27
-#define BAUM_RSP_FrontKeys6            0x28
-#define BAUM_RSP_BackKeys6             0x29
-#define BAUM_RSP_CommandKeys           0x2B
-#define BAUM_RSP_FrontKeys10           0x2C
-#define BAUM_RSP_BackKeys10            0x2D
-#define BAUM_RSP_EntryKeys             0x33
-#define BAUM_RSP_JoyStick              0x34
-#define BAUM_RSP_ErrorCode             0x40
-#define BAUM_RSP_InfoBlock             0x42
-#define BAUM_RSP_DeviceIdentity                0x84
-#define BAUM_RSP_SerialNumber          0x8A
-#define BAUM_RSP_BluetoothName         0x8C
-
-#define BAUM_TL1 0x01
-#define BAUM_TL2 0x02
-#define BAUM_TL3 0x04
-#define BAUM_TR1 0x08
-#define BAUM_TR2 0x10
-#define BAUM_TR3 0x20
-
-#define BUF_SIZE 256
-
-typedef struct {
-    CharDriverState *chr;
-
-    brlapi_handle_t *brlapi;
-    int brlapi_fd;
-    unsigned int x, y;
-
-    uint8_t in_buf[BUF_SIZE];
-    uint8_t in_buf_used;
-    uint8_t out_buf[BUF_SIZE];
-    uint8_t out_buf_used, out_buf_ptr;
-
-    QEMUTimer *cellCount_timer;
-} BaumDriverState;
-
-/* Let's assume NABCC by default */
-static const uint8_t nabcc_translation[256] = {
-    [0] = ' ',
-#ifndef BRLAPI_DOTS
-#define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \
-    ((d1?BRLAPI_DOT1:0)|\
-     (d2?BRLAPI_DOT2:0)|\
-     (d3?BRLAPI_DOT3:0)|\
-     (d4?BRLAPI_DOT4:0)|\
-     (d5?BRLAPI_DOT5:0)|\
-     (d6?BRLAPI_DOT6:0)|\
-     (d7?BRLAPI_DOT7:0)|\
-     (d8?BRLAPI_DOT8:0))
-#endif
-    [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a',
-    [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b',
-    [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c',
-    [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd',
-    [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e',
-    [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f',
-    [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g',
-    [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h',
-    [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i',
-    [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j',
-    [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k',
-    [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l',
-    [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm',
-    [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n',
-    [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o',
-    [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p',
-    [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q',
-    [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r',
-    [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's',
-    [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't',
-    [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u',
-    [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v',
-    [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w',
-    [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x',
-    [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y',
-    [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z',
-
-    [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A',
-    [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B',
-    [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C',
-    [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D',
-    [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E',
-    [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F',
-    [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G',
-    [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H',
-    [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I',
-    [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J',
-    [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K',
-    [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L',
-    [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M',
-    [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N',
-    [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O',
-    [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P',
-    [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q',
-    [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R',
-    [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S',
-    [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T',
-    [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U',
-    [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V',
-    [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W',
-    [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X',
-    [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y',
-    [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z',
-
-    [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0',
-    [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1',
-    [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2',
-    [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3',
-    [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4',
-    [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5',
-    [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6',
-    [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7',
-    [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8',
-    [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9',
-
-    [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.',
-    [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+',
-    [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-',
-    [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*',
-    [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/',
-    [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(',
-    [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')',
-
-    [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&',
-    [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#',
-
-    [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',',
-    [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';',
-    [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':',
-    [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!',
-    [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?',
-    [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"',
-    [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'',
-    [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`',
-    [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^',
-    [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~',
-    [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[',
-    [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']',
-    [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{',
-    [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}',
-    [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=',
-    [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<',
-    [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>',
-    [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$',
-    [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%',
-    [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@',
-    [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|',
-    [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\',
-    [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_',
-};
-
-/* The serial port can receive more of our data */
-static void baum_accept_input(struct CharDriverState *chr)
-{
-    BaumDriverState *baum = chr->opaque;
-    int room, first;
-
-    if (!baum->out_buf_used)
-        return;
-    room = qemu_chr_be_can_write(chr);
-    if (!room)
-        return;
-    if (room > baum->out_buf_used)
-        room = baum->out_buf_used;
-
-    first = BUF_SIZE - baum->out_buf_ptr;
-    if (room > first) {
-        qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, first);
-        baum->out_buf_ptr = 0;
-        baum->out_buf_used -= first;
-        room -= first;
-    }
-    qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, room);
-    baum->out_buf_ptr += room;
-    baum->out_buf_used -= room;
-}
-
-/* We want to send a packet */
-static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len)
-{
-    uint8_t io_buf[1 + 2 * len], *cur = io_buf;
-    int room;
-    *cur++ = ESC;
-    while (len--)
-        if ((*cur++ = *buf++) == ESC)
-            *cur++ = ESC;
-    room = qemu_chr_be_can_write(baum->chr);
-    len = cur - io_buf;
-    if (len <= room) {
-        /* Fits */
-        qemu_chr_be_write(baum->chr, io_buf, len);
-    } else {
-        int first;
-        uint8_t out;
-        /* Can't fit all, send what can be, and store the rest. */
-        qemu_chr_be_write(baum->chr, io_buf, room);
-        len -= room;
-        cur = io_buf + room;
-        if (len > BUF_SIZE - baum->out_buf_used) {
-            /* Can't even store it, drop the previous data... */
-            assert(len <= BUF_SIZE);
-            baum->out_buf_used = 0;
-            baum->out_buf_ptr = 0;
-        }
-        out = baum->out_buf_ptr;
-        baum->out_buf_used += len;
-        first = BUF_SIZE - baum->out_buf_ptr;
-        if (len > first) {
-            memcpy(baum->out_buf + out, cur, first);
-            out = 0;
-            len -= first;
-            cur += first;
-        }
-        memcpy(baum->out_buf + out, cur, len);
-    }
-}
-
-/* Called when the other end seems to have a wrong idea of our display size */
-static void baum_cellCount_timer_cb(void *opaque)
-{
-    BaumDriverState *baum = opaque;
-    uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y };
-    DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
-    baum_write_packet(baum, cell_count, sizeof(cell_count));
-}
-
-/* Try to interpret a whole incoming packet */
-static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
-{
-    const uint8_t *cur = buf;
-    uint8_t req = 0;
-
-    if (!len--)
-        return 0;
-    if (*cur++ != ESC) {
-        while (*cur != ESC) {
-            if (!len--)
-                return 0;
-            cur++;
-        }
-        DPRINTF("Dropped %d bytes!\n", cur - buf);
-    }
-
-#define EAT(c) do {\
-    if (!len--) \
-        return 0; \
-    if ((c = *cur++) == ESC) { \
-        if (!len--) \
-            return 0; \
-        if (*cur++ != ESC) { \
-            DPRINTF("Broken packet %#2x, tossing\n", req); \
-               if (qemu_timer_pending(baum->cellCount_timer)) { \
-                qemu_del_timer(baum->cellCount_timer); \
-                baum_cellCount_timer_cb(baum); \
-            } \
-            return (cur - 2 - buf); \
-        } \
-    } \
-} while (0)
-
-    EAT(req);
-    switch (req) {
-    case BAUM_REQ_DisplayData:
-    {
-        uint8_t cells[baum->x * baum->y], c;
-        uint8_t text[baum->x * baum->y];
-        uint8_t zero[baum->x * baum->y];
-        int cursor = BRLAPI_CURSOR_OFF;
-        int i;
-
-        /* Allow 100ms to complete the DisplayData packet */
-        qemu_mod_timer(baum->cellCount_timer, qemu_get_clock_ns(vm_clock) +
-                       get_ticks_per_sec() / 10);
-        for (i = 0; i < baum->x * baum->y ; i++) {
-            EAT(c);
-            cells[i] = c;
-            if ((c & (BRLAPI_DOT7|BRLAPI_DOT8))
-                    == (BRLAPI_DOT7|BRLAPI_DOT8)) {
-                cursor = i + 1;
-                c &= ~(BRLAPI_DOT7|BRLAPI_DOT8);
-            }
-            if (!(c = nabcc_translation[c]))
-                c = '?';
-            text[i] = c;
-        }
-        qemu_del_timer(baum->cellCount_timer);
-
-        memset(zero, 0, sizeof(zero));
-
-        brlapi_writeArguments_t wa = {
-            .displayNumber = BRLAPI_DISPLAY_DEFAULT,
-            .regionBegin = 1,
-            .regionSize = baum->x * baum->y,
-            .text = (char *)text,
-            .textSize = baum->x * baum->y,
-            .andMask = zero,
-            .orMask = cells,
-            .cursor = cursor,
-            .charset = (char *)"ISO-8859-1",
-        };
-
-        if (brlapi__write(baum->brlapi, &wa) == -1)
-            brlapi_perror("baum brlapi_write");
-        break;
-    }
-    case BAUM_REQ_SetMode:
-    {
-        uint8_t mode, setting;
-        DPRINTF("SetMode\n");
-        EAT(mode);
-        EAT(setting);
-        /* ignore */
-        break;
-    }
-    case BAUM_REQ_SetProtocol:
-    {
-        uint8_t protocol;
-        DPRINTF("SetProtocol\n");
-        EAT(protocol);
-        /* ignore */
-        break;
-    }
-    case BAUM_REQ_GetDeviceIdentity:
-    {
-        uint8_t identity[17] = { BAUM_RSP_DeviceIdentity,
-            'B','a','u','m',' ','V','a','r','i','o' };
-        DPRINTF("GetDeviceIdentity\n");
-        identity[11] = '0' + baum->x / 10;
-        identity[12] = '0' + baum->x % 10;
-        baum_write_packet(baum, identity, sizeof(identity));
-        break;
-    }
-    case BAUM_REQ_GetVersionNumber:
-    {
-        uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */
-        DPRINTF("GetVersionNumber\n");
-        baum_write_packet(baum, version, sizeof(version));
-        break;
-    }
-    case BAUM_REQ_GetSerialNumber:
-    {
-        uint8_t serial[] = { BAUM_RSP_SerialNumber,
-            '0','0','0','0','0','0','0','0' };
-        DPRINTF("GetSerialNumber\n");
-        baum_write_packet(baum, serial, sizeof(serial));
-        break;
-    }
-    case BAUM_REQ_GetKeys:
-    {
-        DPRINTF("Get%0#2x\n", req);
-        /* ignore */
-        break;
-    }
-    default:
-        DPRINTF("unrecognized request %0#2x\n", req);
-        do
-            if (!len--)
-                return 0;
-        while (*cur++ != ESC);
-        cur--;
-        break;
-    }
-    return cur - buf;
-}
-
-/* The other end is writing some data.  Store it and try to interpret */
-static int baum_write(CharDriverState *chr, const uint8_t *buf, int len)
-{
-    BaumDriverState *baum = chr->opaque;
-    int tocopy, cur, eaten, orig_len = len;
-
-    if (!len)
-        return 0;
-    if (!baum->brlapi)
-        return len;
-
-    while (len) {
-        /* Complete our buffer as much as possible */
-        tocopy = len;
-        if (tocopy > BUF_SIZE - baum->in_buf_used)
-            tocopy = BUF_SIZE - baum->in_buf_used;
-
-        memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy);
-        baum->in_buf_used += tocopy;
-        buf += tocopy;
-        len -= tocopy;
-
-        /* Interpret it as much as possible */
-        cur = 0;
-        while (cur < baum->in_buf_used &&
-                (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur)))
-            cur += eaten;
-
-        /* Shift the remainder */
-        if (cur) {
-            memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur);
-            baum->in_buf_used -= cur;
-        }
-
-        /* And continue if any data left */
-    }
-    return orig_len;
-}
-
-/* Send the key code to the other end */
-static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) {
-    uint8_t packet[] = { type, value };
-    DPRINTF("writing key %x %x\n", type, value);
-    baum_write_packet(baum, packet, sizeof(packet));
-}
-
-/* We got some data on the BrlAPI socket */
-static void baum_chr_read(void *opaque)
-{
-    BaumDriverState *baum = opaque;
-    brlapi_keyCode_t code;
-    int ret;
-    if (!baum->brlapi)
-        return;
-    while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) {
-        DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code);
-        /* Emulate */
-        switch (code & BRLAPI_KEY_TYPE_MASK) {
-        case BRLAPI_KEY_TYPE_CMD:
-            switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
-            case BRLAPI_KEY_CMD_ROUTE:
-                baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1);
-                baum_send_key(baum, BAUM_RSP_RoutingKey, 0);
-                break;
-            case 0:
-                switch (code & BRLAPI_KEY_CMD_ARG_MASK) {
-                case BRLAPI_KEY_CMD_FWINLT:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_FWINRT:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_LNUP:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_LNDN:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_TOP:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_BOT:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_TOP_LEFT:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_BOT_LEFT:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_HOME:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_PREFMENU:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                }
-            }
-            break;
-        case BRLAPI_KEY_TYPE_SYM:
-            break;
-        }
-    }
-    if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) {
-        brlapi_perror("baum: brlapi_readKey");
-        brlapi__closeConnection(baum->brlapi);
-        g_free(baum->brlapi);
-        baum->brlapi = NULL;
-    }
-}
-
-static void baum_close(struct CharDriverState *chr)
-{
-    BaumDriverState *baum = chr->opaque;
-
-    qemu_free_timer(baum->cellCount_timer);
-    if (baum->brlapi) {
-        brlapi__closeConnection(baum->brlapi);
-        g_free(baum->brlapi);
-    }
-    g_free(baum);
-}
-
-static CharDriverState *chr_baum_init(QemuOpts *opts)
-{
-    BaumDriverState *baum;
-    CharDriverState *chr;
-    brlapi_handle_t *handle;
-#ifdef CONFIG_SDL
-    SDL_SysWMinfo info;
-#endif
-    int tty;
-
-    baum = g_malloc0(sizeof(BaumDriverState));
-    baum->chr = chr = g_malloc0(sizeof(CharDriverState));
-
-    chr->opaque = baum;
-    chr->chr_write = baum_write;
-    chr->chr_accept_input = baum_accept_input;
-    chr->chr_close = baum_close;
-
-    handle = g_malloc0(brlapi_getHandleSize());
-    baum->brlapi = handle;
-
-    baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
-    if (baum->brlapi_fd == -1) {
-        brlapi_perror("baum_init: brlapi_openConnection");
-        goto fail_handle;
-    }
-
-    baum->cellCount_timer = qemu_new_timer_ns(vm_clock, baum_cellCount_timer_cb, baum);
-
-    if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
-        brlapi_perror("baum_init: brlapi_getDisplaySize");
-        goto fail;
-    }
-
-#ifdef CONFIG_SDL
-    memset(&info, 0, sizeof(info));
-    SDL_VERSION(&info.version);
-    if (SDL_GetWMInfo(&info))
-        tty = info.info.x11.wmwindow;
-    else
-#endif
-        tty = BRLAPI_TTY_DEFAULT;
-
-    if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
-        brlapi_perror("baum_init: brlapi_enterTtyMode");
-        goto fail;
-    }
-
-    qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
-
-    qemu_chr_generic_open(chr);
-
-    return chr;
-
-fail:
-    qemu_free_timer(baum->cellCount_timer);
-    brlapi__closeConnection(handle);
-fail_handle:
-    g_free(handle);
-    g_free(chr);
-    g_free(baum);
-    return NULL;
-}
-
-static void register_types(void)
-{
-    register_char_driver("braille", chr_baum_init);
-}
-
-type_init(register_types);
index 114508fade9cfe13eb77371b58d756c9baebc14d..b8e6d3a1033e03d8a1657da10fd0f5d85ec7d892 100644 (file)
@@ -9,9 +9,9 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "bitbang_i2c.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/bitbang_i2c.h"
+#include "hw/sysbus.h"
 
 //#define DEBUG_BITBANG_I2C
 
index 519d2dc22fe4dce8a9504de930273e0cda1848c8..e86062742c6f810037df10ab6ab54e3cf0414515 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BITBANG_I2C_H
 #define BITBANG_I2C_H
 
-#include "i2c.h"
+#include "hw/i2c.h"
 
 typedef struct bitbang_i2c_interface bitbang_i2c_interface;
 
index 24bde32e5afbc892cd8e79e1aa2df5017a913cdd..805f4d55586a9741c51aecf8c241c7c9ff50b599 100644 (file)
@@ -20,8 +20,8 @@
 
 #include "qemu-common.h"
 #include "ui/console.h"
-#include "devices.h"
-#include "vga_int.h"
+#include "hw/devices.h"
+#include "hw/vga_int.h"
 #include "ui/pixel_ops.h"
 
 typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int);
@@ -941,15 +941,15 @@ static void blizzard_screen_dump(void *opaque, const char *filename,
 }
 
 #define DEPTH 8
-#include "blizzard_template.h"
+#include "hw/blizzard_template.h"
 #define DEPTH 15
-#include "blizzard_template.h"
+#include "hw/blizzard_template.h"
 #define DEPTH 16
-#include "blizzard_template.h"
+#include "hw/blizzard_template.h"
 #define DEPTH 24
-#include "blizzard_template.h"
+#include "hw/blizzard_template.h"
 #define DEPTH 32
-#include "blizzard_template.h"
+#include "hw/blizzard_template.h"
 
 void *s1d13745_init(qemu_irq gpio_int)
 {
index 3813d4e551b127e550dc0a56269d796380983fed..425bdc74a810dd7bdc88b7fd3b5505577f47bb78 100644 (file)
@@ -4,7 +4,7 @@
 #define HW_BOARDS_H
 
 #include "sysemu/blockdev.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 
 #define DEFAULT_MACHINE_OPTIONS \
     .boot_order = "cad"
index 0498c9be7980da5e94b671f72f93c2222b346c56..3456e7840ed0f81e4f09255927f53cc0f49ace8e 100644 (file)
 
 #include <assert.h>
 
-#include "hw.h"
-#include "pci/pci.h"
-#include "pc.h"
-#include "mips.h"
-#include "pci/pci_host.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pc.h"
+#include "hw/mips.h"
+#include "hw/pci/pci_host.h"
 #include "sysemu/sysemu.h"
 #include "exec/address-spaces.h"
 
index 2070bb940c7a1316afde7a6d1ca620cb33def32e..e4ada3c731174983afaed69056e564e9bae3bbf2 100644 (file)
@@ -21,9 +21,9 @@
 #include "qemu-common.h"
 #include "char/char.h"
 #include "qemu/timer.h"
-#include "irq.h"
+#include "hw/irq.h"
 #include "bt/bt.h"
-#include "bt.h"
+#include "hw/bt.h"
 
 struct csrhci_s {
     int enable;
index 69d2c73862c3c6a1492d7f86274f7255d7fa3e14..a76edea2c910ebedc692bbae515206774140d455 100644 (file)
@@ -20,9 +20,9 @@
 
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "usb.h"
+#include "hw/usb.h"
 #include "bt/bt.h"
-#include "bt.h"
+#include "hw/bt.h"
 
 struct bt_hci_s {
     uint8_t *(*evt_packet)(void *opaque);
index cfa7c145b88075526d01b851742ebe229058a324..69ccf9b4329e48cbe83f7f8f1e97e25df0b07eaa 100644 (file)
@@ -21,8 +21,8 @@
 #include "qemu-common.h"
 #include "qemu/timer.h"
 #include "ui/console.h"
-#include "hid.h"
-#include "bt.h"
+#include "hw/hid.h"
+#include "hw/bt.h"
 
 enum hid_transaction_req {
     BT_HANDSHAKE                       = 0x0,
index ba061c0da32762297fe23fbe8ca04c19157a3833..521587a1120a822ac20abc26211fa0683f92b079 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "bt.h"
+#include "hw/bt.h"
 
 #define L2CAP_CID_MAX  0x100   /* Between 0x40 and 0x10000 */
 
index c0431d1a40ad98399146c032293e0aa31cfc03fb..218e075df75f6593c85d53dcf30877b608914b9d 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #include "qemu-common.h"
-#include "bt.h"
+#include "hw/bt.h"
 
 struct bt_l2cap_sdp_state_s {
     struct bt_l2cap_conn_params_s *channel;
diff --git a/hw/bt.c b/hw/bt.c
index 4f2372d7943b7046473546ad351da2917e8105b5..24ef4de49d15adc460f1f916b29cd694324e2e41 100644 (file)
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -19,7 +19,7 @@
 
 #include "qemu-common.h"
 #include "bt/bt.h"
-#include "bt.h"
+#include "hw/bt.h"
 
 /* Slave implementations can ignore this */
 static void bt_dummy_lmp_mode_change(struct bt_link_s *link)
index de7d15ab76767c1ca0ad23c13af26715202a5ec9..e177057e4980808dfd9dadca7c9acc4381acd0a8 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <zlib.h> /* For crc32 */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
 #include "net/checksum.h"
 
index 67028a3f75694c7ef771c9e50386cacf276f1f5a..ba584f47190a78e4489d974ea3d3d0ca0e092942 100644 (file)
@@ -16,7 +16,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 
 #ifdef CADENCE_TTC_ERR_DEBUG
index 5766d38f13ce50e6b4ad6f73c2aae95583ee650a..5426f1001896eecbd58ddbd167594bfd95fc9189 100644 (file)
@@ -16,7 +16,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 #include "qemu/timer.h"
 
index 6fd39054486956f3b5f17b46f30aac011f8dbf4f..29b467b61fdb928d2bec56dc7a757447e60bc0c8 100644 (file)
--- a/hw/cbus.c
+++ b/hw/cbus.c
@@ -21,8 +21,8 @@
  */
 
 #include "qemu-common.h"
-#include "irq.h"
-#include "devices.h"
+#include "hw/irq.h"
+#include "hw/devices.h"
 #include "sysemu/sysemu.h"
 
 //#define DEBUG
index 6adc745a6d1f250ccb85ca4a178572f2897177a2..9334da8acd004a9546572e9928af762afc2b55a3 100644 (file)
--- a/hw/ccid.h
+++ b/hw/ccid.h
@@ -10,7 +10,7 @@
 #ifndef CCID_H
 #define CCID_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 typedef struct CCIDCardState CCIDCardState;
 typedef struct CCIDCardInfo CCIDCardInfo;
index 3b99535dcebc3e005811ce1500cbd2d2e2bfb523..a018eec40aa898facb230a97d308f6d16d6f18c8 100644 (file)
@@ -26,7 +26,7 @@
    here.  */
 
 #include "qemu-common.h"
-#include "scsi.h"
+#include "hw/scsi.h"
 
 static void lba_to_msf(uint8_t *buf, int lba)
 {
index 2a2c8dad628cf77f845301b0e43d082b154274e3..7babcb67c84ef07e0b25cad39328c2c41a1a7869 100644 (file)
  * Reference: Finn Thogersons' VGADOC4b
  *   available at http://home.worldonline.dk/~finth/
  */
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "ui/console.h"
-#include "vga_int.h"
-#include "loader.h"
+#include "hw/vga_int.h"
+#include "hw/loader.h"
 
 /*
  * TODO:
@@ -288,63 +288,63 @@ static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
 
 #define ROP_NAME 0
 #define ROP_FN(d, s) 0
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_and_dst
 #define ROP_FN(d, s) (s) & (d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_and_notdst
 #define ROP_FN(d, s) (s) & (~(d))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notdst
 #define ROP_FN(d, s) ~(d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src
 #define ROP_FN(d, s) s
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME 1
 #define ROP_FN(d, s) ~0
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notsrc_and_dst
 #define ROP_FN(d, s) (~(s)) & (d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_xor_dst
 #define ROP_FN(d, s) (s) ^ (d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_or_dst
 #define ROP_FN(d, s) (s) | (d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notsrc_or_notdst
 #define ROP_FN(d, s) (~(s)) | (~(d))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_notxor_dst
 #define ROP_FN(d, s) ~((s) ^ (d))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_or_notdst
 #define ROP_FN(d, s) (s) | (~(d))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notsrc
 #define ROP_FN(d, s) (~(s))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notsrc_or_dst
 #define ROP_FN(d, s) (~(s)) | (d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notsrc_and_notdst
 #define ROP_FN(d, s) (~(s)) & (~(d))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = {
     cirrus_bitblt_rop_fwd_0,
@@ -2165,13 +2165,13 @@ static void cirrus_cursor_invalidate(VGACommonState *s1)
 }
 
 #define DEPTH 8
-#include "cirrus_vga_template.h"
+#include "hw/cirrus_vga_template.h"
 
 #define DEPTH 16
-#include "cirrus_vga_template.h"
+#include "hw/cirrus_vga_template.h"
 
 #define DEPTH 32
-#include "cirrus_vga_template.h"
+#include "hw/cirrus_vga_template.h"
 
 static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
 {
index 9c7bb092862cc5f9a49b9a3d22f82a0336af1387..894610cc22349a56b3fe7ab3a637159bb5761ea2 100644 (file)
@@ -191,16 +191,16 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
 }
 
 #define DEPTH 8
-#include "cirrus_vga_rop2.h"
+#include "hw/cirrus_vga_rop2.h"
 
 #define DEPTH 16
-#include "cirrus_vga_rop2.h"
+#include "hw/cirrus_vga_rop2.h"
 
 #define DEPTH 24
-#include "cirrus_vga_rop2.h"
+#include "hw/cirrus_vga_rop2.h"
 
 #define DEPTH 32
-#include "cirrus_vga_rop2.h"
+#include "hw/cirrus_vga_rop2.h"
 
 #undef ROP_NAME
 #undef ROP_OP
diff --git a/hw/collie.c b/hw/collie.c
deleted file mode 100644 (file)
index d19db59..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * SA-1110-based Sharp Zaurus SL-5500 platform.
- *
- * Copyright (C) 2011 Dmitry Eremin-Solenikov
- *
- * This code is licensed under GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-#include "hw.h"
-#include "sysbus.h"
-#include "boards.h"
-#include "devices.h"
-#include "strongarm.h"
-#include "arm-misc.h"
-#include "flash.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-static struct arm_boot_info collie_binfo = {
-    .loader_start = SA_SDCS0,
-    .ram_size = 0x20000000,
-};
-
-static void collie_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    StrongARMState *s;
-    DriveInfo *dinfo;
-    MemoryRegion *sysmem = get_system_memory();
-
-    if (!cpu_model) {
-        cpu_model = "sa1110";
-    }
-
-    s = sa1110_init(sysmem, collie_binfo.ram_size, cpu_model);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
-                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
-
-    dinfo = drive_get(IF_PFLASH, 0, 1);
-    pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000,
-                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
-
-    sysbus_create_simple("scoop", 0x40800000, NULL);
-
-    collie_binfo.kernel_filename = kernel_filename;
-    collie_binfo.kernel_cmdline = kernel_cmdline;
-    collie_binfo.initrd_filename = initrd_filename;
-    collie_binfo.board_id = 0x208;
-    arm_load_kernel(s->cpu, &collie_binfo);
-}
-
-static QEMUMachine collie_machine = {
-    .name = "collie",
-    .desc = "Collie PDA (SA-1110)",
-    .init = collie_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void collie_machine_init(void)
-{
-    qemu_register_machine(&collie_machine);
-}
-
-machine_init(collie_machine_init)
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
deleted file mode 100644 (file)
index b21326f..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * CRIS image loading.
- *
- * Copyright (c) 2010 Edgar E. Iglesias, Axis Communications AB.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw.h"
-#include "loader.h"
-#include "elf.h"
-#include "cris-boot.h"
-
-static void main_cpu_reset(void *opaque)
-{
-    CRISCPU *cpu = opaque;
-    CPUCRISState *env = &cpu->env;
-    struct cris_load_info *li;
-
-    li = env->load_info;
-
-    cpu_reset(CPU(cpu));
-
-    if (!li) {
-        /* nothing more to do.  */
-        return;
-    }
-
-    env->pc = li->entry;
-
-    if (li->image_filename) {
-        env->regs[8] = 0x56902387; /* RAM boot magic.  */
-        env->regs[9] = 0x40004000 + li->image_size;
-    }
-
-    if (li->cmdline) {
-        /* Let the kernel know we are modifying the cmdline.  */
-        env->regs[10] = 0x87109563;
-        env->regs[11] = 0x40000000;
-    }
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return addr - 0x80000000LL;
-}
-
-void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
-{
-    CPUCRISState *env = &cpu->env;
-    uint64_t entry, high;
-    int kcmdline_len;
-    int image_size;
-
-    env->load_info = li;
-    /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
-       devboard SDK.  */
-    image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
-                          &entry, NULL, &high, 0, ELF_MACHINE, 0);
-    li->entry = entry;
-    if (image_size < 0) {
-        /* Takes a kimage from the axis devboard SDK.  */
-        image_size = load_image_targphys(li->image_filename, 0x40004000,
-                                         ram_size);
-        li->entry = 0x40004000;
-    }
-
-    if (image_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                li->image_filename);
-        exit(1);
-    }
-
-    if (li->cmdline && (kcmdline_len = strlen(li->cmdline))) {
-        if (kcmdline_len > 256) {
-            fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
-            exit(1);
-        }
-        pstrcpy_targphys("cmdline", 0x40000000, 256, li->cmdline);
-    }
-    qemu_register_reset(main_cpu_reset, cpu);
-}
index aa9298a0ed036d04a61e64f61a21917009feedac..a94c62450d308e8c9b4f654d0105c754877460af 100644 (file)
@@ -1,8 +1,3 @@
-# Boards
-obj-y = cris_pic_cpu.o
-obj-y += cris-boot.o
-obj-y += axis_dev88.o
-
 # IO blocks
 obj-y += etraxfs_dma.o
 obj-y += etraxfs_pic.o
@@ -11,3 +6,8 @@ obj-y += etraxfs_timer.o
 obj-y += etraxfs_ser.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+# Boards
+obj-y += pic_cpu.o
+obj-y += boot.o
+obj-y += axis_dev88.o
diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c
new file mode 100644 (file)
index 0000000..eccd423
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * QEMU model for the AXIS devboard 88.
+ *
+ * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/sysbus.h"
+#include "net/net.h"
+#include "hw/flash.h"
+#include "hw/boards.h"
+#include "hw/etraxfs.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/cris-boot.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define D(x)
+#define DNAND(x)
+
+struct nand_state_t
+{
+    DeviceState *nand;
+    MemoryRegion iomem;
+    unsigned int rdy:1;
+    unsigned int ale:1;
+    unsigned int cle:1;
+    unsigned int ce:1;
+};
+
+static struct nand_state_t nand_state;
+static uint64_t nand_read(void *opaque, hwaddr addr, unsigned size)
+{
+    struct nand_state_t *s = opaque;
+    uint32_t r;
+    int rdy;
+
+    r = nand_getio(s->nand);
+    nand_getpins(s->nand, &rdy);
+    s->rdy = rdy;
+
+    DNAND(printf("%s addr=%x r=%x\n", __func__, addr, r));
+    return r;
+}
+
+static void
+nand_write(void *opaque, hwaddr addr, uint64_t value,
+           unsigned size)
+{
+    struct nand_state_t *s = opaque;
+    int rdy;
+
+    DNAND(printf("%s addr=%x v=%x\n", __func__, addr, (unsigned)value));
+    nand_setpins(s->nand, s->cle, s->ale, s->ce, 1, 0);
+    nand_setio(s->nand, value);
+    nand_getpins(s->nand, &rdy);
+    s->rdy = rdy;
+}
+
+static const MemoryRegionOps nand_ops = {
+    .read = nand_read,
+    .write = nand_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+struct tempsensor_t
+{
+    unsigned int shiftreg;
+    unsigned int count;
+    enum {
+        ST_OUT, ST_IN, ST_Z
+    } state;
+
+    uint16_t regs[3];
+};
+
+static void tempsensor_clkedge(struct tempsensor_t *s,
+                               unsigned int clk, unsigned int data_in)
+{
+    D(printf("%s clk=%d state=%d sr=%x\n", __func__,
+             clk, s->state, s->shiftreg));
+    if (s->count == 0) {
+        s->count = 16;
+        s->state = ST_OUT;
+    }
+    switch (s->state) {
+        case ST_OUT:
+            /* Output reg is clocked at negedge.  */
+            if (!clk) {
+                s->count--;
+                s->shiftreg <<= 1;
+                if (s->count == 0) {
+                    s->shiftreg = 0;
+                    s->state = ST_IN;
+                    s->count = 16;
+                }
+            }
+            break;
+        case ST_Z:
+            if (clk) {
+                s->count--;
+                if (s->count == 0) {
+                    s->shiftreg = 0;
+                    s->state = ST_OUT;
+                    s->count = 16;
+                }
+            }
+            break;
+        case ST_IN:
+            /* Indata is sampled at posedge.  */
+            if (clk) {
+                s->count--;
+                s->shiftreg <<= 1;
+                s->shiftreg |= data_in & 1;
+                if (s->count == 0) {
+                    D(printf("%s cfgreg=%x\n", __func__, s->shiftreg));
+                    s->regs[0] = s->shiftreg;
+                    s->state = ST_OUT;
+                    s->count = 16;
+
+                    if ((s->regs[0] & 0xff) == 0) {
+                        /* 25 degrees celcius.  */
+                        s->shiftreg = 0x0b9f;
+                    } else if ((s->regs[0] & 0xff) == 0xff) {
+                        /* Sensor ID, 0x8100 LM70.  */
+                        s->shiftreg = 0x8100;
+                    } else
+                        printf("Invalid tempsens state %x\n", s->regs[0]);
+                }
+            }
+            break;
+    }
+}
+
+
+#define RW_PA_DOUT    0x00
+#define R_PA_DIN      0x01
+#define RW_PA_OE      0x02
+#define RW_PD_DOUT    0x10
+#define R_PD_DIN      0x11
+#define RW_PD_OE      0x12
+
+static struct gpio_state_t
+{
+    MemoryRegion iomem;
+    struct nand_state_t *nand;
+    struct tempsensor_t tempsensor;
+    uint32_t regs[0x5c / 4];
+} gpio_state;
+
+static uint64_t gpio_read(void *opaque, hwaddr addr, unsigned size)
+{
+    struct gpio_state_t *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr)
+    {
+        case R_PA_DIN:
+            r = s->regs[RW_PA_DOUT] & s->regs[RW_PA_OE];
+
+            /* Encode pins from the nand.  */
+            r |= s->nand->rdy << 7;
+            break;
+        case R_PD_DIN:
+            r = s->regs[RW_PD_DOUT] & s->regs[RW_PD_OE];
+
+            /* Encode temp sensor pins.  */
+            r |= (!!(s->tempsensor.shiftreg & 0x10000)) << 4;
+            break;
+
+        default:
+            r = s->regs[addr];
+            break;
+    }
+    return r;
+    D(printf("%s %x=%x\n", __func__, addr, r));
+}
+
+static void gpio_write(void *opaque, hwaddr addr, uint64_t value,
+                       unsigned size)
+{
+    struct gpio_state_t *s = opaque;
+    D(printf("%s %x=%x\n", __func__, addr, (unsigned)value));
+
+    addr >>= 2;
+    switch (addr)
+    {
+        case RW_PA_DOUT:
+            /* Decode nand pins.  */
+            s->nand->ale = !!(value & (1 << 6));
+            s->nand->cle = !!(value & (1 << 5));
+            s->nand->ce  = !!(value & (1 << 4));
+
+            s->regs[addr] = value;
+            break;
+
+        case RW_PD_DOUT:
+            /* Temp sensor clk.  */
+            if ((s->regs[addr] ^ value) & 2)
+                tempsensor_clkedge(&s->tempsensor, !!(value & 2),
+                                   !!(value & 16));
+            s->regs[addr] = value;
+            break;
+
+        default:
+            s->regs[addr] = value;
+            break;
+    }
+}
+
+static const MemoryRegionOps gpio_ops = {
+    .read = gpio_read,
+    .write = gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+#define INTMEM_SIZE (128 * 1024)
+
+static struct cris_load_info li;
+
+static
+void axisdev88_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    CRISCPU *cpu;
+    CPUCRISState *env;
+    DeviceState *dev;
+    SysBusDevice *s;
+    DriveInfo *nand;
+    qemu_irq irq[30], nmi[2], *cpu_irq;
+    void *etraxfs_dmac;
+    struct etraxfs_dma_client *dma_eth;
+    int i;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_intmem = g_new(MemoryRegion, 1);
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "crisv32";
+    }
+    cpu = cpu_cris_init(cpu_model);
+    env = &cpu->env;
+
+    /* allocate RAM */
+    memory_region_init_ram(phys_ram, "axisdev88.ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram);
+
+    /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
+       internal memory.  */
+    memory_region_init_ram(phys_intmem, "axisdev88.chipram", INTMEM_SIZE);
+    vmstate_register_ram_global(phys_intmem);
+    memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem);
+
+      /* Attach a NAND flash to CS1.  */
+    nand = drive_get(IF_MTD, 0, 0);
+    nand_state.nand = nand_init(nand ? nand->bdrv : NULL,
+                                NAND_MFR_STMICRO, 0x39);
+    memory_region_init_io(&nand_state.iomem, &nand_ops, &nand_state,
+                          "nand", 0x05000000);
+    memory_region_add_subregion(address_space_mem, 0x10000000,
+                                &nand_state.iomem);
+
+    gpio_state.nand = &nand_state;
+    memory_region_init_io(&gpio_state.iomem, &gpio_ops, &gpio_state,
+                          "gpio", 0x5c);
+    memory_region_add_subregion(address_space_mem, 0x3001a000,
+                                &gpio_state.iomem);
+
+
+    cpu_irq = cris_pic_init_cpu(env);
+    dev = qdev_create(NULL, "etraxfs,pic");
+    /* FIXME: Is there a proper way to signal vectors to the CPU core?  */
+    qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(s, 0, 0x3001c000);
+    sysbus_connect_irq(s, 0, cpu_irq[0]);
+    sysbus_connect_irq(s, 1, cpu_irq[1]);
+    for (i = 0; i < 30; i++) {
+        irq[i] = qdev_get_gpio_in(dev, i);
+    }
+    nmi[0] = qdev_get_gpio_in(dev, 30);
+    nmi[1] = qdev_get_gpio_in(dev, 31);
+
+    etraxfs_dmac = etraxfs_dmac_init(0x30000000, 10);
+    for (i = 0; i < 10; i++) {
+        /* On ETRAX, odd numbered channels are inputs.  */
+        etraxfs_dmac_connect(etraxfs_dmac, i, irq + 7 + i, i & 1);
+    }
+
+    /* Add the two ethernet blocks.  */
+    dma_eth = g_malloc0(sizeof dma_eth[0] * 4); /* Allocate 4 channels.  */
+    etraxfs_eth_init(&nd_table[0], 0x30034000, 1, &dma_eth[0], &dma_eth[1]);
+    if (nb_nics > 1) {
+        etraxfs_eth_init(&nd_table[1], 0x30036000, 2, &dma_eth[2], &dma_eth[3]);
+    }
+
+    /* The DMA Connector block is missing, hardwire things for now.  */
+    etraxfs_dmac_connect_client(etraxfs_dmac, 0, &dma_eth[0]);
+    etraxfs_dmac_connect_client(etraxfs_dmac, 1, &dma_eth[1]);
+    if (nb_nics > 1) {
+        etraxfs_dmac_connect_client(etraxfs_dmac, 6, &dma_eth[2]);
+        etraxfs_dmac_connect_client(etraxfs_dmac, 7, &dma_eth[3]);
+    }
+
+    /* 2 timers.  */
+    sysbus_create_varargs("etraxfs,timer", 0x3001e000, irq[0x1b], nmi[1], NULL);
+    sysbus_create_varargs("etraxfs,timer", 0x3005e000, irq[0x1b], nmi[1], NULL);
+
+    for (i = 0; i < 4; i++) {
+        sysbus_create_simple("etraxfs,serial", 0x30026000 + i * 0x2000,
+                             irq[0x14 + i]);
+    }
+
+    if (!kernel_filename) {
+        fprintf(stderr, "Kernel image must be specified\n");
+        exit(1);
+    }
+
+    li.image_filename = kernel_filename;
+    li.cmdline = kernel_cmdline;
+    cris_load_image(cpu, &li);
+}
+
+static QEMUMachine axisdev88_machine = {
+    .name = "axis-dev88",
+    .desc = "AXIS devboard 88",
+    .init = axisdev88_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void axisdev88_machine_init(void)
+{
+    qemu_register_machine(&axisdev88_machine);
+}
+
+machine_init(axisdev88_machine_init);
diff --git a/hw/cris/boot.c b/hw/cris/boot.c
new file mode 100644 (file)
index 0000000..c330e22
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * CRIS image loading.
+ *
+ * Copyright (c) 2010 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/cris-boot.h"
+
+static void main_cpu_reset(void *opaque)
+{
+    CRISCPU *cpu = opaque;
+    CPUCRISState *env = &cpu->env;
+    struct cris_load_info *li;
+
+    li = env->load_info;
+
+    cpu_reset(CPU(cpu));
+
+    if (!li) {
+        /* nothing more to do.  */
+        return;
+    }
+
+    env->pc = li->entry;
+
+    if (li->image_filename) {
+        env->regs[8] = 0x56902387; /* RAM boot magic.  */
+        env->regs[9] = 0x40004000 + li->image_size;
+    }
+
+    if (li->cmdline) {
+        /* Let the kernel know we are modifying the cmdline.  */
+        env->regs[10] = 0x87109563;
+        env->regs[11] = 0x40000000;
+    }
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return addr - 0x80000000LL;
+}
+
+void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
+{
+    CPUCRISState *env = &cpu->env;
+    uint64_t entry, high;
+    int kcmdline_len;
+    int image_size;
+
+    env->load_info = li;
+    /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
+       devboard SDK.  */
+    image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
+                          &entry, NULL, &high, 0, ELF_MACHINE, 0);
+    li->entry = entry;
+    if (image_size < 0) {
+        /* Takes a kimage from the axis devboard SDK.  */
+        image_size = load_image_targphys(li->image_filename, 0x40004000,
+                                         ram_size);
+        li->entry = 0x40004000;
+    }
+
+    if (image_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                li->image_filename);
+        exit(1);
+    }
+
+    if (li->cmdline && (kcmdline_len = strlen(li->cmdline))) {
+        if (kcmdline_len > 256) {
+            fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
+            exit(1);
+        }
+        pstrcpy_targphys("cmdline", 0x40000000, 256, li->cmdline);
+    }
+    qemu_register_reset(main_cpu_reset, cpu);
+}
diff --git a/hw/cris/pic_cpu.c b/hw/cris/pic_cpu.c
new file mode 100644 (file)
index 0000000..7f50471
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * QEMU CRIS CPU interrupt wrapper logic.
+ *
+ * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/etraxfs.h"
+
+#define D(x)
+
+static void cris_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    CPUCRISState *env = (CPUCRISState *)opaque;
+    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+
+    if (level)
+        cpu_interrupt(env, type);
+    else
+        cpu_reset_interrupt(env, type);
+}
+
+qemu_irq *cris_pic_init_cpu(CPUCRISState *env)
+{
+    return qemu_allocate_irqs(cris_pic_cpu_handler, env, 2);
+}
diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c
deleted file mode 100644 (file)
index 3da0e86..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * QEMU CRIS CPU interrupt wrapper logic.
- *
- * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "hw.h"
-#include "etraxfs.h"
-
-#define D(x)
-
-static void cris_pic_cpu_handler(void *opaque, int irq, int level)
-{
-    CPUCRISState *env = (CPUCRISState *)opaque;
-    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
-
-    if (level)
-        cpu_interrupt(env, type);
-    else
-        cpu_reset_interrupt(env, type);
-}
-
-qemu_irq *cris_pic_init_cpu(CPUCRISState *env)
-{
-    return qemu_allocate_irqs(cris_pic_cpu_handler, env, 2);
-}
index ae384b90fd2f1d8c635850555ed3e0db2038716f..29753360579024016c51c6dbe9ed26abf3d1c4b6 100644 (file)
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /*
index 73f08594bf468ea616d24c6bc61e09e7a5590fc5..f005f2589918176e29ce6fee95f77322e59b8b52 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "isa.h"
-#include "qdev.h"
+#include "hw/isa.h"
+#include "hw/qdev.h"
 #include "qemu/timer.h"
 
 /*
index b36c53527ab03c4137d6f96d9e9b677e20903e1e..2ae430d326e3e9382fae3a69d609de231143ec5f 100644 (file)
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -22,9 +22,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc/mac.h"
-#include "adb.h"
+#include "hw/hw.h"
+#include "hw/ppc/mac.h"
+#include "hw/adb.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 
index 0c9f5c4d6082a42e89c6df972cb8aeafbe0d6864..f709f87ed630b1f598e0da834f626c6eea3f9816 100644 (file)
@@ -12,7 +12,7 @@
  *
  */
 
-#include "hw/dataplane/ioq.h"
+#include "ioq.h"
 
 void ioq_init(IOQueue *ioq, int fd, unsigned int max_reqs)
 {
index aa9b04078bb59296d4a40d3372231814265810d6..dfe5f9b9cdd3d4a5edfd76625beee50194c34f7a 100644 (file)
 #include "trace.h"
 #include "qemu/iov.h"
 #include "qemu/thread.h"
+#include "qemu/error-report.h"
 #include "vring.h"
 #include "ioq.h"
 #include "migration/migration.h"
+#include "block/block.h"
 #include "hw/virtio-blk.h"
 #include "hw/dataplane/virtio-blk.h"
 #include "block/aio.h"
index d5d4ef45d17b8a3ec756945e7baf8b8e57d0771a..e3b225315ff99353dadece9055a36ecb595737da 100644 (file)
@@ -15,7 +15,8 @@
  */
 
 #include "trace.h"
-#include "hw/dataplane/vring.h"
+#include "vring.h"
+#include "qemu/error-report.h"
 
 /* Map the guest's vring to host memory */
 bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
index 3274f623f5267bba0cb4b335f8f54e141b2c7973..defb1efcda4be1cfcbf772025dcf29a27b372b98 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <linux/virtio_ring.h>
 #include "qemu-common.h"
-#include "hw/dataplane/hostmem.h"
+#include "hostmem.h"
 #include "hw/virtio.h"
 
 typedef struct {
index 81b2bb00fd0da132f479fa180c069ec8ba01fab5..cab7691b12e4b4af88fa187bffb10150e5dbba73 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "char/char.h"
-#include "isa.h"
-#include "pc.h"
+#include "hw/isa.h"
+#include "hw/pc.h"
 
 #define TYPE_ISA_DEBUGCON_DEVICE "isa-debugcon"
 #define ISA_DEBUGCON_DEVICE(obj) \
index c1b489ddcb81ff19165fb84324e68f6181ead71a..ba67a8fb415956add7a1e8b97f1012c5c5b3c4ca 100644 (file)
@@ -7,8 +7,8 @@
  * (at your option) any later version.
  */
 
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 
 #define TYPE_ISA_DEBUG_EXIT_DEVICE "isa-debug-exit"
 #define ISA_DEBUG_EXIT_DEVICE(obj) \
index ee3f4ca834400137855a6998a8cfe61546b6a8e6..64a50924f6bf356b74fdc72a621869fcb13f41b7 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "dec_pci.h"
-#include "sysbus.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
-#include "pci/pci_bridge.h"
-#include "pci/pci_bus.h"
+#include "hw/dec_pci.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_bus.h"
 
 /* debug DEC */
 //#define DEBUG_DEC
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
deleted file mode 100644 (file)
index 88da145..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * QEMU device hotplug helpers
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw.h"
-#include "boards.h"
-#include "sysemu/blockdev.h"
-#include "qemu/config-file.h"
-#include "sysemu/sysemu.h"
-#include "monitor/monitor.h"
-
-DriveInfo *add_init_drive(const char *optstr)
-{
-    DriveInfo *dinfo;
-    QemuOpts *opts;
-
-    opts = drive_def(optstr);
-    if (!opts)
-        return NULL;
-
-    dinfo = drive_init(opts, current_machine->block_default_type);
-    if (!dinfo) {
-        qemu_opts_del(opts);
-        return NULL;
-    }
-
-    return dinfo;
-}
-
-#if !defined(TARGET_I386)
-int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo)
-{
-    /* On non-x86 we don't do PCI hotplug */
-    monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
-    return -1;
-}
-#endif
-
-void drive_hot_add(Monitor *mon, const QDict *qdict)
-{
-    DriveInfo *dinfo = NULL;
-    const char *opts = qdict_get_str(qdict, "opts");
-
-    dinfo = add_init_drive(opts);
-    if (!dinfo) {
-        goto err;
-    }
-    if (dinfo->devaddr) {
-        monitor_printf(mon, "Parameter addr not supported\n");
-        goto err;
-    }
-
-    switch (dinfo->type) {
-    case IF_NONE:
-        monitor_printf(mon, "OK\n");
-        break;
-    default:
-        if (pci_drive_hot_add(mon, qdict, dinfo)) {
-            goto err;
-        }
-    }
-    return;
-
-err:
-    if (dinfo) {
-        drive_put_ref(dinfo);
-    }
-}
index 5bdf4358e3d31cc15d1adbc86cdb57a63f9b5c64..fd1161ca312c4f8cc01cffb0ab898655c10098cb 100644 (file)
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -21,8 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 #include "qemu/main-loop.h"
 
 /* #define DEBUG_DMA */
index 808157b38b7d8368ee0a1c452b6a42ab79a4deba..8b5ca6a4ece6636bec71106129d353c2fd7df057 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
 #include "net/net.h"
-#include "mips.h"
+#include "hw/mips.h"
 
 //#define DEBUG_SONIC
 
index a6219a7908c1cbd701375c9dadf258c470d5fc41..488f1d7241889289f186de2704a42fda3a9f52bb 100644 (file)
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 typedef struct {
index 1da0f96fdc300bd25b986e0a06c003a504a7bcc1..ae7ca9f82daaae05f4d671edb714a01ea6897cb3 100644 (file)
@@ -10,7 +10,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "i2c.h"
+#include "hw/i2c.h"
 
 /* Size of NVRAM including both the user-accessible area and the
  * secondary register area.
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
deleted file mode 100644 (file)
index 3a88805..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Dummy board with just RAM and CPU for use as an ISS.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-
-#include "hw.h"
-#include "boards.h"
-#include "loader.h"
-#include "elf.h"
-#include "exec/address-spaces.h"
-
-#define KERNEL_LOAD_ADDR 0x10000
-
-/* Board init.  */
-
-static void dummy_m68k_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    CPUM68KState *env;
-    MemoryRegion *address_space_mem =  get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    int kernel_size;
-    uint64_t elf_entry;
-    hwaddr entry;
-
-    if (!cpu_model)
-        cpu_model = "cfv4e";
-    env = cpu_init(cpu_model);
-    if (!env) {
-        fprintf(stderr, "Unable to find m68k CPU definition\n");
-        exit(1);
-    }
-
-    /* Initialize CPU registers.  */
-    env->vbr = 0;
-
-    /* RAM at address zero */
-    memory_region_init_ram(ram, "dummy_m68k.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, 0, ram);
-
-    /* Load kernel.  */
-    if (kernel_filename) {
-        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                               NULL, NULL, 1, ELF_MACHINE, 0);
-        entry = elf_entry;
-        if (kernel_size < 0) {
-            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
-        }
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename,
-                                              KERNEL_LOAD_ADDR,
-                                              ram_size - KERNEL_LOAD_ADDR);
-            entry = KERNEL_LOAD_ADDR;
-        }
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-    } else {
-        entry = 0;
-    }
-    env->pc = entry;
-}
-
-static QEMUMachine dummy_m68k_machine = {
-    .name = "dummy",
-    .desc = "Dummy board",
-    .init = dummy_m68k_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void dummy_m68k_machine_init(void)
-{
-    qemu_register_machine(&dummy_m68k_machine);
-}
-
-machine_init(dummy_m68k_machine_init);
index 45cc3300cfa922081e5fb9cdc56f501c68e2b9ae..80b6ee3c1a626651bbfa664feee84883d70c7f0d 100644 (file)
  */
 
 
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "net/net.h"
 #include "net/checksum.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/dma.h"
 
-#include "e1000_hw.h"
+#include "hw/e1000_hw.h"
 
 #define E1000_DEBUG
 
index 60d1f1d4f23c283e74bd786d93b5507d302404a8..8c97c33debd0832cfb5b2f7a71d1281196b93d0c 100644 (file)
--- a/hw/ecc.c
+++ b/hw/ecc.c
@@ -11,8 +11,8 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "flash.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
 
 /*
  * Pre-calculated 256-way 1 byte column parity.  Table borrowed from Linux.
index dbac2c2bbcce1a6b241ff1fded07c1332df9f63b..6f4a407cbfb847e22882067e26e6b7c6c2dae6e4 100644 (file)
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /* There are 3 versions of this chip used in SMP sun4m systems:
index 5d237968e74c890f719a38214f3120a82ee73cc8..68d729c17af4d67b53b5fc348739c99ca68aebe2 100644 (file)
  */
 
 #include <stddef.h>             /* offsetof */
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "net/net.h"
-#include "eeprom93xx.h"
+#include "hw/eeprom93xx.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/dma.h"
 
index 4c7158d1a59a753bf2eeacfd63c0a7aa75b61355..39f560553d15c22589c513ad840147118a396ef3 100644 (file)
@@ -35,8 +35,8 @@
  * - No emulation of EEPROM timings.
  */
 
-#include "hw.h"
-#include "eeprom93xx.h"
+#include "hw/hw.h"
+#include "hw/eeprom93xx.h"
 
 /* Debug EEPROM emulation. */
 //~ #define DEBUG_EEPROM
index d7b54973a425a66f3f34d0f93fb6031ccca5669a..5234a4ddc6cbe558333d09cc950049ade1cfd1b8 100644 (file)
@@ -9,9 +9,9 @@
  * version.
  */
 
-#include "hw.h"
-#include "sysbus.h"
-#include "empty_slot.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/empty_slot.h"
 
 //#define DEBUG_EMPTY_SLOT
 
index 977d2e376767de68f8160e11597952e0ecfe6c82..e64cf23099ed695233332fb9d2b2ad72e4665269 100644 (file)
 /* #define VERBOSE_ES1370 */
 #define SILENT_ES1370
 
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 #include "sysemu/dma.h"
 
 /* Missing stuff:
index 18c02921e3035985e7a0fb8803d59a9f09c168ef..baf02193043bb6e923ec8f960ca753ac91fb61a3 100644 (file)
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -22,9 +22,9 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "sysbus.h"
-#include "escc.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/escc.h"
 #include "char/char.h"
 #include "ui/console.h"
 #include "trace.h"
index c949e6e0d9e7d3abb16dac545f451606223d2c01..7599b39d8d564b1802bc9666fbb7c8e339b02fcb 100644 (file)
@@ -23,9 +23,9 @@
  * THE SOFTWARE.
  */
 
-#include "pci/pci.h"
-#include "eeprom93xx.h"
-#include "esp.h"
+#include "hw/pci/pci.h"
+#include "hw/eeprom93xx.h"
+#include "hw/esp.h"
 #include "trace.h"
 #include "qemu/log.h"
 
index 2af48aac4bb33a58df77d613fc6eac3c96e4395f..5365eacec0fa7ddde81514bbff33e779fafa6ddc 100644 (file)
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -23,8 +23,8 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "esp.h"
+#include "hw/sysbus.h"
+#include "hw/esp.h"
 #include "trace.h"
 #include "qemu/log.h"
 
index f15cc7b5bdbdaba1cd87257a0d76e314478fffd2..830673be8f33a27aa7779a40017162b4ada1e1db 100644 (file)
--- a/hw/esp.h
+++ b/hw/esp.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_HW_ESP_H
 #define QEMU_HW_ESP_H
 
-#include "scsi.h"
+#include "hw/scsi.h"
 
 /* esp.c */
 #define ESP_MAX_DEVS 7
index 180de5a0887bbfd13946173d4d473a6c54438758..0df4fdd2e999253414bf981d66112bdadb29862c 100644 (file)
@@ -26,7 +26,7 @@
 #define HW_EXTRAXFS_H 1
 
 #include "net/net.h"
-#include "etraxfs_dma.h"
+#include "hw/etraxfs_dma.h"
 
 qemu_irq *cris_pic_init_cpu(CPUCRISState *env);
 
index d41500316fbf4c7123ff8ffd04b9985d98d04d52..a84ec1f23ce1286b23b2db9a8058c6ee539636f1 100644 (file)
  */
 #include <stdio.h>
 #include <sys/time.h>
-#include "hw.h"
+#include "hw/hw.h"
 #include "exec/address-spaces.h"
 #include "qemu-common.h"
 #include "sysemu/sysemu.h"
 
-#include "etraxfs_dma.h"
+#include "hw/etraxfs_dma.h"
 
 #define D(x)
 
index ad36411193034d00e4c07325636daa74cb367993..591bee245cc5f8b07892d461feed862799aa4ba2 100644 (file)
@@ -23,9 +23,9 @@
  */
 
 #include <stdio.h>
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
-#include "etraxfs.h"
+#include "hw/etraxfs.h"
 
 #define D(x)
 
index 64af31c46e9ab6bb97fc5f2c8484e456c03062c4..635103c00109a1725ec9b3ea5dc60dad5f57ec53 100644 (file)
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "hw.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
 //#include "pc.h"
 //#include "etraxfs.h"
 
index 72c8868639b7a56f561699756a5fd82a10426ae8..7e24d34230ade124e976edbf9c6f8fb5be25a22d 100644 (file)
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 #include "qemu/log.h"
 
index d3dac52315c5de2af5df87a4f1fa1d9fcc50fb57..3cd9476bb19885a46426a3ba5767dbc70ad573f5 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
 #define D(x)
 
diff --git a/hw/exynos4210.c b/hw/exynos4210.c
deleted file mode 100644 (file)
index fa54e42..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- *  Samsung exynos4210 SoC emulation
- *
- *  Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *    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 "sysemu/sysemu.h"
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "loader.h"
-#include "exynos4210.h"
-#include "usb/hcd-ehci.h"
-
-#define EXYNOS4210_CHIPID_ADDR         0x10000000
-
-/* PWM */
-#define EXYNOS4210_PWM_BASE_ADDR       0x139D0000
-
-/* RTC */
-#define EXYNOS4210_RTC_BASE_ADDR       0x10070000
-
-/* MCT */
-#define EXYNOS4210_MCT_BASE_ADDR       0x10050000
-
-/* 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
-
-/* 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
-
-/* PMU SFR base address */
-#define EXYNOS4210_PMU_BASE_ADDR            0x10020000
-
-/* Display controllers (FIMD) */
-#define EXYNOS4210_FIMD0_BASE_ADDR          0x11C00000
-
-/* EHCI */
-#define EXYNOS4210_EHCI_BASE_ADDR           0x12580000
-
-static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
-                                    0x09, 0x00, 0x00, 0x00 };
-
-void exynos4210_write_secondary(ARMCPU *cpu,
-        const struct arm_boot_info *info)
-{
-    int n;
-    uint32_t smpboot[] = {
-        0xe59f3034, /* ldr r3, External gic_cpu_if */
-        0xe59f2034, /* ldr r2, Internal gic_cpu_if */
-        0xe59f0034, /* ldr r0, startaddr */
-        0xe3a01001, /* mov r1, #1 */
-        0xe5821000, /* str r1, [r2] */
-        0xe5831000, /* str r1, [r3] */
-        0xe3a010ff, /* mov r1, #0xff */
-        0xe5821004, /* str r1, [r2, #4] */
-        0xe5831004, /* str r1, [r3, #4] */
-        0xf57ff04f, /* dsb */
-        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 *exynos4210_init(MemoryRegion *system_mem,
-        unsigned long ram_size)
-{
-    qemu_irq cpu_irq[EXYNOS4210_NCPUS];
-    int i, n;
-    Exynos4210State *s = g_new(Exynos4210State, 1);
-    qemu_irq *irqp;
-    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++) {
-        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 */
-        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 */
-    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 = SYS_BUS_DEVICE(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 = SYS_BUS_DEVICE(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][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 = SYS_BUS_DEVICE(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++) {
-        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 = SYS_BUS_DEVICE(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 = SYS_BUS_DEVICE(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);
-    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);
-    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);
-
-   /* 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("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
-
-    /* PWM */
-    sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
-                          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(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 = SYS_BUS_DEVICE(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 = SYS_BUS_DEVICE(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, 0)]);
-
-    exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
-                           EXYNOS4210_UART1_FIFO_SIZE, 1, NULL,
-                  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, 2)]);
-
-    exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
-                           EXYNOS4210_UART3_FIFO_SIZE, 3, NULL,
-                  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);
-
-    sysbus_create_simple(TYPE_EXYNOS4210_EHCI, EXYNOS4210_EHCI_BASE_ADDR,
-            s->irq_table[exynos4210_get_irq(28, 3)]);
-
-    return s;
-}
index ba644b43c226c267a18733e398ecab99b5eb01e6..5818f101324f239f2091383be24217b3936baa29 100644 (file)
@@ -27,9 +27,9 @@
  * IRQs are passed to GIC through Combiner.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
-#include "exynos4210.h"
+#include "hw/exynos4210.h"
 
 //#define DEBUG_COMBINER
 
index 3d498b77f848a27e449e9c0daaa5d354e29a4d4f..6b31ae33b61ff7e82d6eb4755aab777a2eae4262 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "qemu-common.h"
 #include "exec/cpu-all.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
 #include "qemu/bswap.h"
index 94b138fa467e3dd080b0f0bc792cafd634938b2f..807849c5741787660ea0aec73b8787154da49f29 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu-common.h"
-#include "irq.h"
-#include "exynos4210.h"
+#include "hw/irq.h"
+#include "hw/exynos4210.h"
 
 enum ExtGicId {
     EXT_GIC_ID_MDMA_LCD0 = 66,
index cefd736092d4377abb53984c48d318df99e1a8f2..9e428759a11a0584bdee4b61a612b5a1f4d401eb 100644 (file)
@@ -21,8 +21,8 @@
  */
 
 #include "qemu/timer.h"
-#include "sysbus.h"
-#include "i2c.h"
+#include "hw/sysbus.h"
+#include "hw/i2c.h"
 
 #ifndef EXYNOS4_I2C_DEBUG
 #define EXYNOS4_I2C_DEBUG                 0
index d7d5904cc00aea901d2ae43d46116989a678f01f..862c96212bc96f2aec551357f328c319d20aedd1 100644 (file)
  * there is no way to avoid frequently events).
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
-#include "exynos4210.h"
+#include "hw/exynos4210.h"
 
 //#define DEBUG_MCT
 
index 7c81a1b6283ead7d15ed5e50e69abe9b863feaad..ba5aa8d0e4805efcdd440b7e4b6c5dfa1a16753b 100644 (file)
@@ -24,7 +24,7 @@
  * uses PMU INFORM5 register as a holding pen.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #ifndef DEBUG_PMU
 #define DEBUG_PMU           0
index c8656248a816bbd67a0578331ceae50608ac86ff..6d74cd4db5fc1131d07fadd88c3bef4488e1311a 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
-#include "exynos4210.h"
+#include "hw/exynos4210.h"
 
 //#define DEBUG_PWM
 
index 5694a6207b238654eeb104ef41d206eda3a20f24..d170ca755ade22b5eb0b1ce4b91cbdfab80b107c 100644 (file)
  *  CLKOUTEN Bit[9] not used
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 
-#include "exynos4210.h"
+#include "hw/exynos4210.h"
 
 #define DEBUG_RTC 0
 
index bdf797a02915b78455c24c3ddfeb6f6b39e9390c..006f3d44fb1d8108051282a296d2fe5029ed159b 100644 (file)
  *
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "char/char.h"
 
-#include "exynos4210.h"
+#include "hw/exynos4210.h"
 
 #undef DEBUG_UART
 #undef DEBUG_UART_EXTEND
diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c
deleted file mode 100644 (file)
index b59e6aa..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- *  Samsung exynos4 SoC based boards emulation
- *
- *  Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *    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 "sysemu/sysemu.h"
-#include "sysbus.h"
-#include "net/net.h"
-#include "arm-misc.h"
-#include "exec/address-spaces.h"
-#include "exynos4210.h"
-#include "boards.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
-
-#define SMDK_LAN9118_BASE_ADDR      0x05000000
-
-typedef enum Exynos4BoardType {
-    EXYNOS4_BOARD_NURI,
-    EXYNOS4_BOARD_SMDKC210,
-    EXYNOS4_NUM_OF_BOARDS
-} Exynos4BoardType;
-
-static int exynos4_board_id[EXYNOS4_NUM_OF_BOARDS] = {
-    [EXYNOS4_BOARD_NURI]     = 0xD33,
-    [EXYNOS4_BOARD_SMDKC210] = 0xB16,
-};
-
-static int exynos4_board_smp_bootreg_addr[EXYNOS4_NUM_OF_BOARDS] = {
-    [EXYNOS4_BOARD_NURI]     = EXYNOS4210_SECOND_CPU_BOOTREG,
-    [EXYNOS4_BOARD_SMDKC210] = EXYNOS4210_SECOND_CPU_BOOTREG,
-};
-
-static unsigned long exynos4_board_ram_size[EXYNOS4_NUM_OF_BOARDS] = {
-    [EXYNOS4_BOARD_NURI]     = 0x40000000,
-    [EXYNOS4_BOARD_SMDKC210] = 0x40000000,
-};
-
-static struct arm_boot_info exynos4_board_binfo = {
-    .loader_start     = EXYNOS4210_BASE_BOOT_ADDR,
-    .smp_loader_start = EXYNOS4210_SMP_BOOT_ADDR,
-    .nb_cpus          = EXYNOS4210_NCPUS,
-    .write_secondary_boot = exynos4210_write_secondary,
-};
-
-static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS];
-
-static void lan9215_init(uint32_t base, qemu_irq irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    /* This should be a 9215 but the 9118 is close enough */
-    if (nd_table[0].used) {
-        qemu_check_nic_model(&nd_table[0], "lan9118");
-        dev = qdev_create(NULL, "lan9118");
-        qdev_set_nic_properties(dev, &nd_table[0]);
-        qdev_prop_set_uint32(dev, "mode_16bit", 1);
-        qdev_init_nofail(dev);
-        s = SYS_BUS_DEVICE(dev);
-        sysbus_mmio_map(s, 0, base);
-        sysbus_connect_irq(s, 0, irq);
-    }
-}
-
-static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
-                                                   Exynos4BoardType board_type)
-{
-    if (smp_cpus != EXYNOS4210_NCPUS) {
-        fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus"
-                " value.\n",
-                exynos4_machines[board_type].name,
-                exynos4_machines[board_type].max_cpus);
-    }
-
-    exynos4_board_binfo.ram_size = exynos4_board_ram_size[board_type];
-    exynos4_board_binfo.board_id = exynos4_board_id[board_type];
-    exynos4_board_binfo.smp_bootreg_addr =
-            exynos4_board_smp_bootreg_addr[board_type];
-    exynos4_board_binfo.kernel_filename = args->kernel_filename;
-    exynos4_board_binfo.initrd_filename = args->initrd_filename;
-    exynos4_board_binfo.kernel_cmdline = args->kernel_cmdline;
-    exynos4_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",
-            exynos4_board_ram_size[board_type] / 1048576,
-            exynos4_board_ram_size[board_type],
-            args->kernel_filename,
-            args->kernel_cmdline,
-            args->initrd_filename);
-
-    return exynos4210_init(get_system_memory(),
-            exynos4_board_ram_size[board_type]);
-}
-
-static void nuri_init(QEMUMachineInitArgs *args)
-{
-    exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI);
-
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
-}
-
-static void smdkc210_init(QEMUMachineInitArgs *args)
-{
-    Exynos4210State *s = exynos4_boards_init_common(args,
-                                                    EXYNOS4_BOARD_SMDKC210);
-
-    lan9215_init(SMDK_LAN9118_BASE_ADDR,
-            qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
-}
-
-static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS] = {
-    [EXYNOS4_BOARD_NURI] = {
-        .name = "nuri",
-        .desc = "Samsung NURI board (Exynos4210)",
-        .init = nuri_init,
-        .max_cpus = EXYNOS4210_NCPUS,
-        DEFAULT_MACHINE_OPTIONS,
-    },
-    [EXYNOS4_BOARD_SMDKC210] = {
-        .name = "smdkc210",
-        .desc = "Samsung SMDKC210 board (Exynos4210)",
-        .init = smdkc210_init,
-        .max_cpus = EXYNOS4210_NCPUS,
-        DEFAULT_MACHINE_OPTIONS,
-    },
-};
-
-static void exynos4_machine_init(void)
-{
-    qemu_register_machine(&exynos4_machines[EXYNOS4_BOARD_NURI]);
-    qemu_register_machine(&exynos4_machines[EXYNOS4_BOARD_SMDKC210]);
-}
-
-machine_init(exynos4_machine_init);
index 976a587c42f9976e8cf4b9207723dc5c39d2bf15..a4bb1290effed7aba5151f6c075143960a863758 100644 (file)
--- a/hw/fdc.c
+++ b/hw/fdc.c
  * way. There are changes in DOR register and DMA is not available.
  */
 
-#include "hw.h"
-#include "fdc.h"
+#include "hw/hw.h"
+#include "hw/fdc.h"
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
-#include "isa.h"
-#include "sysbus.h"
-#include "qdev-addr.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
+#include "hw/qdev-addr.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
diff --git a/hw/fifo.c b/hw/fifo.c
deleted file mode 100644 (file)
index 68a955a..0000000
--- a/hw/fifo.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Generic FIFO component, implemented as a circular buffer.
- *
- * Copyright (c) 2012 Peter A. G. Crosthwaite
- *
- * 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.
- *
- * 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 "fifo.h"
-
-void fifo8_create(Fifo8 *fifo, uint32_t capacity)
-{
-    fifo->data = g_new(uint8_t, capacity);
-    fifo->capacity = capacity;
-    fifo->head = 0;
-    fifo->num = 0;
-}
-
-void fifo8_destroy(Fifo8 *fifo)
-{
-    g_free(fifo->data);
-}
-
-void fifo8_push(Fifo8 *fifo, uint8_t data)
-{
-    if (fifo->num == fifo->capacity) {
-        abort();
-    }
-    fifo->data[(fifo->head + fifo->num) % fifo->capacity] = data;
-    fifo->num++;
-}
-
-uint8_t fifo8_pop(Fifo8 *fifo)
-{
-    uint8_t ret;
-
-    if (fifo->num == 0) {
-        abort();
-    }
-    ret = fifo->data[fifo->head++];
-    fifo->head %= fifo->capacity;
-    fifo->num--;
-    return ret;
-}
-
-void fifo8_reset(Fifo8 *fifo)
-{
-    fifo->num = 0;
-}
-
-bool fifo8_is_empty(Fifo8 *fifo)
-{
-    return (fifo->num == 0);
-}
-
-bool fifo8_is_full(Fifo8 *fifo)
-{
-    return (fifo->num == fifo->capacity);
-}
-
-const VMStateDescription vmstate_fifo8 = {
-    .name = "Fifo8",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
-        VMSTATE_UINT32(head, Fifo8),
-        VMSTATE_UINT32(num, Fifo8),
-        VMSTATE_END_OF_LIST()
-    }
-};
diff --git a/hw/fifo.h b/hw/fifo.h
deleted file mode 100644 (file)
index f23890a..0000000
--- a/hw/fifo.h
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef FIFO_H
-#define FIFO_H
-
-#include "hw.h"
-
-typedef struct {
-    /* All fields are private */
-    uint8_t *data;
-    uint32_t capacity;
-    uint32_t head;
-    uint32_t num;
-} Fifo8;
-
-/**
- * fifo8_create:
- * @fifo: struct Fifo8 to initialise with new FIFO
- * @capacity: capacity of the newly created FIFO
- *
- * Create a FIFO of the specified size. Clients should call fifo8_destroy()
- * when finished using the fifo. The FIFO is initially empty.
- */
-
-void fifo8_create(Fifo8 *fifo, uint32_t capacity);
-
-/**
- * fifo8_destroy:
- * @fifo: FIFO to cleanup
- *
- * Cleanup a FIFO created with fifo8_create(). Frees memory created for FIFO
-  *storage. The FIFO is no longer usable after this has been called.
- */
-
-void fifo8_destroy(Fifo8 *fifo);
-
-/**
- * fifo8_push:
- * @fifo: FIFO to push to
- * @data: data byte to push
- *
- * Push a data byte to the FIFO. Behaviour is undefined if the FIFO is full.
- * Clients are responsible for checking for fullness using fifo8_is_full().
- */
-
-void fifo8_push(Fifo8 *fifo, uint8_t data);
-
-/**
- * fifo8_pop:
- * @fifo: fifo to pop from
- *
- * Pop a data byte from the FIFO. Behaviour is undefined if the FIFO is empty.
- * Clients are responsible for checking for emptyness using fifo8_is_empty().
- *
- * Returns: The popped data byte.
- */
-
-uint8_t fifo8_pop(Fifo8 *fifo);
-
-/**
- * fifo8_reset:
- * @fifo: FIFO to reset
- *
- * Reset a FIFO. All data is discarded and the FIFO is emptied.
- */
-
-void fifo8_reset(Fifo8 *fifo);
-
-/**
- * fifo8_is_empty:
- * @fifo: FIFO to check
- *
- * Check if a FIFO is empty.
- *
- * Returns: True if the fifo is empty, false otherwise.
- */
-
-bool fifo8_is_empty(Fifo8 *fifo);
-
-/**
- * fifo8_is_full:
- * @fifo: FIFO to check
- *
- * Check if a FIFO is full.
- *
- * Returns: True if the fifo is full, false otherwise.
- */
-
-bool fifo8_is_full(Fifo8 *fifo);
-
-extern const VMStateDescription vmstate_fifo8;
-
-#define VMSTATE_FIFO8(_field, _state) {                              \
-    .name       = (stringify(_field)),                               \
-    .size       = sizeof(Fifo8),                                     \
-    .vmsd       = &vmstate_fifo8,                                    \
-    .flags      = VMS_STRUCT,                                        \
-    .offset     = vmstate_offset_value(_state, _field, Fifo8),       \
-}
-
-#endif /* FIFO_H */
index f0a023477db5f9074fc822179121ded489ee55ba..e50ba6c0ec06d50262dc40e8a12c8d560fdf1fe3 100644 (file)
@@ -39,7 +39,7 @@
 #include <stdarg.h>
 #include <math.h>
 //#include "driver.h"          /* use M.A.M.E. */
-#include "fmopl.h"
+#include "hw/fmopl.h"
 
 #ifndef PI
 #define PI 3.14159265358979323846
index 2a870961bc965155de650e81773c21a272a60648..d341aa0c6b8c9eb1659f05e99a90803b91ac7cec 100644 (file)
@@ -17,9 +17,9 @@
    - Remove all DisplayState knowledge from devices.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "framebuffer.h"
+#include "hw/framebuffer.h"
 
 /* Render an image from a shared memory framebuffer.  */
    
index 02618f248002e899e5bc3b82aa9f5b382e85cb50..63a199876cfe39412576af61acf7d514f563cb72 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/sysemu.h"
-#include "isa.h"
-#include "fw_cfg.h"
-#include "sysbus.h"
+#include "hw/isa.h"
+#include "hw/fw_cfg.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/error-report.h"
 #include "qemu/config-file.h"
index 0c0c8ba3028e01c07e661a75e4e96120c6abef84..7b69815bc980f5a06091bd2aedcf91319b8d1dd5 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
 #include "trace.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 typedef struct G364State {
     /* hardware */
index 95639d5735d34d2b4551f4442a1f5227c26e7c88..11e47d560e6e2eaaddd8f48b065fb1019a25f911 100644 (file)
@@ -23,9 +23,9 @@
  * THE SOFTWARE.
  */
 
-#include "pci/pci_host.h"
-#include "ppc/mac.h"
-#include "pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/ppc/mac.h"
+#include "hw/pci/pci.h"
 
 /* debug Grackle */
 //#define DEBUG_GRACKLE
index afd53892b05172a050feed7b205e36cdc760029a..470ce722506b1da5948506c4a2d0affa062129a8 100644 (file)
@@ -25,8 +25,8 @@
 #ifndef _GRLIB_H_
 #define _GRLIB_H_
 
-#include "qdev.h"
-#include "sysbus.h"
+#include "hw/qdev.h"
+#include "hw/sysbus.h"
 
 /* Emulation of GrLib device is base on the GRLIB IP Core User's Manual:
  * http://www.gaisler.com/products/grlib/grip.pdf
index ba1685afd1946ce4b2d8f1c7dd360e805df0f3d4..62f799083c8ad0874cc8e0d1342b8a70b0370155 100644 (file)
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 
 #include "trace.h"
index 7962b74f2c430a1b107c23bd9551868b08fb70ac..7043a346843f52d359e0cacba652f55d7e3db678 100644 (file)
@@ -22,9 +22,9 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
 #include "trace.h"
 
index ef8dd95ac9bd222a8f02b4f6851a38c2b3b26fe0..7ee469d1911ba9c15688acef210f632db77baca8 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "cpu.h"
 
-#include "grlib.h"
+#include "hw/grlib.h"
 
 #include "trace.h"
 
index 977a2c5e692e1f6e310067073e921754fcfd9a4f..c73a58a04518bd01cb1c42f3c54ed501dcb70be2 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "mips.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
-#include "pc.h"
+#include "hw/hw.h"
+#include "hw/mips.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pc.h"
 #include "exec/address-spaces.h"
 
 //#define DEBUG
diff --git a/hw/gumstix.c b/hw/gumstix.c
deleted file mode 100644 (file)
index bea1605..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Gumstix Platforms
- *
- * Copyright (c) 2007 by Thorsten Zitterell <info@bitmux.org>
- *
- * Code based on spitz platform by Andrzej Zaborowski <balrog@zabor.org>
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-/* 
- * Example usage:
- * 
- * connex:
- * =======
- * create image:
- * # dd of=flash bs=1k count=16k if=/dev/zero
- * # dd of=flash bs=1k conv=notrunc if=u-boot.bin
- * # dd of=flash bs=1k conv=notrunc seek=256 if=rootfs.arm_nofpu.jffs2
- * start it:
- * # qemu-system-arm -M connex -pflash flash -monitor null -nographic
- *
- * verdex:
- * =======
- * create image:
- * # dd of=flash bs=1k count=32k if=/dev/zero
- * # dd of=flash bs=1k conv=notrunc if=u-boot.bin
- * # dd of=flash bs=1k conv=notrunc seek=256 if=rootfs.arm_nofpu.jffs2
- * # dd of=flash bs=1k conv=notrunc seek=31744 if=uImage
- * start it:
- * # qemu-system-arm -M verdex -pflash flash -monitor null -nographic -m 289
- */
-
-#include "hw.h"
-#include "pxa.h"
-#include "net/net.h"
-#include "flash.h"
-#include "devices.h"
-#include "boards.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-static const int sector_len = 128 * 1024;
-
-static void connex_init(QEMUMachineInitArgs *args)
-{
-    PXA2xxState *cpu;
-    DriveInfo *dinfo;
-    int be;
-    MemoryRegion *address_space_mem = get_system_memory();
-
-    uint32_t connex_rom = 0x01000000;
-    uint32_t connex_ram = 0x04000000;
-
-    cpu = pxa255_init(address_space_mem, connex_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "A flash image must be given with the "
-                "'pflash' parameter\n");
-        exit(1);
-    }
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
-                               dinfo->bdrv, sector_len, connex_rom / sector_len,
-                               2, 0, 0, 0, 0, be)) {
-        fprintf(stderr, "qemu: Error registering flash memory.\n");
-        exit(1);
-    }
-
-    /* Interrupt line of NIC is connected to GPIO line 36 */
-    smc91c111_init(&nd_table[0], 0x04000300,
-                    qdev_get_gpio_in(cpu->gpio, 36));
-}
-
-static void verdex_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    PXA2xxState *cpu;
-    DriveInfo *dinfo;
-    int be;
-    MemoryRegion *address_space_mem = get_system_memory();
-
-    uint32_t verdex_rom = 0x02000000;
-    uint32_t verdex_ram = 0x10000000;
-
-    cpu = pxa270_init(address_space_mem, verdex_ram, cpu_model ?: "pxa270-c0");
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "A flash image must be given with the "
-                "'pflash' parameter\n");
-        exit(1);
-    }
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
-                               dinfo->bdrv, sector_len, verdex_rom / sector_len,
-                               2, 0, 0, 0, 0, be)) {
-        fprintf(stderr, "qemu: Error registering flash memory.\n");
-        exit(1);
-    }
-
-    /* Interrupt line of NIC is connected to GPIO line 99 */
-    smc91c111_init(&nd_table[0], 0x04000300,
-                    qdev_get_gpio_in(cpu->gpio, 99));
-}
-
-static QEMUMachine connex_machine = {
-    .name = "connex",
-    .desc = "Gumstix Connex (PXA255)",
-    .init = connex_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine verdex_machine = {
-    .name = "verdex",
-    .desc = "Gumstix Verdex (PXA270)",
-    .init = verdex_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void gumstix_machine_init(void)
-{
-    qemu_register_machine(&connex_machine);
-    qemu_register_machine(&verdex_machine);
-}
-
-machine_init(gumstix_machine_init);
index aa13fccf0d530a796179c57a89d3568ab6118201..d2682249ca5031763a312c69a70ede06a56b923c 100644 (file)
--- a/hw/gus.c
+++ b/hw/gus.c
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "isa.h"
-#include "gusemu.h"
-#include "gustate.h"
+#include "hw/isa.h"
+#include "hw/gusemu.h"
+#include "hw/gustate.h"
 
 #define dolog(...) AUD_log ("audio", __VA_ARGS__)
 #ifdef DEBUG
index 60966907351c8590f262ca6079665a0516424c25..0eee6176529c8c674079874f89ddf58481196365 100644 (file)
@@ -26,8 +26,8 @@
  * TODO: check mixer: see 7.20 of sdk for panning pos (applies to all gus models?)?
  */
 
-#include "gustate.h"
-#include "gusemu.h"
+#include "hw/gustate.h"
+#include "hw/gusemu.h"
 
 #define GUSregb(position) (*            (gusptr+(position)))
 #define GUSregw(position) (*(GUSword *) (gusptr+(position)))
index 6d8d9ced1178c2bcf0ec9ace96f4f6c200c77c2b..816c58a7ed76eef33cf4c0356492de575190cafc 100644 (file)
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "gusemu.h"
-#include "gustate.h"
+#include "hw/gusemu.h"
+#include "hw/gustate.h"
 
 #define GUSregb(position)  (*            (gusptr+(position)))
 #define GUSregw(position)  (*(GUSword *) (gusptr+(position)))
index 3190bd1cf840e5b328427fd772b2dd0037720422..6bdd8209fb963620523d3c49e1fd20c964f7f50f 100644 (file)
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "pci/pci.h"
-#include "intel-hda.h"
-#include "intel-hda-defs.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/intel-hda.h"
+#include "hw/intel-hda-defs.h"
 #include "audio/audio.h"
 
 /* -------------------------------------------------------------------------- */
index c0a71c3d5f201d665f030e6ad30967c81c7ea238..beb966118249b838758e0bfde1486b78737172eb 100644 (file)
@@ -22,8 +22,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc/mac.h"
+#include "hw/hw.h"
+#include "hw/ppc/mac.h"
 
 /* debug PIC */
 //#define DEBUG_PIC
index 89b5415c0fefcafa9ffd185a287c8f75cd8d21ff..28b34747ff82c4c772fc3d4d455a6bc7de472d96 100644 (file)
--- a/hw/hid.c
+++ b/hw/hid.c
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
 #include "qemu/timer.h"
-#include "hid.h"
+#include "hw/hid.h"
 
 #define HID_USAGE_ERROR_ROLLOVER        0x01
 #define HID_USAGE_POSTFAIL              0x02
diff --git a/hw/highbank.c b/hw/highbank.c
deleted file mode 100644 (file)
index defcc09..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Calxeda Highbank SoC emulation
- *
- * Copyright (c) 2010-2012 Calxeda
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2 or later, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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 "sysbus.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "loader.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "sysbus.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define SMP_BOOT_ADDR 0x100
-#define SMP_BOOT_REG  0x40
-#define GIC_BASE_ADDR 0xfff10000
-
-#define NIRQ_GIC      160
-
-/* Board init.  */
-
-static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
-{
-    int n;
-    uint32_t smpboot[] = {
-        0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
-        0xe210000f, /* ands r0, r0, #0x0f */
-        0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
-        0xe0830200, /* add r0, r3, r0, lsl #4 */
-        0xe59f2024, /* ldr r2, privbase */
-        0xe3a01001, /* mov r1, #1 */
-        0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */
-        0xe3a010ff, /* mov r1, #0xff */
-        0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */
-        0xf57ff04f, /* dsb */
-        0xe320f003, /* wfi */
-        0xe5901000, /* ldr     r1, [r0] */
-        0xe1110001, /* tst     r1, r1 */
-        0x0afffffb, /* beq     <wfi> */
-        0xe12fff11, /* bx      r1 */
-        GIC_BASE_ADDR      /* privbase: gic address.  */
-    };
-    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
-        smpboot[n] = tswap32(smpboot[n]);
-    }
-    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
-}
-
-static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
-{
-    CPUARMState *env = &cpu->env;
-
-    switch (info->nb_cpus) {
-    case 4:
-        stl_phys_notdirty(SMP_BOOT_REG + 0x30, 0);
-    case 3:
-        stl_phys_notdirty(SMP_BOOT_REG + 0x20, 0);
-    case 2:
-        stl_phys_notdirty(SMP_BOOT_REG + 0x10, 0);
-        env->regs[15] = SMP_BOOT_ADDR;
-        break;
-    default:
-        break;
-    }
-}
-
-#define NUM_REGS      0x200
-static void hb_regs_write(void *opaque, hwaddr offset,
-                          uint64_t value, unsigned size)
-{
-    uint32_t *regs = opaque;
-
-    if (offset == 0xf00) {
-        if (value == 1 || value == 2) {
-            qemu_system_reset_request();
-        } else if (value == 3) {
-            qemu_system_shutdown_request();
-        }
-    }
-
-    regs[offset/4] = value;
-}
-
-static uint64_t hb_regs_read(void *opaque, hwaddr offset,
-                             unsigned size)
-{
-    uint32_t *regs = opaque;
-    uint32_t value = regs[offset/4];
-
-    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
-        value |= 0x30000000;
-    }
-
-    return value;
-}
-
-static const MemoryRegionOps hb_mem_ops = {
-    .read = hb_regs_read,
-    .write = hb_regs_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion *iomem;
-    uint32_t regs[NUM_REGS];
-} HighbankRegsState;
-
-static VMStateDescription vmstate_highbank_regs = {
-    .name = "highbank-regs",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
-        VMSTATE_END_OF_LIST(),
-    },
-};
-
-static void highbank_regs_reset(DeviceState *dev)
-{
-    SysBusDevice *sys_dev = SYS_BUS_DEVICE(dev);
-    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, sys_dev);
-
-    s->regs[0x40] = 0x05F20121;
-    s->regs[0x41] = 0x2;
-    s->regs[0x42] = 0x05F30121;
-    s->regs[0x43] = 0x05F40121;
-}
-
-static int highbank_regs_init(SysBusDevice *dev)
-{
-    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev);
-
-    s->iomem = g_new(MemoryRegion, 1);
-    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
-                          0x1000);
-    sysbus_init_mmio(dev, s->iomem);
-
-    return 0;
-}
-
-static void highbank_regs_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    sbc->init = highbank_regs_init;
-    dc->desc = "Calxeda Highbank registers";
-    dc->vmsd = &vmstate_highbank_regs;
-    dc->reset = highbank_regs_reset;
-}
-
-static const TypeInfo highbank_regs_info = {
-    .name          = "highbank-regs",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(HighbankRegsState),
-    .class_init    = highbank_regs_class_init,
-};
-
-static void highbank_regs_register_types(void)
-{
-    type_register_static(&highbank_regs_info);
-}
-
-type_init(highbank_regs_register_types)
-
-static struct arm_boot_info highbank_binfo;
-
-/* ram_size must be set to match the upper bound of memory in the
- * device tree (linux/arch/arm/boot/dts/highbank.dts), which is
- * normally 0xff900000 or -m 4089. When running this board on a
- * 32-bit host, set the reg value of memory to 0xf7ff00000 in the
- * device tree and pass -m 2047 to QEMU.
- */
-static void highbank_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    DeviceState *dev;
-    SysBusDevice *busdev;
-    qemu_irq *irqp;
-    qemu_irq pic[128];
-    int n;
-    qemu_irq cpu_irq[4];
-    MemoryRegion *sysram;
-    MemoryRegion *dram;
-    MemoryRegion *sysmem;
-    char *sysboot_filename;
-
-    if (!cpu_model) {
-        cpu_model = "cortex-a9";
-    }
-
-    for (n = 0; n < smp_cpus; n++) {
-        ARMCPU *cpu;
-        cpu = cpu_arm_init(cpu_model);
-        if (cpu == NULL) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-
-        /* This will become a QOM property eventually */
-        cpu->reset_cbar = GIC_BASE_ADDR;
-        irqp = arm_pic_init_cpu(cpu);
-        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
-    }
-
-    sysmem = get_system_memory();
-    dram = g_new(MemoryRegion, 1);
-    memory_region_init_ram(dram, "highbank.dram", ram_size);
-    /* SDRAM at address zero.  */
-    memory_region_add_subregion(sysmem, 0, dram);
-
-    sysram = g_new(MemoryRegion, 1);
-    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
-    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
-    if (bios_name != NULL) {
-        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-        if (sysboot_filename != NULL) {
-            uint32_t filesize = get_image_size(sysboot_filename);
-            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
-                hw_error("Unable to load %s\n", bios_name);
-            }
-        } else {
-           hw_error("Unable to find %s\n", bios_name);
-        }
-    }
-
-    dev = qdev_create(NULL, "a9mpcore_priv");
-    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
-    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, GIC_BASE_ADDR);
-    for (n = 0; n < smp_cpus; n++) {
-        sysbus_connect_irq(busdev, n, cpu_irq[n]);
-    }
-
-    for (n = 0; n < 128; n++) {
-        pic[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    dev = qdev_create(NULL, "l2x0");
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0xfff12000);
-
-    dev = qdev_create(NULL, "sp804");
-    qdev_prop_set_uint32(dev, "freq0", 150000000);
-    qdev_prop_set_uint32(dev, "freq1", 150000000);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0xfff34000);
-    sysbus_connect_irq(busdev, 0, pic[18]);
-    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
-
-    dev = qdev_create(NULL, "highbank-regs");
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0xfff3c000);
-
-    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
-    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
-    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
-    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
-    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
-    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
-
-    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
-
-    if (nd_table[0].used) {
-        qemu_check_nic_model(&nd_table[0], "xgmac");
-        dev = qdev_create(NULL, "xgmac");
-        qdev_set_nic_properties(dev, &nd_table[0]);
-        qdev_init_nofail(dev);
-        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff50000);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[77]);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[78]);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[79]);
-
-        qemu_check_nic_model(&nd_table[1], "xgmac");
-        dev = qdev_create(NULL, "xgmac");
-        qdev_set_nic_properties(dev, &nd_table[1]);
-        qdev_init_nofail(dev);
-        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff51000);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[80]);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[81]);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[82]);
-    }
-
-    highbank_binfo.ram_size = ram_size;
-    highbank_binfo.kernel_filename = kernel_filename;
-    highbank_binfo.kernel_cmdline = kernel_cmdline;
-    highbank_binfo.initrd_filename = initrd_filename;
-    /* highbank requires a dtb in order to boot, and the dtb will override
-     * the board ID. The following value is ignored, so set it to -1 to be
-     * clear that the value is meaningless.
-     */
-    highbank_binfo.board_id = -1;
-    highbank_binfo.nb_cpus = smp_cpus;
-    highbank_binfo.loader_start = 0;
-    highbank_binfo.write_secondary_boot = hb_write_secondary;
-    highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &highbank_binfo);
-}
-
-static QEMUMachine highbank_machine = {
-    .name = "highbank",
-    .desc = "Calxeda Highbank (ECX-1000)",
-    .init = highbank_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void highbank_machine_init(void)
-{
-    qemu_register_machine(&highbank_machine);
-}
-
-machine_init(highbank_machine_init);
index 97eaa2f700a16c39df87d7610ee374a6fcb62641..6bfbf3a68ca69bd22d84709323b63796f9c1705e 100644 (file)
--- a/hw/hpet.c
+++ b/hw/hpet.c
  * This driver attempts to emulate an HPET device in software.
  */
 
-#include "hw.h"
-#include "pc.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
 #include "ui/console.h"
 #include "qemu/timer.h"
-#include "hpet_emul.h"
-#include "sysbus.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
+#include "hw/hpet_emul.h"
+#include "hw/sysbus.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
 
 //#define HPET_DEBUG
 #ifdef HPET_DEBUG
diff --git a/hw/hw.h b/hw/hw.h
index dfced97bbc1ce605cd5b2b6b8e1b0e272e879b21..1553e54aa740dce645aeeef49f4892a0e3a060cd 100644 (file)
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -9,7 +9,7 @@
 #endif
 
 #include "exec/ioport.h"
-#include "irq.h"
+#include "hw/irq.h"
 #include "block/aio.h"
 #include "migration/qemu-file.h"
 #include "migration/vmstate.h"
index ec314a40d1f2467f3f630c196094bd11bf730384..ad361cc57f98809dc6867971153c19ebcf7e1ba7 100644 (file)
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -7,7 +7,7 @@
  * This code is licensed under the LGPL.
  */
 
-#include "i2c.h"
+#include "hw/i2c.h"
 
 struct i2c_bus
 {
index 0e80d5a9cbd25a394f30a99510d4da41447b0e08..461392f3745c8f27c6567749ba7707a58f659654 100644 (file)
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_I2C_H
 #define QEMU_I2C_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 /* The QEMU I2C implementation only supports simple transfers that complete
    immediately.  It does not support slave devices that need to be able to
index 025803aa66680929237dfafe18b55055727ec832..a78c0b2921617a7ad9111197344a9abdc00f303b 100644 (file)
@@ -1,12 +1,11 @@
-obj-y += mc146818rtc.o pc.o
-obj-y += apic_common.o apic.o kvmvapic.o
+obj-y += mc146818rtc.o
+obj-y += apic_common.o apic.o
 obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o
 obj-y += vmport.o
-obj-y += pci/pci-hotplug.o smbios.o wdt_ib700.o
-obj-y += debugcon.o debugexit.o multiboot.o
-obj-y += pc_piix.o
+obj-y += pci/pci-hotplug.o wdt_ib700.o
+obj-y += debugcon.o debugexit.o
 obj-y += pc_sysfw.o
-obj-y += lpc_ich9.o q35.o pc_q35.o
+obj-y += lpc_ich9.o q35.o
 obj-$(CONFIG_XEN) += xen_platform.o xen_apic.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
@@ -15,3 +14,9 @@ obj-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
 obj-y += pc-testdev.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += multiboot.o smbios.o
+obj-y += pc.o pc_piix.o pc_q35.o
+obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
+
+obj-y += kvmvapic.o
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
new file mode 100644 (file)
index 0000000..c151c95
--- /dev/null
@@ -0,0 +1,822 @@
+/*
+ * TPR optimization for 32-bit Windows guests (XP and Server 2003)
+ *
+ * Copyright (C) 2007-2008 Qumranet Technologies
+ * Copyright (C) 2012      Jan Kiszka, Siemens AG
+ *
+ * This work is licensed under the terms of the GNU GPL version 2, or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+#include "sysemu/sysemu.h"
+#include "sysemu/cpus.h"
+#include "sysemu/kvm.h"
+#include "hw/apic_internal.h"
+
+#define APIC_DEFAULT_ADDRESS    0xfee00000
+
+#define VAPIC_IO_PORT           0x7e
+
+#define VAPIC_CPU_SHIFT         7
+
+#define ROM_BLOCK_SIZE          512
+#define ROM_BLOCK_MASK          (~(ROM_BLOCK_SIZE - 1))
+
+typedef enum VAPICMode {
+    VAPIC_INACTIVE = 0,
+    VAPIC_ACTIVE   = 1,
+    VAPIC_STANDBY  = 2,
+} VAPICMode;
+
+typedef struct VAPICHandlers {
+    uint32_t set_tpr;
+    uint32_t set_tpr_eax;
+    uint32_t get_tpr[8];
+    uint32_t get_tpr_stack;
+} QEMU_PACKED VAPICHandlers;
+
+typedef struct GuestROMState {
+    char signature[8];
+    uint32_t vaddr;
+    uint32_t fixup_start;
+    uint32_t fixup_end;
+    uint32_t vapic_vaddr;
+    uint32_t vapic_size;
+    uint32_t vcpu_shift;
+    uint32_t real_tpr_addr;
+    VAPICHandlers up;
+    VAPICHandlers mp;
+} QEMU_PACKED GuestROMState;
+
+typedef struct VAPICROMState {
+    SysBusDevice busdev;
+    MemoryRegion io;
+    MemoryRegion rom;
+    uint32_t state;
+    uint32_t rom_state_paddr;
+    uint32_t rom_state_vaddr;
+    uint32_t vapic_paddr;
+    uint32_t real_tpr_addr;
+    GuestROMState rom_state;
+    size_t rom_size;
+    bool rom_mapped_writable;
+} VAPICROMState;
+
+#define TPR_INSTR_ABS_MODRM             0x1
+#define TPR_INSTR_MATCH_MODRM_REG       0x2
+
+typedef struct TPRInstruction {
+    uint8_t opcode;
+    uint8_t modrm_reg;
+    unsigned int flags;
+    TPRAccess access;
+    size_t length;
+    off_t addr_offset;
+} TPRInstruction;
+
+/* must be sorted by length, shortest first */
+static const TPRInstruction tpr_instr[] = {
+    { /* mov abs to eax */
+        .opcode = 0xa1,
+        .access = TPR_ACCESS_READ,
+        .length = 5,
+        .addr_offset = 1,
+    },
+    { /* mov eax to abs */
+        .opcode = 0xa3,
+        .access = TPR_ACCESS_WRITE,
+        .length = 5,
+        .addr_offset = 1,
+    },
+    { /* mov r32 to r/m32 */
+        .opcode = 0x89,
+        .flags = TPR_INSTR_ABS_MODRM,
+        .access = TPR_ACCESS_WRITE,
+        .length = 6,
+        .addr_offset = 2,
+    },
+    { /* mov r/m32 to r32 */
+        .opcode = 0x8b,
+        .flags = TPR_INSTR_ABS_MODRM,
+        .access = TPR_ACCESS_READ,
+        .length = 6,
+        .addr_offset = 2,
+    },
+    { /* push r/m32 */
+        .opcode = 0xff,
+        .modrm_reg = 6,
+        .flags = TPR_INSTR_ABS_MODRM | TPR_INSTR_MATCH_MODRM_REG,
+        .access = TPR_ACCESS_READ,
+        .length = 6,
+        .addr_offset = 2,
+    },
+    { /* mov imm32, r/m32 (c7/0) */
+        .opcode = 0xc7,
+        .modrm_reg = 0,
+        .flags = TPR_INSTR_ABS_MODRM | TPR_INSTR_MATCH_MODRM_REG,
+        .access = TPR_ACCESS_WRITE,
+        .length = 10,
+        .addr_offset = 2,
+    },
+};
+
+static void read_guest_rom_state(VAPICROMState *s)
+{
+    cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
+                           sizeof(GuestROMState), 0);
+}
+
+static void write_guest_rom_state(VAPICROMState *s)
+{
+    cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
+                           sizeof(GuestROMState), 1);
+}
+
+static void update_guest_rom_state(VAPICROMState *s)
+{
+    read_guest_rom_state(s);
+
+    s->rom_state.real_tpr_addr = cpu_to_le32(s->real_tpr_addr);
+    s->rom_state.vcpu_shift = cpu_to_le32(VAPIC_CPU_SHIFT);
+
+    write_guest_rom_state(s);
+}
+
+static int find_real_tpr_addr(VAPICROMState *s, CPUX86State *env)
+{
+    hwaddr paddr;
+    target_ulong addr;
+
+    if (s->state == VAPIC_ACTIVE) {
+        return 0;
+    }
+    /*
+     * If there is no prior TPR access instruction we could analyze (which is
+     * the case after resume from hibernation), we need to scan the possible
+     * virtual address space for the APIC mapping.
+     */
+    for (addr = 0xfffff000; addr >= 0x80000000; addr -= TARGET_PAGE_SIZE) {
+        paddr = cpu_get_phys_page_debug(env, addr);
+        if (paddr != APIC_DEFAULT_ADDRESS) {
+            continue;
+        }
+        s->real_tpr_addr = addr + 0x80;
+        update_guest_rom_state(s);
+        return 0;
+    }
+    return -1;
+}
+
+static uint8_t modrm_reg(uint8_t modrm)
+{
+    return (modrm >> 3) & 7;
+}
+
+static bool is_abs_modrm(uint8_t modrm)
+{
+    return (modrm & 0xc7) == 0x05;
+}
+
+static bool opcode_matches(uint8_t *opcode, const TPRInstruction *instr)
+{
+    return opcode[0] == instr->opcode &&
+        (!(instr->flags & TPR_INSTR_ABS_MODRM) || is_abs_modrm(opcode[1])) &&
+        (!(instr->flags & TPR_INSTR_MATCH_MODRM_REG) ||
+         modrm_reg(opcode[1]) == instr->modrm_reg);
+}
+
+static int evaluate_tpr_instruction(VAPICROMState *s, CPUX86State *env,
+                                    target_ulong *pip, TPRAccess access)
+{
+    const TPRInstruction *instr;
+    target_ulong ip = *pip;
+    uint8_t opcode[2];
+    uint32_t real_tpr_addr;
+    int i;
+
+    if ((ip & 0xf0000000ULL) != 0x80000000ULL &&
+        (ip & 0xf0000000ULL) != 0xe0000000ULL) {
+        return -1;
+    }
+
+    /*
+     * Early Windows 2003 SMP initialization contains a
+     *
+     *   mov imm32, r/m32
+     *
+     * instruction that is patched by TPR optimization. The problem is that
+     * RSP, used by the patched instruction, is zero, so the guest gets a
+     * double fault and dies.
+     */
+    if (env->regs[R_ESP] == 0) {
+        return -1;
+    }
+
+    if (kvm_enabled() && !kvm_irqchip_in_kernel()) {
+        /*
+         * KVM without kernel-based TPR access reporting will pass an IP that
+         * points after the accessing instruction. So we need to look backward
+         * to find the reason.
+         */
+        for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
+            instr = &tpr_instr[i];
+            if (instr->access != access) {
+                continue;
+            }
+            if (cpu_memory_rw_debug(env, ip - instr->length, opcode,
+                                    sizeof(opcode), 0) < 0) {
+                return -1;
+            }
+            if (opcode_matches(opcode, instr)) {
+                ip -= instr->length;
+                goto instruction_ok;
+            }
+        }
+        return -1;
+    } else {
+        if (cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0) < 0) {
+            return -1;
+        }
+        for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
+            instr = &tpr_instr[i];
+            if (opcode_matches(opcode, instr)) {
+                goto instruction_ok;
+            }
+        }
+        return -1;
+    }
+
+instruction_ok:
+    /*
+     * Grab the virtual TPR address from the instruction
+     * and update the cached values.
+     */
+    if (cpu_memory_rw_debug(env, ip + instr->addr_offset,
+                            (void *)&real_tpr_addr,
+                            sizeof(real_tpr_addr), 0) < 0) {
+        return -1;
+    }
+    real_tpr_addr = le32_to_cpu(real_tpr_addr);
+    if ((real_tpr_addr & 0xfff) != 0x80) {
+        return -1;
+    }
+    s->real_tpr_addr = real_tpr_addr;
+    update_guest_rom_state(s);
+
+    *pip = ip;
+    return 0;
+}
+
+static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong ip)
+{
+    hwaddr paddr;
+    uint32_t rom_state_vaddr;
+    uint32_t pos, patch, offset;
+
+    /* nothing to do if already activated */
+    if (s->state == VAPIC_ACTIVE) {
+        return 0;
+    }
+
+    /* bail out if ROM init code was not executed (missing ROM?) */
+    if (s->state == VAPIC_INACTIVE) {
+        return -1;
+    }
+
+    /* find out virtual address of the ROM */
+    rom_state_vaddr = s->rom_state_paddr + (ip & 0xf0000000);
+    paddr = cpu_get_phys_page_debug(env, rom_state_vaddr);
+    if (paddr == -1) {
+        return -1;
+    }
+    paddr += rom_state_vaddr & ~TARGET_PAGE_MASK;
+    if (paddr != s->rom_state_paddr) {
+        return -1;
+    }
+    read_guest_rom_state(s);
+    if (memcmp(s->rom_state.signature, "kvm aPiC", 8) != 0) {
+        return -1;
+    }
+    s->rom_state_vaddr = rom_state_vaddr;
+
+    /* fixup addresses in ROM if needed */
+    if (rom_state_vaddr == le32_to_cpu(s->rom_state.vaddr)) {
+        return 0;
+    }
+    for (pos = le32_to_cpu(s->rom_state.fixup_start);
+         pos < le32_to_cpu(s->rom_state.fixup_end);
+         pos += 4) {
+        cpu_physical_memory_rw(paddr + pos - s->rom_state.vaddr,
+                               (void *)&offset, sizeof(offset), 0);
+        offset = le32_to_cpu(offset);
+        cpu_physical_memory_rw(paddr + offset, (void *)&patch,
+                               sizeof(patch), 0);
+        patch = le32_to_cpu(patch);
+        patch += rom_state_vaddr - le32_to_cpu(s->rom_state.vaddr);
+        patch = cpu_to_le32(patch);
+        cpu_physical_memory_rw(paddr + offset, (void *)&patch,
+                               sizeof(patch), 1);
+    }
+    read_guest_rom_state(s);
+    s->vapic_paddr = paddr + le32_to_cpu(s->rom_state.vapic_vaddr) -
+        le32_to_cpu(s->rom_state.vaddr);
+
+    return 0;
+}
+
+/*
+ * Tries to read the unique processor number from the Kernel Processor Control
+ * Region (KPCR) of 32-bit Windows XP and Server 2003. Returns -1 if the KPCR
+ * cannot be accessed or is considered invalid. This also ensures that we are
+ * not patching the wrong guest.
+ */
+static int get_kpcr_number(CPUX86State *env)
+{
+    struct kpcr {
+        uint8_t  fill1[0x1c];
+        uint32_t self;
+        uint8_t  fill2[0x31];
+        uint8_t  number;
+    } QEMU_PACKED kpcr;
+
+    if (cpu_memory_rw_debug(env, env->segs[R_FS].base,
+                            (void *)&kpcr, sizeof(kpcr), 0) < 0 ||
+        kpcr.self != env->segs[R_FS].base) {
+        return -1;
+    }
+    return kpcr.number;
+}
+
+static int vapic_enable(VAPICROMState *s, CPUX86State *env)
+{
+    int cpu_number = get_kpcr_number(env);
+    hwaddr vapic_paddr;
+    static const uint8_t enabled = 1;
+
+    if (cpu_number < 0) {
+        return -1;
+    }
+    vapic_paddr = s->vapic_paddr +
+        (((hwaddr)cpu_number) << VAPIC_CPU_SHIFT);
+    cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled),
+                           (void *)&enabled, sizeof(enabled), 1);
+    apic_enable_vapic(env->apic_state, vapic_paddr);
+
+    s->state = VAPIC_ACTIVE;
+
+    return 0;
+}
+
+static void patch_byte(CPUX86State *env, target_ulong addr, uint8_t byte)
+{
+    cpu_memory_rw_debug(env, addr, &byte, 1, 1);
+}
+
+static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip,
+                       uint32_t target)
+{
+    uint32_t offset;
+
+    offset = cpu_to_le32(target - ip - 5);
+    patch_byte(env, ip, 0xe8); /* call near */
+    cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1);
+}
+
+static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
+{
+    CPUState *cs = CPU(cpu);
+    CPUX86State *env = &cpu->env;
+    VAPICHandlers *handlers;
+    uint8_t opcode[2];
+    uint32_t imm32;
+    target_ulong current_pc = 0;
+    target_ulong current_cs_base = 0;
+    int current_flags = 0;
+
+    if (smp_cpus == 1) {
+        handlers = &s->rom_state.up;
+    } else {
+        handlers = &s->rom_state.mp;
+    }
+
+    if (!kvm_enabled()) {
+        cpu_restore_state(env, env->mem_io_pc);
+        cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
+                             &current_flags);
+    }
+
+    pause_all_vcpus();
+
+    cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0);
+
+    switch (opcode[0]) {
+    case 0x89: /* mov r32 to r/m32 */
+        patch_byte(env, ip, 0x50 + modrm_reg(opcode[1]));  /* push reg */
+        patch_call(s, env, ip + 1, handlers->set_tpr);
+        break;
+    case 0x8b: /* mov r/m32 to r32 */
+        patch_byte(env, ip, 0x90);
+        patch_call(s, env, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
+        break;
+    case 0xa1: /* mov abs to eax */
+        patch_call(s, env, ip, handlers->get_tpr[0]);
+        break;
+    case 0xa3: /* mov eax to abs */
+        patch_call(s, env, ip, handlers->set_tpr_eax);
+        break;
+    case 0xc7: /* mov imm32, r/m32 (c7/0) */
+        patch_byte(env, ip, 0x68);  /* push imm32 */
+        cpu_memory_rw_debug(env, ip + 6, (void *)&imm32, sizeof(imm32), 0);
+        cpu_memory_rw_debug(env, ip + 1, (void *)&imm32, sizeof(imm32), 1);
+        patch_call(s, env, ip + 5, handlers->set_tpr);
+        break;
+    case 0xff: /* push r/m32 */
+        patch_byte(env, ip, 0x50); /* push eax */
+        patch_call(s, env, ip + 1, handlers->get_tpr_stack);
+        break;
+    default:
+        abort();
+    }
+
+    resume_all_vcpus();
+
+    if (!kvm_enabled()) {
+        cs->current_tb = NULL;
+        tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
+        cpu_resume_from_signal(env, NULL);
+    }
+}
+
+void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip,
+                             TPRAccess access)
+{
+    VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
+    cpu_synchronize_state(env);
+
+    if (evaluate_tpr_instruction(s, env, &ip, access) < 0) {
+        if (s->state == VAPIC_ACTIVE) {
+            vapic_enable(s, env);
+        }
+        return;
+    }
+    if (update_rom_mapping(s, env, ip) < 0) {
+        return;
+    }
+    if (vapic_enable(s, env) < 0) {
+        return;
+    }
+    patch_instruction(s, cpu, ip);
+}
+
+typedef struct VAPICEnableTPRReporting {
+    DeviceState *apic;
+    bool enable;
+} VAPICEnableTPRReporting;
+
+static void vapic_do_enable_tpr_reporting(void *data)
+{
+    VAPICEnableTPRReporting *info = data;
+
+    apic_enable_tpr_access_reporting(info->apic, info->enable);
+}
+
+static void vapic_enable_tpr_reporting(bool enable)
+{
+    VAPICEnableTPRReporting info = {
+        .enable = enable,
+    };
+    X86CPU *cpu;
+    CPUX86State *env;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu = x86_env_get_cpu(env);
+        info.apic = env->apic_state;
+        run_on_cpu(CPU(cpu), vapic_do_enable_tpr_reporting, &info);
+    }
+}
+
+static void vapic_reset(DeviceState *dev)
+{
+    VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
+
+    if (s->state == VAPIC_ACTIVE) {
+        s->state = VAPIC_STANDBY;
+    }
+    vapic_enable_tpr_reporting(false);
+}
+
+/*
+ * Set the IRQ polling hypercalls to the supported variant:
+ *  - vmcall if using KVM in-kernel irqchip
+ *  - 32-bit VAPIC port write otherwise
+ */
+static int patch_hypercalls(VAPICROMState *s)
+{
+    hwaddr rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK;
+    static const uint8_t vmcall_pattern[] = { /* vmcall */
+        0xb8, 0x1, 0, 0, 0, 0xf, 0x1, 0xc1
+    };
+    static const uint8_t outl_pattern[] = { /* nop; outl %eax,0x7e */
+        0xb8, 0x1, 0, 0, 0, 0x90, 0xe7, 0x7e
+    };
+    uint8_t alternates[2];
+    const uint8_t *pattern;
+    const uint8_t *patch;
+    int patches = 0;
+    off_t pos;
+    uint8_t *rom;
+
+    rom = g_malloc(s->rom_size);
+    cpu_physical_memory_rw(rom_paddr, rom, s->rom_size, 0);
+
+    for (pos = 0; pos < s->rom_size - sizeof(vmcall_pattern); pos++) {
+        if (kvm_irqchip_in_kernel()) {
+            pattern = outl_pattern;
+            alternates[0] = outl_pattern[7];
+            alternates[1] = outl_pattern[7];
+            patch = &vmcall_pattern[5];
+        } else {
+            pattern = vmcall_pattern;
+            alternates[0] = vmcall_pattern[7];
+            alternates[1] = 0xd9; /* AMD's VMMCALL */
+            patch = &outl_pattern[5];
+        }
+        if (memcmp(rom + pos, pattern, 7) == 0 &&
+            (rom[pos + 7] == alternates[0] || rom[pos + 7] == alternates[1])) {
+            cpu_physical_memory_rw(rom_paddr + pos + 5, (uint8_t *)patch,
+                                   3, 1);
+            /*
+             * Don't flush the tb here. Under ordinary conditions, the patched
+             * calls are miles away from the current IP. Under malicious
+             * conditions, the guest could trick us to crash.
+             */
+        }
+    }
+
+    g_free(rom);
+
+    if (patches != 0 && patches != 2) {
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * For TCG mode or the time KVM honors read-only memory regions, we need to
+ * enable write access to the option ROM so that variables can be updated by
+ * the guest.
+ */
+static void vapic_map_rom_writable(VAPICROMState *s)
+{
+    hwaddr rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK;
+    MemoryRegionSection section;
+    MemoryRegion *as;
+    size_t rom_size;
+    uint8_t *ram;
+
+    as = sysbus_address_space(&s->busdev);
+
+    if (s->rom_mapped_writable) {
+        memory_region_del_subregion(as, &s->rom);
+        memory_region_destroy(&s->rom);
+    }
+
+    /* grab RAM memory region (region @rom_paddr may still be pc.rom) */
+    section = memory_region_find(as, 0, 1);
+
+    /* read ROM size from RAM region */
+    ram = memory_region_get_ram_ptr(section.mr);
+    rom_size = ram[rom_paddr + 2] * ROM_BLOCK_SIZE;
+    s->rom_size = rom_size;
+
+    /* We need to round to avoid creating subpages
+     * from which we cannot run code. */
+    rom_size += rom_paddr & ~TARGET_PAGE_MASK;
+    rom_paddr &= TARGET_PAGE_MASK;
+    rom_size = TARGET_PAGE_ALIGN(rom_size);
+
+    memory_region_init_alias(&s->rom, "kvmvapic-rom", section.mr, rom_paddr,
+                             rom_size);
+    memory_region_add_subregion_overlap(as, rom_paddr, &s->rom, 1000);
+    s->rom_mapped_writable = true;
+}
+
+static int vapic_prepare(VAPICROMState *s)
+{
+    vapic_map_rom_writable(s);
+
+    if (patch_hypercalls(s) < 0) {
+        return -1;
+    }
+
+    vapic_enable_tpr_reporting(true);
+
+    return 0;
+}
+
+static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
+                        unsigned int size)
+{
+    CPUX86State *env = cpu_single_env;
+    hwaddr rom_paddr;
+    VAPICROMState *s = opaque;
+
+    cpu_synchronize_state(env);
+
+    /*
+     * The VAPIC supports two PIO-based hypercalls, both via port 0x7E.
+     *  o 16-bit write access:
+     *    Reports the option ROM initialization to the hypervisor. Written
+     *    value is the offset of the state structure in the ROM.
+     *  o 8-bit write access:
+     *    Reactivates the VAPIC after a guest hibernation, i.e. after the
+     *    option ROM content has been re-initialized by a guest power cycle.
+     *  o 32-bit write access:
+     *    Poll for pending IRQs, considering the current VAPIC state.
+     */
+    switch (size) {
+    case 2:
+        if (s->state == VAPIC_INACTIVE) {
+            rom_paddr = (env->segs[R_CS].base + env->eip) & ROM_BLOCK_MASK;
+            s->rom_state_paddr = rom_paddr + data;
+
+            s->state = VAPIC_STANDBY;
+        }
+        if (vapic_prepare(s) < 0) {
+            s->state = VAPIC_INACTIVE;
+            break;
+        }
+        break;
+    case 1:
+        if (kvm_enabled()) {
+            /*
+             * Disable triggering instruction in ROM by writing a NOP.
+             *
+             * We cannot do this in TCG mode as the reported IP is not
+             * accurate.
+             */
+            pause_all_vcpus();
+            patch_byte(env, env->eip - 2, 0x66);
+            patch_byte(env, env->eip - 1, 0x90);
+            resume_all_vcpus();
+        }
+
+        if (s->state == VAPIC_ACTIVE) {
+            break;
+        }
+        if (update_rom_mapping(s, env, env->eip) < 0) {
+            break;
+        }
+        if (find_real_tpr_addr(s, env) < 0) {
+            break;
+        }
+        vapic_enable(s, env);
+        break;
+    default:
+    case 4:
+        if (!kvm_irqchip_in_kernel()) {
+            apic_poll_irq(env->apic_state);
+        }
+        break;
+    }
+}
+
+static const MemoryRegionOps vapic_ops = {
+    .write = vapic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int vapic_init(SysBusDevice *dev)
+{
+    VAPICROMState *s = FROM_SYSBUS(VAPICROMState, dev);
+
+    memory_region_init_io(&s->io, &vapic_ops, s, "kvmvapic", 2);
+    sysbus_add_io(dev, VAPIC_IO_PORT, &s->io);
+    sysbus_init_ioports(dev, VAPIC_IO_PORT, 2);
+
+    option_rom[nb_option_roms].name = "kvmvapic.bin";
+    option_rom[nb_option_roms].bootindex = -1;
+    nb_option_roms++;
+
+    return 0;
+}
+
+static void do_vapic_enable(void *data)
+{
+    VAPICROMState *s = data;
+
+    vapic_enable(s, first_cpu);
+}
+
+static int vapic_post_load(void *opaque, int version_id)
+{
+    VAPICROMState *s = opaque;
+    uint8_t *zero;
+
+    /*
+     * The old implementation of qemu-kvm did not provide the state
+     * VAPIC_STANDBY. Reconstruct it.
+     */
+    if (s->state == VAPIC_INACTIVE && s->rom_state_paddr != 0) {
+        s->state = VAPIC_STANDBY;
+    }
+
+    if (s->state != VAPIC_INACTIVE) {
+        if (vapic_prepare(s) < 0) {
+            return -1;
+        }
+    }
+    if (s->state == VAPIC_ACTIVE) {
+        if (smp_cpus == 1) {
+            run_on_cpu(ENV_GET_CPU(first_cpu), do_vapic_enable, s);
+        } else {
+            zero = g_malloc0(s->rom_state.vapic_size);
+            cpu_physical_memory_rw(s->vapic_paddr, zero,
+                                   s->rom_state.vapic_size, 1);
+            g_free(zero);
+        }
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_handlers = {
+    .name = "kvmvapic-handlers",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(set_tpr, VAPICHandlers),
+        VMSTATE_UINT32(set_tpr_eax, VAPICHandlers),
+        VMSTATE_UINT32_ARRAY(get_tpr, VAPICHandlers, 8),
+        VMSTATE_UINT32(get_tpr_stack, VAPICHandlers),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_guest_rom = {
+    .name = "kvmvapic-guest-rom",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UNUSED(8),     /* signature */
+        VMSTATE_UINT32(vaddr, GuestROMState),
+        VMSTATE_UINT32(fixup_start, GuestROMState),
+        VMSTATE_UINT32(fixup_end, GuestROMState),
+        VMSTATE_UINT32(vapic_vaddr, GuestROMState),
+        VMSTATE_UINT32(vapic_size, GuestROMState),
+        VMSTATE_UINT32(vcpu_shift, GuestROMState),
+        VMSTATE_UINT32(real_tpr_addr, GuestROMState),
+        VMSTATE_STRUCT(up, GuestROMState, 0, vmstate_handlers, VAPICHandlers),
+        VMSTATE_STRUCT(mp, GuestROMState, 0, vmstate_handlers, VAPICHandlers),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_vapic = {
+    .name = "kvm-tpr-opt",      /* compatible with qemu-kvm VAPIC */
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = vapic_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(rom_state, VAPICROMState, 0, vmstate_guest_rom,
+                       GuestROMState),
+        VMSTATE_UINT32(state, VAPICROMState),
+        VMSTATE_UINT32(real_tpr_addr, VAPICROMState),
+        VMSTATE_UINT32(rom_state_vaddr, VAPICROMState),
+        VMSTATE_UINT32(vapic_paddr, VAPICROMState),
+        VMSTATE_UINT32(rom_state_paddr, VAPICROMState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void vapic_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->no_user = 1;
+    dc->reset   = vapic_reset;
+    dc->vmsd    = &vmstate_vapic;
+    sc->init    = vapic_init;
+}
+
+static const TypeInfo vapic_type = {
+    .name          = "kvmvapic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(VAPICROMState),
+    .class_init    = vapic_class_init,
+};
+
+static void vapic_register(void)
+{
+    type_register_static(&vapic_type);
+}
+
+type_init(vapic_register);
diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c
new file mode 100644 (file)
index 0000000..3cb228f
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/fw_cfg.h"
+#include "hw/multiboot.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "sysemu/sysemu.h"
+
+/* Show multiboot debug output */
+//#define DEBUG_MULTIBOOT
+
+#ifdef DEBUG_MULTIBOOT
+#define mb_debug(a...) fprintf(stderr, ## a)
+#else
+#define mb_debug(a...)
+#endif
+
+#define MULTIBOOT_STRUCT_ADDR 0x9000
+
+#if MULTIBOOT_STRUCT_ADDR > 0xf0000
+#error multiboot struct needs to fit in 16 bit real mode
+#endif
+
+enum {
+    /* Multiboot info */
+    MBI_FLAGS       = 0,
+    MBI_MEM_LOWER   = 4,
+    MBI_MEM_UPPER   = 8,
+    MBI_BOOT_DEVICE = 12,
+    MBI_CMDLINE     = 16,
+    MBI_MODS_COUNT  = 20,
+    MBI_MODS_ADDR   = 24,
+    MBI_MMAP_ADDR   = 48,
+
+    MBI_SIZE        = 88,
+
+    /* Multiboot modules */
+    MB_MOD_START    = 0,
+    MB_MOD_END      = 4,
+    MB_MOD_CMDLINE  = 8,
+
+    MB_MOD_SIZE     = 16,
+
+    /* Region offsets */
+    ADDR_E820_MAP = MULTIBOOT_STRUCT_ADDR + 0,
+    ADDR_MBI      = ADDR_E820_MAP + 0x500,
+
+    /* Multiboot flags */
+    MULTIBOOT_FLAGS_MEMORY      = 1 << 0,
+    MULTIBOOT_FLAGS_BOOT_DEVICE = 1 << 1,
+    MULTIBOOT_FLAGS_CMDLINE     = 1 << 2,
+    MULTIBOOT_FLAGS_MODULES     = 1 << 3,
+    MULTIBOOT_FLAGS_MMAP        = 1 << 6,
+};
+
+typedef struct {
+    /* buffer holding kernel, cmdlines and mb_infos */
+    void *mb_buf;
+    /* address in target */
+    hwaddr mb_buf_phys;
+    /* size of mb_buf in bytes */
+    unsigned mb_buf_size;
+    /* offset of mb-info's in bytes */
+    hwaddr offset_mbinfo;
+    /* offset in buffer for cmdlines in bytes */
+    hwaddr offset_cmdlines;
+    /* offset of modules in bytes */
+    hwaddr offset_mods;
+    /* available slots for mb modules infos */
+    int mb_mods_avail;
+    /* currently used slots of mb modules */
+    int mb_mods_count;
+} MultibootState;
+
+static uint32_t mb_add_cmdline(MultibootState *s, const char *cmdline)
+{
+    hwaddr p = s->offset_cmdlines;
+    char *b = (char *)s->mb_buf + p;
+
+    get_opt_value(b, strlen(cmdline) + 1, cmdline);
+    s->offset_cmdlines += strlen(b) + 1;
+    return s->mb_buf_phys + p;
+}
+
+static void mb_add_mod(MultibootState *s,
+                       hwaddr start, hwaddr end,
+                       hwaddr cmdline_phys)
+{
+    char *p;
+    assert(s->mb_mods_count < s->mb_mods_avail);
+
+    p = (char *)s->mb_buf + s->offset_mbinfo + MB_MOD_SIZE * s->mb_mods_count;
+
+    stl_p(p + MB_MOD_START,   start);
+    stl_p(p + MB_MOD_END,     end);
+    stl_p(p + MB_MOD_CMDLINE, cmdline_phys);
+
+    mb_debug("mod%02d: "TARGET_FMT_plx" - "TARGET_FMT_plx"\n",
+             s->mb_mods_count, start, end);
+
+    s->mb_mods_count++;
+}
+
+int load_multiboot(void *fw_cfg,
+                   FILE *f,
+                   const char *kernel_filename,
+                   const char *initrd_filename,
+                   const char *kernel_cmdline,
+                   int kernel_file_size,
+                   uint8_t *header)
+{
+    int i, is_multiboot = 0;
+    uint32_t flags = 0;
+    uint32_t mh_entry_addr;
+    uint32_t mh_load_addr;
+    uint32_t mb_kernel_size;
+    MultibootState mbs;
+    uint8_t bootinfo[MBI_SIZE];
+    uint8_t *mb_bootinfo_data;
+
+    /* Ok, let's see if it is a multiboot image.
+       The header is 12x32bit long, so the latest entry may be 8192 - 48. */
+    for (i = 0; i < (8192 - 48); i += 4) {
+        if (ldl_p(header+i) == 0x1BADB002) {
+            uint32_t checksum = ldl_p(header+i+8);
+            flags = ldl_p(header+i+4);
+            checksum += flags;
+            checksum += (uint32_t)0x1BADB002;
+            if (!checksum) {
+                is_multiboot = 1;
+                break;
+            }
+        }
+    }
+
+    if (!is_multiboot)
+        return 0; /* no multiboot */
+
+    mb_debug("qemu: I believe we found a multiboot image!\n");
+    memset(bootinfo, 0, sizeof(bootinfo));
+    memset(&mbs, 0, sizeof(mbs));
+
+    if (flags & 0x00000004) { /* MULTIBOOT_HEADER_HAS_VBE */
+        fprintf(stderr, "qemu: multiboot knows VBE. we don't.\n");
+    }
+    if (!(flags & 0x00010000)) { /* MULTIBOOT_HEADER_HAS_ADDR */
+        uint64_t elf_entry;
+        uint64_t elf_low, elf_high;
+        int kernel_size;
+        fclose(f);
+
+        if (((struct elf64_hdr*)header)->e_machine == EM_X86_64) {
+            fprintf(stderr, "Cannot load x86-64 image, give a 32bit one.\n");
+            exit(1);
+        }
+
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                               &elf_low, &elf_high, 0, ELF_MACHINE, 0);
+        if (kernel_size < 0) {
+            fprintf(stderr, "Error while loading elf kernel\n");
+            exit(1);
+        }
+        mh_load_addr = elf_low;
+        mb_kernel_size = elf_high - elf_low;
+        mh_entry_addr = elf_entry;
+
+        mbs.mb_buf = g_malloc(mb_kernel_size);
+        if (rom_copy(mbs.mb_buf, mh_load_addr, mb_kernel_size) != mb_kernel_size) {
+            fprintf(stderr, "Error while fetching elf kernel from rom\n");
+            exit(1);
+        }
+
+        mb_debug("qemu: loading multiboot-elf kernel (%#x bytes) with entry %#zx\n",
+                  mb_kernel_size, (size_t)mh_entry_addr);
+    } else {
+        /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_ADDR. */
+        uint32_t mh_header_addr = ldl_p(header+i+12);
+        uint32_t mh_load_end_addr = ldl_p(header+i+20);
+        uint32_t mh_bss_end_addr = ldl_p(header+i+24);
+        mh_load_addr = ldl_p(header+i+16);
+        uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
+        uint32_t mb_load_size = 0;
+        mh_entry_addr = ldl_p(header+i+28);
+
+        if (mh_load_end_addr) {
+            mb_kernel_size = mh_bss_end_addr - mh_load_addr;
+            mb_load_size = mh_load_end_addr - mh_load_addr;
+        } else {
+            mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
+            mb_load_size = mb_kernel_size;
+        }
+
+        /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE.
+        uint32_t mh_mode_type = ldl_p(header+i+32);
+        uint32_t mh_width = ldl_p(header+i+36);
+        uint32_t mh_height = ldl_p(header+i+40);
+        uint32_t mh_depth = ldl_p(header+i+44); */
+
+        mb_debug("multiboot: mh_header_addr = %#x\n", mh_header_addr);
+        mb_debug("multiboot: mh_load_addr = %#x\n", mh_load_addr);
+        mb_debug("multiboot: mh_load_end_addr = %#x\n", mh_load_end_addr);
+        mb_debug("multiboot: mh_bss_end_addr = %#x\n", mh_bss_end_addr);
+        mb_debug("qemu: loading multiboot kernel (%#x bytes) at %#x\n",
+                 mb_load_size, mh_load_addr);
+
+        mbs.mb_buf = g_malloc(mb_kernel_size);
+        fseek(f, mb_kernel_text_offset, SEEK_SET);
+        if (fread(mbs.mb_buf, 1, mb_load_size, f) != mb_load_size) {
+            fprintf(stderr, "fread() failed\n");
+            exit(1);
+        }
+        memset(mbs.mb_buf + mb_load_size, 0, mb_kernel_size - mb_load_size);
+        fclose(f);
+    }
+
+    mbs.mb_buf_phys = mh_load_addr;
+
+    mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_kernel_size);
+    mbs.offset_mbinfo = mbs.mb_buf_size;
+
+    /* Calculate space for cmdlines and mb_mods */
+    mbs.mb_buf_size += strlen(kernel_filename) + 1;
+    mbs.mb_buf_size += strlen(kernel_cmdline) + 1;
+    if (initrd_filename) {
+        const char *r = initrd_filename;
+        mbs.mb_buf_size += strlen(r) + 1;
+        mbs.mb_mods_avail = 1;
+        while (*(r = get_opt_value(NULL, 0, r))) {
+           mbs.mb_mods_avail++;
+           r++;
+        }
+        mbs.mb_buf_size += MB_MOD_SIZE * mbs.mb_mods_avail;
+    }
+
+    mbs.mb_buf_size = TARGET_PAGE_ALIGN(mbs.mb_buf_size);
+
+    /* enlarge mb_buf to hold cmdlines and mb-info structs */
+    mbs.mb_buf          = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
+    mbs.offset_cmdlines = mbs.offset_mbinfo + mbs.mb_mods_avail * MB_MOD_SIZE;
+
+    if (initrd_filename) {
+        char *next_initrd, not_last;
+
+        mbs.offset_mods = mbs.mb_buf_size;
+
+        do {
+            char *next_space;
+            int mb_mod_length;
+            uint32_t offs = mbs.mb_buf_size;
+
+            next_initrd = (char *)get_opt_value(NULL, 0, initrd_filename);
+            not_last = *next_initrd;
+            *next_initrd = '\0';
+            /* if a space comes after the module filename, treat everything
+               after that as parameters */
+            hwaddr c = mb_add_cmdline(&mbs, initrd_filename);
+            if ((next_space = strchr(initrd_filename, ' ')))
+                *next_space = '\0';
+            mb_debug("multiboot loading module: %s\n", initrd_filename);
+            mb_mod_length = get_image_size(initrd_filename);
+            if (mb_mod_length < 0) {
+                fprintf(stderr, "Failed to open file '%s'\n", initrd_filename);
+                exit(1);
+            }
+
+            mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_mod_length + mbs.mb_buf_size);
+            mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
+
+            load_image(initrd_filename, (unsigned char *)mbs.mb_buf + offs);
+            mb_add_mod(&mbs, mbs.mb_buf_phys + offs,
+                       mbs.mb_buf_phys + offs + mb_mod_length, c);
+
+            mb_debug("mod_start: %p\nmod_end:   %p\n  cmdline: "TARGET_FMT_plx"\n",
+                     (char *)mbs.mb_buf + offs,
+                     (char *)mbs.mb_buf + offs + mb_mod_length, c);
+            initrd_filename = next_initrd+1;
+        } while (not_last);
+    }
+
+    /* Commandline support */
+    char kcmdline[strlen(kernel_filename) + strlen(kernel_cmdline) + 2];
+    snprintf(kcmdline, sizeof(kcmdline), "%s %s",
+             kernel_filename, kernel_cmdline);
+    stl_p(bootinfo + MBI_CMDLINE, mb_add_cmdline(&mbs, kcmdline));
+
+    stl_p(bootinfo + MBI_MODS_ADDR,  mbs.mb_buf_phys + mbs.offset_mbinfo);
+    stl_p(bootinfo + MBI_MODS_COUNT, mbs.mb_mods_count); /* mods_count */
+
+    /* the kernel is where we want it to be now */
+    stl_p(bootinfo + MBI_FLAGS, MULTIBOOT_FLAGS_MEMORY
+                                | MULTIBOOT_FLAGS_BOOT_DEVICE
+                                | MULTIBOOT_FLAGS_CMDLINE
+                                | MULTIBOOT_FLAGS_MODULES
+                                | MULTIBOOT_FLAGS_MMAP);
+    stl_p(bootinfo + MBI_MEM_LOWER,   640);
+    stl_p(bootinfo + MBI_MEM_UPPER,   (ram_size / 1024) - 1024);
+    stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8000ffff); /* XXX: use the -boot switch? */
+    stl_p(bootinfo + MBI_MMAP_ADDR,   ADDR_E820_MAP);
+
+    mb_debug("multiboot: mh_entry_addr = %#x\n", mh_entry_addr);
+    mb_debug("           mb_buf_phys   = "TARGET_FMT_plx"\n", mbs.mb_buf_phys);
+    mb_debug("           mod_start     = "TARGET_FMT_plx"\n", mbs.mb_buf_phys + mbs.offset_mods);
+    mb_debug("           mb_mods_count = %d\n", mbs.mb_mods_count);
+
+    /* save bootinfo off the stack */
+    mb_bootinfo_data = g_malloc(sizeof(bootinfo));
+    memcpy(mb_bootinfo_data, bootinfo, sizeof(bootinfo));
+
+    /* Pass variables to option rom */
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ENTRY, mh_entry_addr);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, mh_load_addr);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, mbs.mb_buf_size);
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA,
+                     mbs.mb_buf, mbs.mb_buf_size);
+
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, ADDR_MBI);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, sizeof(bootinfo));
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, mb_bootinfo_data,
+                     sizeof(bootinfo));
+
+    option_rom[nb_option_roms].name = "multiboot.bin";
+    option_rom[nb_option_roms].bootindex = 0;
+    nb_option_roms++;
+
+    return 1; /* yes, we are multiboot */
+}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
new file mode 100644 (file)
index 0000000..309bb83
--- /dev/null
@@ -0,0 +1,1161 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/apic.h"
+#include "hw/fdc.h"
+#include "hw/ide.h"
+#include "hw/pci/pci.h"
+#include "monitor/monitor.h"
+#include "hw/fw_cfg.h"
+#include "hw/hpet_emul.h"
+#include "hw/smbios.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/multiboot.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "hw/pcspk.h"
+#include "hw/pci/msi.h"
+#include "hw/sysbus.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "kvm_i386.h"
+#include "hw/xen.h"
+#include "sysemu/blockdev.h"
+#include "hw/block-common.h"
+#include "ui/qemu-spice.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "sysemu/arch_init.h"
+#include "qemu/bitmap.h"
+
+/* debug PC/ISA interrupts */
+//#define DEBUG_IRQ
+
+#ifdef DEBUG_IRQ
+#define DPRINTF(fmt, ...)                                       \
+    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables.  */
+#define ACPI_DATA_SIZE       0x10000
+#define BIOS_CFG_IOPORT 0x510
+#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
+#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
+#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
+#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
+#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
+
+#define E820_NR_ENTRIES                16
+
+struct e820_entry {
+    uint64_t address;
+    uint64_t length;
+    uint32_t type;
+} QEMU_PACKED __attribute((__aligned__(4)));
+
+struct e820_table {
+    uint32_t count;
+    struct e820_entry entry[E820_NR_ENTRIES];
+} QEMU_PACKED __attribute((__aligned__(4)));
+
+static struct e820_table e820_table;
+struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
+
+void gsi_handler(void *opaque, int n, int level)
+{
+    GSIState *s = opaque;
+
+    DPRINTF("pc: %s GSI %d\n", level ? "raising" : "lowering", n);
+    if (n < ISA_NUM_IRQS) {
+        qemu_set_irq(s->i8259_irq[n], level);
+    }
+    qemu_set_irq(s->ioapic_irq[n], level);
+}
+
+static void ioport80_write(void *opaque, hwaddr addr, uint64_t data,
+                           unsigned size)
+{
+}
+
+static uint64_t ioport80_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return 0xffffffffffffffffULL;
+}
+
+/* MSDOS compatibility mode FPU exception support */
+static qemu_irq ferr_irq;
+
+void pc_register_ferr_irq(qemu_irq irq)
+{
+    ferr_irq = irq;
+}
+
+/* XXX: add IGNNE support */
+void cpu_set_ferr(CPUX86State *s)
+{
+    qemu_irq_raise(ferr_irq);
+}
+
+static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
+                           unsigned size)
+{
+    qemu_irq_lower(ferr_irq);
+}
+
+static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return 0xffffffffffffffffULL;
+}
+
+/* TSC handling */
+uint64_t cpu_get_tsc(CPUX86State *env)
+{
+    return cpu_get_ticks();
+}
+
+/* SMM support */
+
+static cpu_set_smm_t smm_set;
+static void *smm_arg;
+
+void cpu_smm_register(cpu_set_smm_t callback, void *arg)
+{
+    assert(smm_set == NULL);
+    assert(smm_arg == NULL);
+    smm_set = callback;
+    smm_arg = arg;
+}
+
+void cpu_smm_update(CPUX86State *env)
+{
+    if (smm_set && smm_arg && env == first_cpu)
+        smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
+}
+
+
+/* IRQ handling */
+int cpu_get_pic_interrupt(CPUX86State *env)
+{
+    int intno;
+
+    intno = apic_get_interrupt(env->apic_state);
+    if (intno >= 0) {
+        return intno;
+    }
+    /* read the irq from the PIC */
+    if (!apic_accept_pic_intr(env->apic_state)) {
+        return -1;
+    }
+
+    intno = pic_read_irq(isa_pic);
+    return intno;
+}
+
+static void pic_irq_request(void *opaque, int irq, int level)
+{
+    CPUX86State *env = first_cpu;
+
+    DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
+    if (env->apic_state) {
+        while (env) {
+            if (apic_accept_pic_intr(env->apic_state)) {
+                apic_deliver_pic_intr(env->apic_state, level);
+            }
+            env = env->next_cpu;
+        }
+    } else {
+        if (level)
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        else
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+/* PC cmos mappings */
+
+#define REG_EQUIPMENT_BYTE          0x14
+
+static int cmos_get_fd_drive_type(FDriveType fd0)
+{
+    int val;
+
+    switch (fd0) {
+    case FDRIVE_DRV_144:
+        /* 1.44 Mb 3"5 drive */
+        val = 4;
+        break;
+    case FDRIVE_DRV_288:
+        /* 2.88 Mb 3"5 drive */
+        val = 5;
+        break;
+    case FDRIVE_DRV_120:
+        /* 1.2 Mb 5"5 drive */
+        val = 2;
+        break;
+    case FDRIVE_DRV_NONE:
+    default:
+        val = 0;
+        break;
+    }
+    return val;
+}
+
+static void cmos_init_hd(ISADevice *s, int type_ofs, int info_ofs,
+                         int16_t cylinders, int8_t heads, int8_t sectors)
+{
+    rtc_set_memory(s, type_ofs, 47);
+    rtc_set_memory(s, info_ofs, cylinders);
+    rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
+    rtc_set_memory(s, info_ofs + 2, heads);
+    rtc_set_memory(s, info_ofs + 3, 0xff);
+    rtc_set_memory(s, info_ofs + 4, 0xff);
+    rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3));
+    rtc_set_memory(s, info_ofs + 6, cylinders);
+    rtc_set_memory(s, info_ofs + 7, cylinders >> 8);
+    rtc_set_memory(s, info_ofs + 8, sectors);
+}
+
+/* convert boot_device letter to something recognizable by the bios */
+static int boot_device2nibble(char boot_device)
+{
+    switch(boot_device) {
+    case 'a':
+    case 'b':
+        return 0x01; /* floppy boot */
+    case 'c':
+        return 0x02; /* hard drive boot */
+    case 'd':
+        return 0x03; /* CD-ROM boot */
+    case 'n':
+        return 0x04; /* Network boot */
+    }
+    return 0;
+}
+
+static int set_boot_dev(ISADevice *s, const char *boot_device, int fd_bootchk)
+{
+#define PC_MAX_BOOT_DEVICES 3
+    int nbds, bds[3] = { 0, };
+    int i;
+
+    nbds = strlen(boot_device);
+    if (nbds > PC_MAX_BOOT_DEVICES) {
+        error_report("Too many boot devices for PC");
+        return(1);
+    }
+    for (i = 0; i < nbds; i++) {
+        bds[i] = boot_device2nibble(boot_device[i]);
+        if (bds[i] == 0) {
+            error_report("Invalid boot device for PC: '%c'",
+                         boot_device[i]);
+            return(1);
+        }
+    }
+    rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
+    rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1));
+    return(0);
+}
+
+static int pc_boot_set(void *opaque, const char *boot_device)
+{
+    return set_boot_dev(opaque, boot_device, 0);
+}
+
+typedef struct pc_cmos_init_late_arg {
+    ISADevice *rtc_state;
+    BusState *idebus[2];
+} pc_cmos_init_late_arg;
+
+static void pc_cmos_init_late(void *opaque)
+{
+    pc_cmos_init_late_arg *arg = opaque;
+    ISADevice *s = arg->rtc_state;
+    int16_t cylinders;
+    int8_t heads, sectors;
+    int val;
+    int i, trans;
+
+    val = 0;
+    if (ide_get_geometry(arg->idebus[0], 0,
+                         &cylinders, &heads, &sectors) >= 0) {
+        cmos_init_hd(s, 0x19, 0x1b, cylinders, heads, sectors);
+        val |= 0xf0;
+    }
+    if (ide_get_geometry(arg->idebus[0], 1,
+                         &cylinders, &heads, &sectors) >= 0) {
+        cmos_init_hd(s, 0x1a, 0x24, cylinders, heads, sectors);
+        val |= 0x0f;
+    }
+    rtc_set_memory(s, 0x12, val);
+
+    val = 0;
+    for (i = 0; i < 4; i++) {
+        /* NOTE: ide_get_geometry() returns the physical
+           geometry.  It is always such that: 1 <= sects <= 63, 1
+           <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
+           geometry can be different if a translation is done. */
+        if (ide_get_geometry(arg->idebus[i / 2], i % 2,
+                             &cylinders, &heads, &sectors) >= 0) {
+            trans = ide_get_bios_chs_trans(arg->idebus[i / 2], i % 2) - 1;
+            assert((trans & ~3) == 0);
+            val |= trans << (i * 2);
+        }
+    }
+    rtc_set_memory(s, 0x39, val);
+
+    qemu_unregister_reset(pc_cmos_init_late, opaque);
+}
+
+void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
+                  const char *boot_device,
+                  ISADevice *floppy, BusState *idebus0, BusState *idebus1,
+                  ISADevice *s)
+{
+    int val, nb, i;
+    FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
+    static pc_cmos_init_late_arg arg;
+
+    /* various important CMOS locations needed by PC/Bochs bios */
+
+    /* memory size */
+    /* base memory (first MiB) */
+    val = MIN(ram_size / 1024, 640);
+    rtc_set_memory(s, 0x15, val);
+    rtc_set_memory(s, 0x16, val >> 8);
+    /* extended memory (next 64MiB) */
+    if (ram_size > 1024 * 1024) {
+        val = (ram_size - 1024 * 1024) / 1024;
+    } else {
+        val = 0;
+    }
+    if (val > 65535)
+        val = 65535;
+    rtc_set_memory(s, 0x17, val);
+    rtc_set_memory(s, 0x18, val >> 8);
+    rtc_set_memory(s, 0x30, val);
+    rtc_set_memory(s, 0x31, val >> 8);
+    /* memory between 16MiB and 4GiB */
+    if (ram_size > 16 * 1024 * 1024) {
+        val = (ram_size - 16 * 1024 * 1024) / 65536;
+    } else {
+        val = 0;
+    }
+    if (val > 65535)
+        val = 65535;
+    rtc_set_memory(s, 0x34, val);
+    rtc_set_memory(s, 0x35, val >> 8);
+    /* memory above 4GiB */
+    val = above_4g_mem_size / 65536;
+    rtc_set_memory(s, 0x5b, val);
+    rtc_set_memory(s, 0x5c, val >> 8);
+    rtc_set_memory(s, 0x5d, val >> 16);
+
+    /* set the number of CPU */
+    rtc_set_memory(s, 0x5f, smp_cpus - 1);
+
+    /* set boot devices, and disable floppy signature check if requested */
+    if (set_boot_dev(s, boot_device, fd_bootchk)) {
+        exit(1);
+    }
+
+    /* floppy type */
+    if (floppy) {
+        for (i = 0; i < 2; i++) {
+            fd_type[i] = isa_fdc_get_drive_type(floppy, i);
+        }
+    }
+    val = (cmos_get_fd_drive_type(fd_type[0]) << 4) |
+        cmos_get_fd_drive_type(fd_type[1]);
+    rtc_set_memory(s, 0x10, val);
+
+    val = 0;
+    nb = 0;
+    if (fd_type[0] < FDRIVE_DRV_NONE) {
+        nb++;
+    }
+    if (fd_type[1] < FDRIVE_DRV_NONE) {
+        nb++;
+    }
+    switch (nb) {
+    case 0:
+        break;
+    case 1:
+        val |= 0x01; /* 1 drive, ready for boot */
+        break;
+    case 2:
+        val |= 0x41; /* 2 drives, ready for boot */
+        break;
+    }
+    val |= 0x02; /* FPU is there */
+    val |= 0x04; /* PS/2 mouse installed */
+    rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
+
+    /* hard drives */
+    arg.rtc_state = s;
+    arg.idebus[0] = idebus0;
+    arg.idebus[1] = idebus1;
+    qemu_register_reset(pc_cmos_init_late, &arg);
+}
+
+/* port 92 stuff: could be split off */
+typedef struct Port92State {
+    ISADevice dev;
+    MemoryRegion io;
+    uint8_t outport;
+    qemu_irq *a20_out;
+} Port92State;
+
+static void port92_write(void *opaque, hwaddr addr, uint64_t val,
+                         unsigned size)
+{
+    Port92State *s = opaque;
+
+    DPRINTF("port92: write 0x%02x\n", val);
+    s->outport = val;
+    qemu_set_irq(*s->a20_out, (val >> 1) & 1);
+    if (val & 1) {
+        qemu_system_reset_request();
+    }
+}
+
+static uint64_t port92_read(void *opaque, hwaddr addr,
+                            unsigned size)
+{
+    Port92State *s = opaque;
+    uint32_t ret;
+
+    ret = s->outport;
+    DPRINTF("port92: read 0x%02x\n", ret);
+    return ret;
+}
+
+static void port92_init(ISADevice *dev, qemu_irq *a20_out)
+{
+    Port92State *s = DO_UPCAST(Port92State, dev, dev);
+
+    s->a20_out = a20_out;
+}
+
+static const VMStateDescription vmstate_port92_isa = {
+    .name = "port92",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT8(outport, Port92State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void port92_reset(DeviceState *d)
+{
+    Port92State *s = container_of(d, Port92State, dev.qdev);
+
+    s->outport &= ~1;
+}
+
+static const MemoryRegionOps port92_ops = {
+    .read = port92_read,
+    .write = port92_write,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int port92_initfn(ISADevice *dev)
+{
+    Port92State *s = DO_UPCAST(Port92State, dev, dev);
+
+    memory_region_init_io(&s->io, &port92_ops, s, "port92", 1);
+    isa_register_ioport(dev, &s->io, 0x92);
+
+    s->outport = 0;
+    return 0;
+}
+
+static void port92_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+    ic->init = port92_initfn;
+    dc->no_user = 1;
+    dc->reset = port92_reset;
+    dc->vmsd = &vmstate_port92_isa;
+}
+
+static const TypeInfo port92_info = {
+    .name          = "port92",
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(Port92State),
+    .class_init    = port92_class_initfn,
+};
+
+static void port92_register_types(void)
+{
+    type_register_static(&port92_info);
+}
+
+type_init(port92_register_types)
+
+static void handle_a20_line_change(void *opaque, int irq, int level)
+{
+    X86CPU *cpu = opaque;
+
+    /* XXX: send to all CPUs ? */
+    /* XXX: add logic to handle multiple A20 line sources */
+    x86_cpu_set_a20(cpu, level);
+}
+
+int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
+{
+    int index = le32_to_cpu(e820_table.count);
+    struct e820_entry *entry;
+
+    if (index >= E820_NR_ENTRIES)
+        return -EBUSY;
+    entry = &e820_table.entry[index++];
+
+    entry->address = cpu_to_le64(address);
+    entry->length = cpu_to_le64(length);
+    entry->type = cpu_to_le32(type);
+
+    e820_table.count = cpu_to_le32(index);
+    return index;
+}
+
+/* Calculates the limit to CPU APIC ID values
+ *
+ * This function returns the limit for the APIC ID value, so that all
+ * CPU APIC IDs are < pc_apic_id_limit().
+ *
+ * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
+ */
+static unsigned int pc_apic_id_limit(unsigned int max_cpus)
+{
+    return x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
+}
+
+static void *bochs_bios_init(void)
+{
+    void *fw_cfg;
+    uint8_t *smbios_table;
+    size_t smbios_len;
+    uint64_t *numa_fw_cfg;
+    int i, j;
+    unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
+
+    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
+    /* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86:
+     *
+     * SeaBIOS needs FW_CFG_MAX_CPUS for CPU hotplug, but the CPU hotplug
+     * QEMU<->SeaBIOS interface is not based on the "CPU index", but on the APIC
+     * ID of hotplugged CPUs[1]. This means that FW_CFG_MAX_CPUS is not the
+     * "maximum number of CPUs", but the "limit to the APIC ID values SeaBIOS
+     * may see".
+     *
+     * So, this means we must not use max_cpus, here, but the maximum possible
+     * APIC ID value, plus one.
+     *
+     * [1] The only kind of "CPU identifier" used between SeaBIOS and QEMU is
+     *     the APIC ID, not the "CPU index"
+     */
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)apic_id_limit);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
+                     acpi_tables, acpi_tables_len);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
+
+    smbios_table = smbios_get_table(&smbios_len);
+    if (smbios_table)
+        fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
+                         smbios_table, smbios_len);
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
+                     &e820_table, sizeof(e820_table));
+
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, &hpet_cfg, sizeof(hpet_cfg));
+    /* allocate memory for the NUMA channel: one (64bit) word for the number
+     * of nodes, one word for each VCPU->node and one word for each node to
+     * hold the amount of memory.
+     */
+    numa_fw_cfg = g_new0(uint64_t, 1 + apic_id_limit + nb_numa_nodes);
+    numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
+    for (i = 0; i < max_cpus; i++) {
+        unsigned int apic_id = x86_cpu_apic_id_from_index(i);
+        assert(apic_id < apic_id_limit);
+        for (j = 0; j < nb_numa_nodes; j++) {
+            if (test_bit(i, node_cpumask[j])) {
+                numa_fw_cfg[apic_id + 1] = cpu_to_le64(j);
+                break;
+            }
+        }
+    }
+    for (i = 0; i < nb_numa_nodes; i++) {
+        numa_fw_cfg[apic_id_limit + 1 + i] = cpu_to_le64(node_mem[i]);
+    }
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg,
+                     (1 + apic_id_limit + nb_numa_nodes) *
+                     sizeof(*numa_fw_cfg));
+
+    return fw_cfg;
+}
+
+static long get_file_size(FILE *f)
+{
+    long where, size;
+
+    /* XXX: on Unix systems, using fstat() probably makes more sense */
+
+    where = ftell(f);
+    fseek(f, 0, SEEK_END);
+    size = ftell(f);
+    fseek(f, where, SEEK_SET);
+
+    return size;
+}
+
+static void load_linux(void *fw_cfg,
+                       const char *kernel_filename,
+                      const char *initrd_filename,
+                      const char *kernel_cmdline,
+                       hwaddr max_ram_size)
+{
+    uint16_t protocol;
+    int setup_size, kernel_size, initrd_size = 0, cmdline_size;
+    uint32_t initrd_max;
+    uint8_t header[8192], *setup, *kernel, *initrd_data;
+    hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
+    FILE *f;
+    char *vmode;
+
+    /* Align to 16 bytes as a paranoia measure */
+    cmdline_size = (strlen(kernel_cmdline)+16) & ~15;
+
+    /* load the kernel header */
+    f = fopen(kernel_filename, "rb");
+    if (!f || !(kernel_size = get_file_size(f)) ||
+       fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
+       MIN(ARRAY_SIZE(header), kernel_size)) {
+       fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
+               kernel_filename, strerror(errno));
+       exit(1);
+    }
+
+    /* kernel protocol version */
+#if 0
+    fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));
+#endif
+    if (ldl_p(header+0x202) == 0x53726448)
+       protocol = lduw_p(header+0x206);
+    else {
+       /* This looks like a multiboot kernel. If it is, let's stop
+          treating it like a Linux kernel. */
+        if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
+                           kernel_cmdline, kernel_size, header))
+            return;
+       protocol = 0;
+    }
+
+    if (protocol < 0x200 || !(header[0x211] & 0x01)) {
+       /* Low kernel */
+       real_addr    = 0x90000;
+       cmdline_addr = 0x9a000 - cmdline_size;
+       prot_addr    = 0x10000;
+    } else if (protocol < 0x202) {
+       /* High but ancient kernel */
+       real_addr    = 0x90000;
+       cmdline_addr = 0x9a000 - cmdline_size;
+       prot_addr    = 0x100000;
+    } else {
+       /* High and recent kernel */
+       real_addr    = 0x10000;
+       cmdline_addr = 0x20000;
+       prot_addr    = 0x100000;
+    }
+
+#if 0
+    fprintf(stderr,
+           "qemu: real_addr     = 0x" TARGET_FMT_plx "\n"
+           "qemu: cmdline_addr  = 0x" TARGET_FMT_plx "\n"
+           "qemu: prot_addr     = 0x" TARGET_FMT_plx "\n",
+           real_addr,
+           cmdline_addr,
+           prot_addr);
+#endif
+
+    /* highest address for loading the initrd */
+    if (protocol >= 0x203)
+       initrd_max = ldl_p(header+0x22c);
+    else
+       initrd_max = 0x37ffffff;
+
+    if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)
+       initrd_max = max_ram_size-ACPI_DATA_SIZE-1;
+
+    fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline)+1);
+    fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+
+    if (protocol >= 0x202) {
+       stl_p(header+0x228, cmdline_addr);
+    } else {
+       stw_p(header+0x20, 0xA33F);
+       stw_p(header+0x22, cmdline_addr-real_addr);
+    }
+
+    /* handle vga= parameter */
+    vmode = strstr(kernel_cmdline, "vga=");
+    if (vmode) {
+        unsigned int video_mode;
+        /* skip "vga=" */
+        vmode += 4;
+        if (!strncmp(vmode, "normal", 6)) {
+            video_mode = 0xffff;
+        } else if (!strncmp(vmode, "ext", 3)) {
+            video_mode = 0xfffe;
+        } else if (!strncmp(vmode, "ask", 3)) {
+            video_mode = 0xfffd;
+        } else {
+            video_mode = strtol(vmode, NULL, 0);
+        }
+        stw_p(header+0x1fa, video_mode);
+    }
+
+    /* loader type */
+    /* High nybble = B reserved for QEMU; low nybble is revision number.
+       If this code is substantially changed, you may want to consider
+       incrementing the revision. */
+    if (protocol >= 0x200)
+       header[0x210] = 0xB0;
+
+    /* heap */
+    if (protocol >= 0x201) {
+       header[0x211] |= 0x80;  /* CAN_USE_HEAP */
+       stw_p(header+0x224, cmdline_addr-real_addr-0x200);
+    }
+
+    /* load initrd */
+    if (initrd_filename) {
+       if (protocol < 0x200) {
+           fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
+           exit(1);
+       }
+
+       initrd_size = get_image_size(initrd_filename);
+        if (initrd_size < 0) {
+            fprintf(stderr, "qemu: error reading initrd %s\n",
+                    initrd_filename);
+            exit(1);
+        }
+
+        initrd_addr = (initrd_max-initrd_size) & ~4095;
+
+        initrd_data = g_malloc(initrd_size);
+        load_image(initrd_filename, initrd_data);
+
+        fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
+        fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
+        fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size);
+
+       stl_p(header+0x218, initrd_addr);
+       stl_p(header+0x21c, initrd_size);
+    }
+
+    /* load kernel and setup */
+    setup_size = header[0x1f1];
+    if (setup_size == 0)
+       setup_size = 4;
+    setup_size = (setup_size+1)*512;
+    kernel_size -= setup_size;
+
+    setup  = g_malloc(setup_size);
+    kernel = g_malloc(kernel_size);
+    fseek(f, 0, SEEK_SET);
+    if (fread(setup, 1, setup_size, f) != setup_size) {
+        fprintf(stderr, "fread() failed\n");
+        exit(1);
+    }
+    if (fread(kernel, 1, kernel_size, f) != kernel_size) {
+        fprintf(stderr, "fread() failed\n");
+        exit(1);
+    }
+    fclose(f);
+    memcpy(setup, header, MIN(sizeof(header), setup_size));
+
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
+
+    fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
+
+    option_rom[nb_option_roms].name = "linuxboot.bin";
+    option_rom[nb_option_roms].bootindex = 0;
+    nb_option_roms++;
+}
+
+#define NE2000_NB_MAX 6
+
+static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
+                                              0x280, 0x380 };
+static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
+
+static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
+static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
+
+void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
+{
+    static int nb_ne2k = 0;
+
+    if (nb_ne2k == NE2000_NB_MAX)
+        return;
+    isa_ne2000_init(bus, ne2000_io[nb_ne2k],
+                    ne2000_irq[nb_ne2k], nd);
+    nb_ne2k++;
+}
+
+DeviceState *cpu_get_current_apic(void)
+{
+    if (cpu_single_env) {
+        return cpu_single_env->apic_state;
+    } else {
+        return NULL;
+    }
+}
+
+void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
+{
+    CPUX86State *s = opaque;
+
+    if (level) {
+        cpu_interrupt(s, CPU_INTERRUPT_SMI);
+    }
+}
+
+void pc_cpus_init(const char *cpu_model)
+{
+    int i;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_X86_64
+        cpu_model = "qemu64";
+#else
+        cpu_model = "qemu32";
+#endif
+    }
+
+    for (i = 0; i < smp_cpus; i++) {
+        if (!cpu_x86_init(cpu_model)) {
+            exit(1);
+        }
+    }
+}
+
+void pc_acpi_init(const char *default_dsdt)
+{
+    char *filename = NULL, *arg = NULL;
+
+    if (acpi_tables != NULL) {
+        /* manually set via -acpitable, leave it alone */
+        return;
+    }
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt);
+    if (filename == NULL) {
+        fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt);
+        return;
+    }
+
+    arg = g_strdup_printf("file=%s", filename);
+    if (acpi_table_add(arg) != 0) {
+        fprintf(stderr, "WARNING: failed to load %s\n", filename);
+    }
+    g_free(arg);
+    g_free(filename);
+}
+
+void *pc_memory_init(MemoryRegion *system_memory,
+                    const char *kernel_filename,
+                    const char *kernel_cmdline,
+                    const char *initrd_filename,
+                    ram_addr_t below_4g_mem_size,
+                    ram_addr_t above_4g_mem_size,
+                    MemoryRegion *rom_memory,
+                    MemoryRegion **ram_memory)
+{
+    int linux_boot, i;
+    MemoryRegion *ram, *option_rom_mr;
+    MemoryRegion *ram_below_4g, *ram_above_4g;
+    void *fw_cfg;
+
+    linux_boot = (kernel_filename != NULL);
+
+    /* Allocate RAM.  We allocate it as a single memory region and use
+     * aliases to address portions of it, mostly for backwards compatibility
+     * with older qemus that used qemu_ram_alloc().
+     */
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, "pc.ram",
+                           below_4g_mem_size + above_4g_mem_size);
+    vmstate_register_ram_global(ram);
+    *ram_memory = ram;
+    ram_below_4g = g_malloc(sizeof(*ram_below_4g));
+    memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
+                             0, below_4g_mem_size);
+    memory_region_add_subregion(system_memory, 0, ram_below_4g);
+    if (above_4g_mem_size > 0) {
+        ram_above_4g = g_malloc(sizeof(*ram_above_4g));
+        memory_region_init_alias(ram_above_4g, "ram-above-4g", ram,
+                                 below_4g_mem_size, above_4g_mem_size);
+        memory_region_add_subregion(system_memory, 0x100000000ULL,
+                                    ram_above_4g);
+    }
+
+
+    /* Initialize PC system firmware */
+    pc_system_firmware_init(rom_memory);
+
+    option_rom_mr = g_malloc(sizeof(*option_rom_mr));
+    memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE);
+    vmstate_register_ram_global(option_rom_mr);
+    memory_region_add_subregion_overlap(rom_memory,
+                                        PC_ROM_MIN_VGA,
+                                        option_rom_mr,
+                                        1);
+
+    fw_cfg = bochs_bios_init();
+    rom_set_fw(fw_cfg);
+
+    if (linux_boot) {
+        load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
+    }
+
+    for (i = 0; i < nb_option_roms; i++) {
+        rom_add_option(option_rom[i].name, option_rom[i].bootindex);
+    }
+    return fw_cfg;
+}
+
+qemu_irq *pc_allocate_cpu_irq(void)
+{
+    return qemu_allocate_irqs(pic_irq_request, NULL, 1);
+}
+
+DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
+{
+    DeviceState *dev = NULL;
+
+    if (pci_bus) {
+        PCIDevice *pcidev = pci_vga_init(pci_bus);
+        dev = pcidev ? &pcidev->qdev : NULL;
+    } else if (isa_bus) {
+        ISADevice *isadev = isa_vga_init(isa_bus);
+        dev = isadev ? &isadev->qdev : NULL;
+    }
+    return dev;
+}
+
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+    CPUX86State *env = cpu_single_env;
+
+    if (env && level) {
+        cpu_exit(env);
+    }
+}
+
+static const MemoryRegionOps ioport80_io_ops = {
+    .write = ioport80_write,
+    .read = ioport80_read,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+static const MemoryRegionOps ioportF0_io_ops = {
+    .write = ioportF0_write,
+    .read = ioportF0_read,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
+                          ISADevice **rtc_state,
+                          ISADevice **floppy,
+                          bool no_vmport)
+{
+    int i;
+    DriveInfo *fd[MAX_FD];
+    DeviceState *hpet = NULL;
+    int pit_isa_irq = 0;
+    qemu_irq pit_alt_irq = NULL;
+    qemu_irq rtc_irq = NULL;
+    qemu_irq *a20_line;
+    ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
+    qemu_irq *cpu_exit_irq;
+    MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
+    MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
+
+    memory_region_init_io(ioport80_io, &ioport80_io_ops, NULL, "ioport80", 1);
+    memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io);
+
+    memory_region_init_io(ioportF0_io, &ioportF0_io_ops, NULL, "ioportF0", 1);
+    memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
+
+    /*
+     * Check if an HPET shall be created.
+     *
+     * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT
+     * when the HPET wants to take over. Thus we have to disable the latter.
+     */
+    if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {
+        hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
+
+        if (hpet) {
+            for (i = 0; i < GSI_NUM_PINS; i++) {
+                sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]);
+            }
+            pit_isa_irq = -1;
+            pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
+            rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);
+        }
+    }
+    *rtc_state = rtc_init(isa_bus, 2000, rtc_irq);
+
+    qemu_register_boot_set(pc_boot_set, *rtc_state);
+
+    if (!xen_enabled()) {
+        if (kvm_irqchip_in_kernel()) {
+            pit = kvm_pit_init(isa_bus, 0x40);
+        } else {
+            pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
+        }
+        if (hpet) {
+            /* connect PIT to output control line of the HPET */
+            qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
+        }
+        pcspk_init(isa_bus, pit);
+    }
+
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_isa_init(isa_bus, i, serial_hds[i]);
+        }
+    }
+
+    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
+        if (parallel_hds[i]) {
+            parallel_init(isa_bus, i, parallel_hds[i]);
+        }
+    }
+
+    a20_line = qemu_allocate_irqs(handle_a20_line_change,
+                                  x86_env_get_cpu(first_cpu), 2);
+    i8042 = isa_create_simple(isa_bus, "i8042");
+    i8042_setup_a20_line(i8042, &a20_line[0]);
+    if (!no_vmport) {
+        vmport_init(isa_bus);
+        vmmouse = isa_try_create(isa_bus, "vmmouse");
+    } else {
+        vmmouse = NULL;
+    }
+    if (vmmouse) {
+        qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
+        qdev_init_nofail(&vmmouse->qdev);
+    }
+    port92 = isa_create_simple(isa_bus, "port92");
+    port92_init(port92, &a20_line[1]);
+
+    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+    DMA_init(0, cpu_exit_irq);
+
+    for(i = 0; i < MAX_FD; i++) {
+        fd[i] = drive_get(IF_FLOPPY, 0, i);
+    }
+    *floppy = fdctrl_init_isa(isa_bus, fd);
+}
+
+void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus)
+{
+    int i;
+
+    for (i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+
+        if (!pci_bus || (nd->model && strcmp(nd->model, "ne2k_isa") == 0)) {
+            pc_init_ne2k_isa(isa_bus, nd);
+        } else {
+            pci_nic_init_nofail(nd, "e1000", NULL);
+        }
+    }
+}
+
+void pc_pci_device_init(PCIBus *pci_bus)
+{
+    int max_bus;
+    int bus;
+
+    max_bus = drive_get_max_bus(IF_SCSI);
+    for (bus = 0; bus <= max_bus; bus++) {
+        pci_create_simple(pci_bus, -1, "lsi53c895a");
+    }
+}
+
+void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
+{
+    DeviceState *dev;
+    SysBusDevice *d;
+    unsigned int i;
+
+    if (kvm_irqchip_in_kernel()) {
+        dev = qdev_create(NULL, "kvm-ioapic");
+    } else {
+        dev = qdev_create(NULL, "ioapic");
+    }
+    if (parent_name) {
+        object_property_add_child(object_resolve_path(parent_name, NULL),
+                                  "ioapic", OBJECT(dev), NULL);
+    }
+    qdev_init_nofail(dev);
+    d = SYS_BUS_DEVICE(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);
+    }
+}
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
new file mode 100644 (file)
index 0000000..0ee3b3b
--- /dev/null
@@ -0,0 +1,717 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <glib.h>
+
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/apic.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/usb.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "hw/ide.h"
+#include "sysemu/kvm.h"
+#include "hw/kvm/clock.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/blockdev.h"
+#include "hw/smbus.h"
+#include "hw/xen.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "cpu.h"
+#ifdef CONFIG_XEN
+#  include <xen/hvm/hvm_info_table.h>
+#endif
+
+#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 };
+
+/* PC hardware initialisation */
+static void pc_init1(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);
+    pc_acpi_init("acpi-dsdt.aml");
+
+    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()) {
+        fw_cfg = pc_memory_init(system_memory,
+                       kernel_filename, kernel_cmdline, initrd_filename,
+                       below_4g_mem_size, above_4g_mem_size,
+                       rom_memory, &ram_memory);
+    }
+
+    gsi_state = g_malloc0(sizeof(*gsi_state));
+    if (kvm_irqchip_in_kernel()) {
+        kvm_pc_setup_irq_routing(pci_enabled);
+        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
+                                 GSI_NUM_PINS);
+    } else {
+        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+    }
+
+    if (pci_enabled) {
+        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
+                              system_memory, system_io, ram_size,
+                              below_4g_mem_size,
+                              0x100000000ULL - below_4g_mem_size,
+                              0x100000000ULL + above_4g_mem_size,
+                              (sizeof(hwaddr) == 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(gsi_state, "i440fx");
+    }
+
+    pc_register_ferr_irq(gsi[13]);
+
+    pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
+    if (xen_enabled()) {
+        pci_create_simple(pci_bus, -1, "xen-platform");
+    }
+
+    /* init basic PC hardware */
+    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());
+
+    pc_nic_init(isa_bus, pci_bus);
+
+    ide_drive_get(hd, MAX_IDE_BUS);
+    if (pci_enabled) {
+        PCIDevice *dev;
+        if (xen_enabled()) {
+            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
+        } else {
+            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
+        }
+        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
+        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
+    } else {
+        for(i = 0; i < MAX_IDE_BUS; i++) {
+            ISADevice *dev;
+            dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
+                               ide_irq[i],
+                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
+            idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
+        }
+    }
+
+    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(false)) {
+        pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
+    }
+
+    if (pci_enabled && acpi_enabled) {
+        i2c_bus *smbus;
+
+        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
+        /* TODO: Populate SPD eeprom data.  */
+        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
+                              gsi[9], *smi_irq,
+                              kvm_enabled(), fw_cfg);
+        smbus_eeprom_init(smbus, 8, NULL, 0);
+    }
+
+    if (pci_enabled) {
+        pc_pci_device_init(pci_bus);
+    }
+}
+
+static void pc_init_pci(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    pc_init1(get_system_memory(),
+             get_system_io(),
+             ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 1, 1);
+}
+
+static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
+{
+    enable_compat_apic_id_mode();
+    pc_init_pci(args);
+}
+
+/* PC machine init function for pc-0.14 to pc-1.2 */
+static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
+{
+    disable_kvm_pv_eoi();
+    pc_init_pci_1_3(args);
+}
+
+/* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
+static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    disable_kvm_pv_eoi();
+    enable_compat_apic_id_mode();
+    pc_init1(get_system_memory(),
+             get_system_io(),
+             ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 1, 0);
+}
+
+static void pc_init_isa(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    if (cpu_model == NULL)
+        cpu_model = "486";
+    disable_kvm_pv_eoi();
+    enable_compat_apic_id_mode();
+    pc_init1(get_system_memory(),
+             get_system_io(),
+             ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 0, 1);
+}
+
+#ifdef CONFIG_XEN
+static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
+{
+    if (xen_hvm_init() != 0) {
+        hw_error("xen hardware virtual machine initialisation failed");
+    }
+    pc_init_pci_no_kvmclock(args);
+    xen_vcpu_init();
+}
+#endif
+
+static QEMUMachine pc_i440fx_machine_v1_5 = {
+    .name = "pc-i440fx-1.5",
+    .alias = "pc",
+    .desc = "Standard PC (i440FX + PIIX, 1996)",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine pc_i440fx_machine_v1_4 = {
+    .name = "pc-i440fx-1.4",
+    .desc = "Standard PC (i440FX + PIIX, 1996)",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_4,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_1_3 \
+       PC_COMPAT_1_4, \
+        {\
+            .driver   = "usb-tablet",\
+            .property = "usb_version",\
+            .value    = stringify(1),\
+        },{\
+            .driver   = "virtio-net-pci",\
+            .property = "ctrl_mac_addr",\
+            .value    = "off",      \
+        },{ \
+            .driver   = "virtio-net-pci", \
+            .property = "mq", \
+            .value    = "off", \
+        }, {\
+            .driver   = "e1000",\
+            .property = "autonegotiation",\
+            .value    = "off",\
+        }
+
+static QEMUMachine pc_machine_v1_3 = {
+    .name = "pc-1.3",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_3,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_3,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_1_2 \
+        PC_COMPAT_1_3,\
+        {\
+            .driver   = "nec-usb-xhci",\
+            .property = "msi",\
+            .value    = "off",\
+        },{\
+            .driver   = "nec-usb-xhci",\
+            .property = "msix",\
+            .value    = "off",\
+        },{\
+            .driver   = "ivshmem",\
+            .property = "use64",\
+            .value    = "0",\
+        },{\
+            .driver   = "qxl",\
+            .property = "revision",\
+            .value    = stringify(3),\
+        },{\
+            .driver   = "qxl-vga",\
+            .property = "revision",\
+            .value    = stringify(3),\
+        },{\
+            .driver   = "VGA",\
+            .property = "mmio",\
+            .value    = "off",\
+        }
+
+static QEMUMachine pc_machine_v1_2 = {
+    .name = "pc-1.2",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_2,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_2,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_1_1 \
+        PC_COMPAT_1_2,\
+        {\
+            .driver   = "virtio-scsi-pci",\
+            .property = "hotplug",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-scsi-pci",\
+            .property = "param_change",\
+            .value    = "off",\
+        },{\
+            .driver   = "VGA",\
+            .property = "vgamem_mb",\
+            .value    = stringify(8),\
+        },{\
+            .driver   = "vmware-svga",\
+            .property = "vgamem_mb",\
+            .value    = stringify(8),\
+        },{\
+            .driver   = "qxl-vga",\
+            .property = "vgamem_mb",\
+            .value    = stringify(8),\
+        },{\
+            .driver   = "qxl",\
+            .property = "vgamem_mb",\
+            .value    = stringify(8),\
+        },{\
+            .driver   = "virtio-blk-pci",\
+            .property = "config-wce",\
+            .value    = "off",\
+        }
+
+static QEMUMachine pc_machine_v1_1 = {
+    .name = "pc-1.1",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_2,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_1,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_1_0 \
+        PC_COMPAT_1_1,\
+        {\
+            .driver   = "pc-sysfw",\
+            .property = "rom_only",\
+            .value    = stringify(1),\
+        }, {\
+            .driver   = "isa-fdc",\
+            .property = "check_media_rate",\
+            .value    = "off",\
+        }, {\
+            .driver   = "virtio-balloon-pci",\
+            .property = "class",\
+            .value    = stringify(PCI_CLASS_MEMORY_RAM),\
+        },{\
+            .driver   = "apic",\
+            .property = "vapic",\
+            .value    = "off",\
+        },{\
+            .driver   = TYPE_USB_DEVICE,\
+            .property = "full-path",\
+            .value    = "no",\
+        }
+
+static QEMUMachine pc_machine_v1_0 = {
+    .name = "pc-1.0",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_2,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_0,
+        { /* end of list */ }
+    },
+    .hw_version = "1.0",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_0_15 \
+        PC_COMPAT_1_0
+
+static QEMUMachine pc_machine_v0_15 = {
+    .name = "pc-0.15",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_2,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_15,
+        { /* end of list */ }
+    },
+    .hw_version = "0.15",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_0_14 \
+        PC_COMPAT_0_15,\
+        {\
+            .driver   = "virtio-blk-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-serial-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-net-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-balloon-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        }
+
+static QEMUMachine pc_machine_v0_14 = {
+    .name = "pc-0.14",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_2,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_14, 
+        {
+            .driver   = "qxl",
+            .property = "revision",
+            .value    = stringify(2),
+        },{
+            .driver   = "qxl-vga",
+            .property = "revision",
+            .value    = stringify(2),
+        },
+        { /* end of list */ }
+    },
+    .hw_version = "0.14",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_0_13 \
+        PC_COMPAT_0_14,\
+        {\
+            .driver   = TYPE_PCI_DEVICE,\
+            .property = "command_serr_enable",\
+            .value    = "off",\
+        },{\
+            .driver   = "AC97",\
+            .property = "use_broken_id",\
+            .value    = stringify(1),\
+        }
+
+static QEMUMachine pc_machine_v0_13 = {
+    .name = "pc-0.13",
+    .desc = "Standard PC",
+    .init = pc_init_pci_no_kvmclock,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_13,
+        {
+            .driver   = "virtio-9p-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },{
+            .driver   = "VGA",
+            .property = "rombar",
+            .value    = stringify(0),
+        },{
+            .driver   = "vmware-svga",
+            .property = "rombar",
+            .value    = stringify(0),
+        },
+        { /* end of list */ }
+    },
+    .hw_version = "0.13",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_0_12 \
+        PC_COMPAT_0_13,\
+        {\
+            .driver   = "virtio-serial-pci",\
+            .property = "max_ports",\
+            .value    = stringify(1),\
+        },{\
+            .driver   = "virtio-serial-pci",\
+            .property = "vectors",\
+            .value    = stringify(0),\
+        }
+
+static QEMUMachine pc_machine_v0_12 = {
+    .name = "pc-0.12",
+    .desc = "Standard PC",
+    .init = pc_init_pci_no_kvmclock,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_12,
+        {
+            .driver   = "VGA",
+            .property = "rombar",
+            .value    = stringify(0),
+        },{
+            .driver   = "vmware-svga",
+            .property = "rombar",
+            .value    = stringify(0),
+        },
+        { /* end of list */ }
+    },
+    .hw_version = "0.12",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_0_11 \
+        PC_COMPAT_0_12,\
+        {\
+            .driver   = "virtio-blk-pci",\
+            .property = "vectors",\
+            .value    = stringify(0),\
+        },{\
+            .driver   = TYPE_PCI_DEVICE,\
+            .property = "rombar",\
+            .value    = stringify(0),\
+        }
+
+static QEMUMachine pc_machine_v0_11 = {
+    .name = "pc-0.11",
+    .desc = "Standard PC, qemu 0.11",
+    .init = pc_init_pci_no_kvmclock,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_11,
+        {
+            .driver   = "ide-drive",
+            .property = "ver",
+            .value    = "0.11",
+        },{
+            .driver   = "scsi-disk",
+            .property = "ver",
+            .value    = "0.11",
+        },
+        { /* end of list */ }
+    },
+    .hw_version = "0.11",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine pc_machine_v0_10 = {
+    .name = "pc-0.10",
+    .desc = "Standard PC, qemu 0.10",
+    .init = pc_init_pci_no_kvmclock,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_11,
+        {
+            .driver   = "virtio-blk-pci",
+            .property = "class",
+            .value    = stringify(PCI_CLASS_STORAGE_OTHER),
+        },{
+            .driver   = "virtio-serial-pci",
+            .property = "class",
+            .value    = stringify(PCI_CLASS_DISPLAY_OTHER),
+        },{
+            .driver   = "virtio-net-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },{
+            .driver   = "ide-drive",
+            .property = "ver",
+            .value    = "0.10",
+        },{
+            .driver   = "scsi-disk",
+            .property = "ver",
+            .value    = "0.10",
+        },
+        { /* end of list */ }
+    },
+    .hw_version = "0.10",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine isapc_machine = {
+    .name = "isapc",
+    .desc = "ISA-only PC",
+    .init = pc_init_isa,
+    .max_cpus = 1,
+    .compat_props = (GlobalProperty[]) {
+        {
+            .driver   = "pc-sysfw",
+            .property = "rom_only",
+            .value    = stringify(1),
+        },
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#ifdef CONFIG_XEN
+static QEMUMachine xenfv_machine = {
+    .name = "xenfv",
+    .desc = "Xen Fully-virtualized PC",
+    .init = pc_xen_hvm_init,
+    .max_cpus = HVM_MAX_VCPUS,
+    .default_machine_opts = "accel=xen",
+    DEFAULT_MACHINE_OPTIONS,
+};
+#endif
+
+static void pc_machine_init(void)
+{
+    qemu_register_machine(&pc_i440fx_machine_v1_5);
+    qemu_register_machine(&pc_i440fx_machine_v1_4);
+    qemu_register_machine(&pc_machine_v1_3);
+    qemu_register_machine(&pc_machine_v1_2);
+    qemu_register_machine(&pc_machine_v1_1);
+    qemu_register_machine(&pc_machine_v1_0);
+    qemu_register_machine(&pc_machine_v0_15);
+    qemu_register_machine(&pc_machine_v0_14);
+    qemu_register_machine(&pc_machine_v0_13);
+    qemu_register_machine(&pc_machine_v0_12);
+    qemu_register_machine(&pc_machine_v0_11);
+    qemu_register_machine(&pc_machine_v0_10);
+    qemu_register_machine(&isapc_machine);
+#ifdef CONFIG_XEN
+    qemu_register_machine(&xenfv_machine);
+#endif
+}
+
+machine_init(pc_machine_init);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
new file mode 100644 (file)
index 0000000..4f5f347
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Q35 chipset based pc system emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2009, 2010
+ *               Isaku Yamahata <yamahata at valinux co jp>
+ *               VA Linux Systems Japan K.K.
+ * Copyright (C) 2012 Jason Baron <jbaron@redhat.com>
+ *
+ * This is based on pc.c, but heavily modified.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "sysemu/arch_init.h"
+#include "hw/smbus.h"
+#include "hw/boards.h"
+#include "hw/mc146818rtc.h"
+#include "hw/xen.h"
+#include "sysemu/kvm.h"
+#include "hw/kvm/clock.h"
+#include "hw/q35.h"
+#include "exec/address-spaces.h"
+#include "hw/ich9.h"
+#include "hw/ide/pci.h"
+#include "hw/ide/ahci.h"
+#include "hw/usb.h"
+
+/* ICH9 AHCI has 6 ports */
+#define MAX_SATA_PORTS     6
+
+/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
+ *    BIOS will read it and start S3 resume at POST Entry */
+static void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
+{
+    ISADevice *s = opaque;
+
+    if (level) {
+        rtc_set_memory(s, 0xF, 0xFE);
+    }
+}
+
+/* PC hardware initialisation */
+static void pc_q35_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    ram_addr_t below_4g_mem_size, above_4g_mem_size;
+    Q35PCIHost *q35_host;
+    PCIBus *host_bus;
+    PCIDevice *lpc;
+    BusState *idebus[MAX_SATA_PORTS];
+    ISADevice *rtc_state;
+    ISADevice *floppy;
+    MemoryRegion *pci_memory;
+    MemoryRegion *rom_memory;
+    MemoryRegion *ram_memory;
+    GSIState *gsi_state;
+    ISABus *isa_bus;
+    int pci_enabled = 1;
+    qemu_irq *cpu_irq;
+    qemu_irq *gsi;
+    qemu_irq *i8259;
+    int i;
+    ICH9LPCState *ich9_lpc;
+    PCIDevice *ahci;
+    qemu_irq *cmos_s3;
+
+    pc_cpus_init(cpu_model);
+    pc_acpi_init("q35-acpi-dsdt.aml");
+
+    kvmclock_create();
+
+    if (ram_size >= 0xb0000000) {
+        above_4g_mem_size = ram_size - 0xb0000000;
+        below_4g_mem_size = 0xb0000000;
+    } else {
+        above_4g_mem_size = 0;
+        below_4g_mem_size = ram_size;
+    }
+
+    /* pci enabled */
+    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 = get_system_memory();
+    }
+
+    /* allocate ram and load rom/bios */
+    if (!xen_enabled()) {
+        pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline,
+                       initrd_filename, below_4g_mem_size, above_4g_mem_size,
+                       rom_memory, &ram_memory);
+    }
+
+    /* irq lines */
+    gsi_state = g_malloc0(sizeof(*gsi_state));
+    if (kvm_irqchip_in_kernel()) {
+        kvm_pc_setup_irq_routing(pci_enabled);
+        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
+                                 GSI_NUM_PINS);
+    } else {
+        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+    }
+
+    /* create pci host bus */
+    q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));
+
+    q35_host->mch.ram_memory = ram_memory;
+    q35_host->mch.pci_address_space = pci_memory;
+    q35_host->mch.system_memory = get_system_memory();
+    q35_host->mch.address_space_io = get_system_io();;
+    q35_host->mch.below_4g_mem_size = below_4g_mem_size;
+    q35_host->mch.above_4g_mem_size = above_4g_mem_size;
+    /* pci */
+    qdev_init_nofail(DEVICE(q35_host));
+    host_bus = q35_host->host.pci.bus;
+    /* create ISA bus */
+    lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
+                                          ICH9_LPC_FUNC), true,
+                                          TYPE_ICH9_LPC_DEVICE);
+    ich9_lpc = ICH9_LPC_DEVICE(lpc);
+    ich9_lpc->pic = gsi;
+    ich9_lpc->ioapic = gsi_state->ioapic_irq;
+    pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
+                 ICH9_LPC_NB_PIRQS);
+    pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
+    isa_bus = ich9_lpc->isa_bus;
+
+    /*end early*/
+    isa_bus_irqs(isa_bus, gsi);
+
+    if (kvm_irqchip_in_kernel()) {
+        i8259 = kvm_i8259_init(isa_bus);
+    } else if (xen_enabled()) {
+        i8259 = xen_interrupt_controller_init();
+    } else {
+        cpu_irq = pc_allocate_cpu_irq();
+        i8259 = i8259_init(isa_bus, cpu_irq[0]);
+    }
+
+    for (i = 0; i < ISA_NUM_IRQS; i++) {
+        gsi_state->i8259_irq[i] = i8259[i];
+    }
+    if (pci_enabled) {
+        ioapic_init_gsi(gsi_state, NULL);
+    }
+
+    pc_register_ferr_irq(gsi[13]);
+
+    /* init basic PC hardware */
+    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false);
+
+    /* connect pm stuff to lpc */
+    cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
+    ich9_lpc_pm_init(lpc, *cmos_s3);
+
+    /* ahci and SATA device, for q35 1 ahci controller is built-in */
+    ahci = pci_create_simple_multifunction(host_bus,
+                                           PCI_DEVFN(ICH9_SATA1_DEV,
+                                                     ICH9_SATA1_FUNC),
+                                           true, "ich9-ahci");
+    idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
+    idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");
+
+    if (usb_enabled(false)) {
+        /* Should we create 6 UHCI according to ich9 spec? */
+        ehci_create_ich9_with_companions(host_bus, 0x1d);
+    }
+
+    /* TODO: Populate SPD eeprom data.  */
+    smbus_eeprom_init(ich9_smb_init(host_bus,
+                                    PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
+                                    0xb100),
+                      8, NULL, 0);
+
+    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
+                 floppy, idebus[0], idebus[1], rtc_state);
+
+    /* the rest devices to which pci devfn is automatically assigned */
+    pc_vga_init(isa_bus, host_bus);
+    audio_init(isa_bus, host_bus);
+    pc_nic_init(isa_bus, host_bus);
+    if (pci_enabled) {
+        pc_pci_device_init(host_bus);
+    }
+}
+
+static QEMUMachine pc_q35_machine_v1_5 = {
+    .name = "pc-q35-1.5",
+    .alias = "q35",
+    .desc = "Standard PC (Q35 + ICH9, 2009)",
+    .init = pc_q35_init,
+    .max_cpus = 255,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine pc_q35_machine_v1_4 = {
+    .name = "pc-q35-1.4",
+    .desc = "Standard PC (Q35 + ICH9, 2009)",
+    .init = pc_q35_init,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_4,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void pc_q35_machine_init(void)
+{
+    qemu_register_machine(&pc_q35_machine_v1_5);
+    qemu_register_machine(&pc_q35_machine_v1_4);
+}
+
+machine_init(pc_q35_machine_init);
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
new file mode 100644 (file)
index 0000000..672ee9b
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * SMBIOS Support
+ *
+ * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * Authors:
+ *  Alex Williamson <alex.williamson@hp.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 "sysemu/sysemu.h"
+#include "hw/smbios.h"
+#include "hw/loader.h"
+
+/*
+ * Structures shared with the BIOS
+ */
+struct smbios_header {
+    uint16_t length;
+    uint8_t type;
+} QEMU_PACKED;
+
+struct smbios_field {
+    struct smbios_header header;
+    uint8_t type;
+    uint16_t offset;
+    uint8_t data[];
+} QEMU_PACKED;
+
+struct smbios_table {
+    struct smbios_header header;
+    uint8_t data[];
+} QEMU_PACKED;
+
+#define SMBIOS_FIELD_ENTRY 0
+#define SMBIOS_TABLE_ENTRY 1
+
+
+static uint8_t *smbios_entries;
+static size_t smbios_entries_len;
+static int smbios_type4_count = 0;
+
+static void smbios_validate_table(void)
+{
+    if (smbios_type4_count && smbios_type4_count != smp_cpus) {
+         fprintf(stderr,
+                 "Number of SMBIOS Type 4 tables must match cpu count.\n");
+        exit(1);
+    }
+}
+
+uint8_t *smbios_get_table(size_t *length)
+{
+    smbios_validate_table();
+    *length = smbios_entries_len;
+    return smbios_entries;
+}
+
+/*
+ * To avoid unresolvable overlaps in data, don't allow both
+ * tables and fields for the same smbios type.
+ */
+static void smbios_check_collision(int type, int entry)
+{
+    uint16_t *num_entries = (uint16_t *)smbios_entries;
+    struct smbios_header *header;
+    char *p;
+    int i;
+
+    if (!num_entries)
+        return;
+
+    p = (char *)(num_entries + 1);
+
+    for (i = 0; i < *num_entries; i++) {
+        header = (struct smbios_header *)p;
+        if (entry == SMBIOS_TABLE_ENTRY && header->type == SMBIOS_FIELD_ENTRY) {
+            struct smbios_field *field = (void *)header;
+            if (type == field->type) {
+                fprintf(stderr, "SMBIOS type %d field already defined, "
+                                "cannot add table\n", type);
+                exit(1);
+            }
+        } else if (entry == SMBIOS_FIELD_ENTRY &&
+                   header->type == SMBIOS_TABLE_ENTRY) {
+            struct smbios_structure_header *table = (void *)(header + 1);
+            if (type == table->type) {
+                fprintf(stderr, "SMBIOS type %d table already defined, "
+                                "cannot add field\n", type);
+                exit(1);
+            }
+        }
+        p += le16_to_cpu(header->length);
+    }
+}
+
+void smbios_add_field(int type, int offset, int len, void *data)
+{
+    struct smbios_field *field;
+
+    smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
+
+    if (!smbios_entries) {
+        smbios_entries_len = sizeof(uint16_t);
+        smbios_entries = g_malloc0(smbios_entries_len);
+    }
+    smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
+                                                  sizeof(*field) + len);
+    field = (struct smbios_field *)(smbios_entries + smbios_entries_len);
+    field->header.type = SMBIOS_FIELD_ENTRY;
+    field->header.length = cpu_to_le16(sizeof(*field) + len);
+
+    field->type = type;
+    field->offset = cpu_to_le16(offset);
+    memcpy(field->data, data, len);
+
+    smbios_entries_len += sizeof(*field) + len;
+    (*(uint16_t *)smbios_entries) =
+            cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
+}
+
+static void smbios_build_type_0_fields(const char *t)
+{
+    char buf[1024];
+
+    if (get_param_value(buf, sizeof(buf), "vendor", t))
+        smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "version", t))
+        smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "date", t))
+        smbios_add_field(0, offsetof(struct smbios_type_0,
+                                     bios_release_date_str),
+                                     strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "release", t)) {
+        int major, minor;
+        sscanf(buf, "%d.%d", &major, &minor);
+        smbios_add_field(0, offsetof(struct smbios_type_0,
+                                     system_bios_major_release), 1, &major);
+        smbios_add_field(0, offsetof(struct smbios_type_0,
+                                     system_bios_minor_release), 1, &minor);
+    }
+}
+
+static void smbios_build_type_1_fields(const char *t)
+{
+    char buf[1024];
+
+    if (get_param_value(buf, sizeof(buf), "manufacturer", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "product", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "version", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "serial", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "uuid", t)) {
+        if (qemu_uuid_parse(buf, qemu_uuid) != 0) {
+            fprintf(stderr, "Invalid SMBIOS UUID string\n");
+            exit(1);
+        }
+    }
+    if (get_param_value(buf, sizeof(buf), "sku", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "family", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
+                         strlen(buf) + 1, buf);
+}
+
+int smbios_entry_add(const char *t)
+{
+    char buf[1024];
+
+    if (get_param_value(buf, sizeof(buf), "file", t)) {
+        struct smbios_structure_header *header;
+        struct smbios_table *table;
+        int size = get_image_size(buf);
+
+        if (size == -1 || size < sizeof(struct smbios_structure_header)) {
+            fprintf(stderr, "Cannot read smbios file %s\n", buf);
+            exit(1);
+        }
+
+        if (!smbios_entries) {
+            smbios_entries_len = sizeof(uint16_t);
+            smbios_entries = g_malloc0(smbios_entries_len);
+        }
+
+        smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
+                                                      sizeof(*table) + size);
+        table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
+        table->header.type = SMBIOS_TABLE_ENTRY;
+        table->header.length = cpu_to_le16(sizeof(*table) + size);
+
+        if (load_image(buf, table->data) != size) {
+            fprintf(stderr, "Failed to load smbios file %s", buf);
+            exit(1);
+        }
+
+        header = (struct smbios_structure_header *)(table->data);
+        smbios_check_collision(header->type, SMBIOS_TABLE_ENTRY);
+        if (header->type == 4) {
+            smbios_type4_count++;
+        }
+
+        smbios_entries_len += sizeof(*table) + size;
+        (*(uint16_t *)smbios_entries) =
+                cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
+        return 0;
+    }
+
+    if (get_param_value(buf, sizeof(buf), "type", t)) {
+        unsigned long type = strtoul(buf, NULL, 0);
+        switch (type) {
+        case 0:
+            smbios_build_type_0_fields(t);
+            return 0;
+        case 1:
+            smbios_build_type_1_fields(t);
+            return 0;
+        default:
+            fprintf(stderr, "Don't know how to build fields for SMBIOS type "
+                    "%ld\n", type);
+            exit(1);
+        }
+    }
+
+    fprintf(stderr, "smbios: must specify type= or file=\n");
+    return -1;
+}
diff --git a/hw/i386/xen_domainbuild.c b/hw/i386/xen_domainbuild.c
new file mode 100644 (file)
index 0000000..d477061
--- /dev/null
@@ -0,0 +1,299 @@
+#include <signal.h>
+#include "hw/xen_backend.h"
+#include "hw/xen_domainbuild.h"
+#include "qemu/timer.h"
+#include "qemu/log.h"
+
+#include <xenguest.h>
+
+static int xenstore_domain_mkdir(char *path)
+{
+    struct xs_permissions perms_ro[] = {{
+            .id    = 0, /* set owner: dom0 */
+        },{
+            .id    = xen_domid,
+            .perms = XS_PERM_READ,
+        }};
+    struct xs_permissions perms_rw[] = {{
+            .id    = 0, /* set owner: dom0 */
+        },{
+            .id    = xen_domid,
+            .perms = XS_PERM_READ | XS_PERM_WRITE,
+        }};
+    const char *writable[] = { "device", "control", "error", NULL };
+    char subpath[256];
+    int i;
+
+    if (!xs_mkdir(xenstore, 0, path)) {
+        fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
+       return -1;
+    }
+    if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) {
+        fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
+       return -1;
+    }
+
+    for (i = 0; writable[i]; i++) {
+        snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]);
+        if (!xs_mkdir(xenstore, 0, subpath)) {
+            fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
+            return -1;
+        }
+        if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
+            fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int xenstore_domain_init1(const char *kernel, const char *ramdisk,
+                          const char *cmdline)
+{
+    char *dom, uuid_string[42], vm[256], path[256];
+    int i;
+
+    snprintf(uuid_string, sizeof(uuid_string), UUID_FMT,
+             qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3],
+             qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
+             qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
+             qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
+    dom = xs_get_domain_path(xenstore, xen_domid);
+    snprintf(vm,  sizeof(vm),  "/vm/%s", uuid_string);
+
+    xenstore_domain_mkdir(dom);
+
+    xenstore_write_str(vm, "image/ostype",  "linux");
+    if (kernel)
+        xenstore_write_str(vm, "image/kernel",  kernel);
+    if (ramdisk)
+        xenstore_write_str(vm, "image/ramdisk", ramdisk);
+    if (cmdline)
+        xenstore_write_str(vm, "image/cmdline", cmdline);
+
+    /* name + id */
+    xenstore_write_str(vm,  "name",   qemu_name ? qemu_name : "no-name");
+    xenstore_write_str(vm,  "uuid",   uuid_string);
+    xenstore_write_str(dom, "name",   qemu_name ? qemu_name : "no-name");
+    xenstore_write_int(dom, "domid",  xen_domid);
+    xenstore_write_str(dom, "vm",     vm);
+
+    /* memory */
+    xenstore_write_int(dom, "memory/target", ram_size >> 10);  // kB
+    xenstore_write_int(vm, "memory",         ram_size >> 20);  // MB
+    xenstore_write_int(vm, "maxmem",         ram_size >> 20);  // MB
+
+    /* cpus */
+    for (i = 0; i < smp_cpus; i++) {
+       snprintf(path, sizeof(path), "cpu/%d/availability",i);
+       xenstore_write_str(dom, path, "online");
+    }
+    xenstore_write_int(vm, "vcpu_avail",  smp_cpus);
+    xenstore_write_int(vm, "vcpus",       smp_cpus);
+
+    /* vnc password */
+    xenstore_write_str(vm, "vncpassword", "" /* FIXME */);
+
+    free(dom);
+    return 0;
+}
+
+int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
+                          int console_port, int console_mfn)
+{
+    char *dom;
+
+    dom = xs_get_domain_path(xenstore, xen_domid);
+
+    /* signal new domain */
+    xs_introduce_domain(xenstore,
+                        xen_domid,
+                        xenstore_mfn,
+                        xenstore_port);
+
+    /* xenstore */
+    xenstore_write_int(dom, "store/ring-ref",   xenstore_mfn);
+    xenstore_write_int(dom, "store/port",       xenstore_port);
+
+    /* console */
+    xenstore_write_str(dom, "console/type",     "ioemu");
+    xenstore_write_int(dom, "console/limit",    128 * 1024);
+    xenstore_write_int(dom, "console/ring-ref", console_mfn);
+    xenstore_write_int(dom, "console/port",     console_port);
+    xen_config_dev_console(0);
+
+    free(dom);
+    return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static QEMUTimer *xen_poll;
+
+/* check domain state once per second */
+static void xen_domain_poll(void *opaque)
+{
+    struct xc_dominfo info;
+    int rc;
+
+    rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info);
+    if ((rc != 1) || (info.domid != xen_domid)) {
+        qemu_log("xen: domain %d is gone\n", xen_domid);
+        goto quit;
+    }
+    if (info.dying) {
+        qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid,
+                 info.crashed  ? "crashed"  : "",
+                 info.shutdown ? "shutdown" : "");
+        goto quit;
+    }
+
+    qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
+    return;
+
+quit:
+    qemu_system_shutdown_request();
+}
+
+static int xen_domain_watcher(void)
+{
+    int qemu_running = 1;
+    int fd[2], i, n, rc;
+    char byte;
+
+    if (pipe(fd) != 0) {
+        qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno));
+        return -1;
+    }
+    if (fork() != 0)
+        return 0; /* not child */
+
+    /* close all file handles, except stdio/out/err,
+     * our watch pipe and the xen interface handle */
+    n = getdtablesize();
+    for (i = 3; i < n; i++) {
+        if (i == fd[0])
+            continue;
+        if (i == xc_fd(xen_xc)) {
+            continue;
+        }
+        close(i);
+    }
+
+    /* ignore term signals */
+    signal(SIGINT,  SIG_IGN);
+    signal(SIGTERM, SIG_IGN);
+
+    /* wait for qemu exiting */
+    while (qemu_running) {
+        rc = read(fd[0], &byte, 1);
+        switch (rc) {
+        case -1:
+            if (errno == EINTR)
+                continue;
+            qemu_log("%s: Huh? read error: %s\n", __FUNCTION__, strerror(errno));
+            qemu_running = 0;
+            break;
+        case 0:
+            /* EOF -> qemu exited */
+            qemu_running = 0;
+            break;
+        default:
+            qemu_log("%s: Huh? data on the watch pipe?\n", __FUNCTION__);
+            break;
+        }
+    }
+
+    /* cleanup */
+    qemu_log("%s: destroy domain %d\n", __FUNCTION__, xen_domid);
+    xc_domain_destroy(xen_xc, xen_domid);
+    _exit(0);
+}
+
+/* normal cleanup */
+static void xen_domain_cleanup(void)
+{
+    char *dom;
+
+    dom = xs_get_domain_path(xenstore, xen_domid);
+    if (dom) {
+        xs_rm(xenstore, 0, dom);
+        free(dom);
+    }
+    xs_release_domain(xenstore, xen_domid);
+}
+
+int xen_domain_build_pv(const char *kernel, const char *ramdisk,
+                        const char *cmdline)
+{
+    uint32_t ssidref = 0;
+    uint32_t flags = 0;
+    xen_domain_handle_t uuid;
+    unsigned int xenstore_port = 0, console_port = 0;
+    unsigned long xenstore_mfn = 0, console_mfn = 0;
+    int rc;
+
+    memcpy(uuid, qemu_uuid, sizeof(uuid));
+    rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_create() failed\n");
+        goto err;
+    }
+    qemu_log("xen: created domain %d\n", xen_domid);
+    atexit(xen_domain_cleanup);
+    if (xen_domain_watcher() == -1) {
+        goto err;
+    }
+
+    xenstore_domain_init1(kernel, ramdisk, cmdline);
+
+    rc = xc_domain_max_vcpus(xen_xc, xen_domid, smp_cpus);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_max_vcpus() failed\n");
+        goto err;
+    }
+
+#if 0
+    rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n");
+        goto err;
+    }
+#endif
+
+    rc = xc_domain_setmaxmem(xen_xc, xen_domid, ram_size >> 10);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_setmaxmem() failed\n");
+        goto err;
+    }
+
+    xenstore_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
+    console_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
+
+    rc = xc_linux_build(xen_xc, xen_domid, ram_size >> 20,
+                        kernel, ramdisk, cmdline,
+                        0, flags,
+                        xenstore_port, &xenstore_mfn,
+                        console_port, &console_mfn);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_linux_build() failed\n");
+        goto err;
+    }
+
+    xenstore_domain_init2(xenstore_port, xenstore_mfn,
+                          console_port, console_mfn);
+
+    qemu_log("xen: unpausing domain %d\n", xen_domid);
+    rc = xc_domain_unpause(xen_xc, xen_domid);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_unpause() failed\n");
+        goto err;
+    }
+
+    xen_poll = qemu_new_timer_ms(rt_clock, xen_domain_poll, NULL);
+    qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
+    return 0;
+
+err:
+    return -1;
+}
diff --git a/hw/i386/xen_machine_pv.c b/hw/i386/xen_machine_pv.c
new file mode 100644 (file)
index 0000000..a8177b6
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * QEMU Xen PV Machine
+ *
+ * Copyright (c) 2007 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/boards.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_domainbuild.h"
+#include "sysemu/blockdev.h"
+
+static void xen_init_pv(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    X86CPU *cpu;
+    CPUX86State *env;
+    DriveInfo *dinfo;
+    int i;
+
+    /* Initialize a dummy CPU */
+    if (cpu_model == NULL) {
+#ifdef TARGET_X86_64
+        cpu_model = "qemu64";
+#else
+        cpu_model = "qemu32";
+#endif
+    }
+    cpu = cpu_x86_init(cpu_model);
+    env = &cpu->env;
+    env->halted = 1;
+
+    /* Initialize backend core & drivers */
+    if (xen_be_init() != 0) {
+        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
+        exit(1);
+    }
+
+    switch (xen_mode) {
+    case XEN_ATTACH:
+        /* nothing to do, xend handles everything */
+        break;
+    case XEN_CREATE:
+        if (xen_domain_build_pv(kernel_filename, initrd_filename,
+                                kernel_cmdline) < 0) {
+            fprintf(stderr, "xen pv domain creation failed\n");
+            exit(1);
+        }
+        break;
+    case XEN_EMULATE:
+        fprintf(stderr, "xen emulation not implemented (yet)\n");
+        exit(1);
+        break;
+    }
+
+    xen_be_register("console", &xen_console_ops);
+    xen_be_register("vkbd", &xen_kbdmouse_ops);
+    xen_be_register("vfb", &xen_framebuffer_ops);
+    xen_be_register("qdisk", &xen_blkdev_ops);
+    xen_be_register("qnic", &xen_netdev_ops);
+
+    /* configure framebuffer */
+    if (xenfb_enabled) {
+        xen_config_dev_vfb(0, "vnc");
+        xen_config_dev_vkbd(0);
+    }
+
+    /* configure disks */
+    for (i = 0; i < 16; i++) {
+        dinfo = drive_get(IF_XEN, 0, i);
+        if (!dinfo)
+            continue;
+        xen_config_dev_blk(dinfo);
+    }
+
+    /* configure nics */
+    for (i = 0; i < nb_nics; i++) {
+        if (!nd_table[i].model || 0 != strcmp(nd_table[i].model, "xen"))
+            continue;
+        xen_config_dev_nic(nd_table + i);
+    }
+
+    /* config cleanup hook */
+    atexit(xen_config_cleanup);
+
+    /* setup framebuffer */
+    xen_init_display(xen_domid);
+}
+
+static QEMUMachine xenpv_machine = {
+    .name = "xenpv",
+    .desc = "Xen Para-virtualized PC",
+    .init = xen_init_pv,
+    .max_cpus = 1,
+    .default_machine_opts = "accel=xen",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void xenpv_machine_init(void)
+{
+    qemu_register_machine(&xenpv_machine);
+}
+
+machine_init(xenpv_machine_init);
index 6a62ba2ab8856be438e5086ace78c3e1ed931d7b..22115e4fcf4a6d2efef4385e755ee892660830ff 100644 (file)
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "isa.h"
+#include "hw/isa.h"
 
 //#define DEBUG_I82374
 
index 0914d7bbfb6c87cce58efcedaaee57e92557074f..6f8c48b9aedfc7c0243b8cd7c85118a01ba96cd5 100644 (file)
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci/pci.h"
-#include "pc.h"
-#include "i8254.h"
-#include "pcspk.h"
+#include "hw/pci/pci.h"
+#include "hw/pc.h"
+#include "hw/i8254.h"
+#include "hw/pcspk.h"
 
 //#define DEBUG_I82378
 
index 394b2e81d760695a91b4e27d3308ae1ac99cb397..67bfc6a80668f406c2c7d38f77a8623b8ce7695f 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 #include "qemu/timer.h"
-#include "i8254.h"
-#include "i8254_internal.h"
+#include "hw/i8254.h"
+#include "hw/i8254_internal.h"
 
 //#define DEBUG_PIT
 
index ba6b598a9988a3c31b21984fc3240595725d9e1d..7d4432e72270a0c14dca41162152272a1676ce7f 100644 (file)
@@ -25,8 +25,8 @@
 #ifndef HW_I8254_H
 #define HW_I8254_H
 
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 
 #define PIT_FREQ 1193182
 
index 8c2e45a92e788ad1173524d451040a6aa12640e8..c6c0c80c248e87ecb547709337d9a52e246d1713 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 #include "qemu/timer.h"
-#include "i8254.h"
-#include "i8254_internal.h"
+#include "hw/i8254.h"
+#include "hw/i8254_internal.h"
 
 /* val must be 0 or 1 */
 void pit_set_gate(ISADevice *dev, int channel, int val)
index 686f0c2ba9db225665a97695415d8b1bca345a29..30d5b1b95018714c1f539e2667e58a64e45db6bc 100644 (file)
@@ -25,9 +25,9 @@
 #ifndef QEMU_I8254_INTERNAL_H
 #define QEMU_I8254_INTERNAL_H
 
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 
 typedef struct PITChannelState {
     int count; /* can be 65536 */
index 54fe14447b767d9a0a0795021dc2aaa12ecebe16..1d8275232abc778147f741ff5116d964d1ef8a17 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 #include "monitor/monitor.h"
 #include "qemu/timer.h"
-#include "i8259_internal.h"
+#include "hw/i8259_internal.h"
 
 /* debug PIC */
 //#define DEBUG_PIC
index fc91056afbf8e01cda6e3dde468ec832a7591233..98052db1fa261d201ac3f40d2cbae25f77d4aecf 100644 (file)
@@ -22,8 +22,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "pc.h"
-#include "i8259_internal.h"
+#include "hw/pc.h"
+#include "hw/i8259_internal.h"
 
 void pic_reset_common(PICCommonState *s)
 {
index 8785b1da3fd391d849fbd3cf1308d5ee25d8fe2f..2813ec1baa00f5691b5e72b36f9bb5d78a031199 100644 (file)
@@ -25,9 +25,9 @@
 #ifndef QEMU_I8259_INTERNAL_H
 #define QEMU_I8259_INTERNAL_H
 
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 
 typedef struct PICCommonState PICCommonState;
 
index 3dc10000a447966bc068bd1cda8335b188022d32..992095c80fcd24749258271eb9e7d344511bd1e5 100644 (file)
@@ -41,8 +41,8 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>
  */
 
-#include "pci/pci.h"
-#include "ich9.h"
+#include "hw/pci/pci.h"
+#include "hw/ich9.h"
 
 
 /*****************************************************************************/
index dbc44957b4b34ce580322251802ed02bf19bf629..e7d2df72802662331791a07cfa8a347aa2794f20 100644 (file)
--- a/hw/ich9.h
+++ b/hw/ich9.h
@@ -1,20 +1,20 @@
 #ifndef HW_ICH9_H
 #define HW_ICH9_H
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/range.h"
-#include "isa.h"
-#include "sysbus.h"
-#include "pc.h"
-#include "apm.h"
-#include "ioapic.h"
-#include "pci/pci.h"
-#include "pci/pcie_host.h"
-#include "pci/pci_bridge.h"
-#include "acpi.h"
-#include "acpi_ich9.h"
-#include "pam.h"
-#include "pci/pci_bus.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
+#include "hw/pc.h"
+#include "hw/apm.h"
+#include "hw/ioapic.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/acpi.h"
+#include "hw/acpi_ich9.h"
+#include "hw/pam.h"
+#include "hw/pci/pci_bus.h"
 
 void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
 int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
index 0eb3a744676bd71c2cfddacd25885f60026301b5..35444a39f94c21e4ab93760d3d2a3ad2750ad774 100644 (file)
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -1,8 +1,8 @@
 #ifndef HW_IDE_H
 #define HW_IDE_H
 
-#include "isa.h"
-#include "pci/pci.h"
+#include "hw/isa.h"
+#include "hw/pci/pci.h"
 #include "exec/memory.h"
 
 #define MAX_IDE_DEVS   2
index f1f066cf9c7667d44010c869404bce6438f3aa86..4e280b6ab98886edcfaa4e21c5703cc6ba055c24 100644 (file)
@@ -14,8 +14,8 @@
  * TODO: implement vectors.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "qemu/host-utils.h"
 
 #define DEBUG_INT 1
index 477903a5467fd81e0f4311e7d49085026bd0b769..ad7aad339747356c01a067009099555f63acaedf 100644 (file)
  * the CCM.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
-#include "imx.h"
+#include "hw/imx.h"
 
 #define CKIH_FREQ 26000000 /* 26MHz crystal input */
 #define CKIL_FREQ    32768 /* nominal 32khz clock */
index 2d8253e0ee0f6b8e788eba693aa9b6027571aa5c..746723cd6e7cbd38dbeba0d96183f4eb4c7bd54e 100644 (file)
  *     is a real serial device.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "char/char.h"
-#include "imx.h"
+#include "hw/imx.h"
 
 //#define DEBUG_SERIAL 1
 #ifdef DEBUG_SERIAL
index e924c747c542b4cc8cef0b82175b155b3ed5e003..a8c311141e9caa1459786ab4a654aeaa32766672 100644 (file)
  *
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
-#include "sysbus.h"
-#include "imx.h"
+#include "hw/ptimer.h"
+#include "hw/sysbus.h"
+#include "hw/imx.h"
 
 //#define DEBUG_TIMER 1
 #ifdef DEBUG_TIMER
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
deleted file mode 100644 (file)
index 9e3630a..0000000
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * ARM Integrator CP System emulation.
- *
- * Copyright (c) 2005-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL
- */
-
-#include "sysbus.h"
-#include "devices.h"
-#include "boards.h"
-#include "arm-misc.h"
-#include "net/net.h"
-#include "exec/address-spaces.h"
-#include "sysemu/sysemu.h"
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t memsz;
-    MemoryRegion flash;
-    uint32_t cm_osc;
-    uint32_t cm_ctrl;
-    uint32_t cm_lock;
-    uint32_t cm_auxosc;
-    uint32_t cm_sdram;
-    uint32_t cm_init;
-    uint32_t cm_flags;
-    uint32_t cm_nvflags;
-    uint32_t int_level;
-    uint32_t irq_enabled;
-    uint32_t fiq_enabled;
-} integratorcm_state;
-
-static uint8_t integrator_spd[128] = {
-   128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
-   0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
-};
-
-static uint64_t integratorcm_read(void *opaque, hwaddr offset,
-                                  unsigned size)
-{
-    integratorcm_state *s = (integratorcm_state *)opaque;
-    if (offset >= 0x100 && offset < 0x200) {
-        /* CM_SPD */
-        if (offset >= 0x180)
-            return 0;
-        return integrator_spd[offset >> 2];
-    }
-    switch (offset >> 2) {
-    case 0: /* CM_ID */
-        return 0x411a3001;
-    case 1: /* CM_PROC */
-        return 0;
-    case 2: /* CM_OSC */
-        return s->cm_osc;
-    case 3: /* CM_CTRL */
-        return s->cm_ctrl;
-    case 4: /* CM_STAT */
-        return 0x00100000;
-    case 5: /* CM_LOCK */
-        if (s->cm_lock == 0xa05f) {
-            return 0x1a05f;
-        } else {
-            return s->cm_lock;
-        }
-    case 6: /* CM_LMBUSCNT */
-        /* ??? High frequency timer.  */
-        hw_error("integratorcm_read: CM_LMBUSCNT");
-    case 7: /* CM_AUXOSC */
-        return s->cm_auxosc;
-    case 8: /* CM_SDRAM */
-        return s->cm_sdram;
-    case 9: /* CM_INIT */
-        return s->cm_init;
-    case 10: /* CM_REFCT */
-        /* ??? High frequency timer.  */
-        hw_error("integratorcm_read: CM_REFCT");
-    case 12: /* CM_FLAGS */
-        return s->cm_flags;
-    case 14: /* CM_NVFLAGS */
-        return s->cm_nvflags;
-    case 16: /* CM_IRQ_STAT */
-        return s->int_level & s->irq_enabled;
-    case 17: /* CM_IRQ_RSTAT */
-        return s->int_level;
-    case 18: /* CM_IRQ_ENSET */
-        return s->irq_enabled;
-    case 20: /* CM_SOFT_INTSET */
-        return s->int_level & 1;
-    case 24: /* CM_FIQ_STAT */
-        return s->int_level & s->fiq_enabled;
-    case 25: /* CM_FIQ_RSTAT */
-        return s->int_level;
-    case 26: /* CM_FIQ_ENSET */
-        return s->fiq_enabled;
-    case 32: /* CM_VOLTAGE_CTL0 */
-    case 33: /* CM_VOLTAGE_CTL1 */
-    case 34: /* CM_VOLTAGE_CTL2 */
-    case 35: /* CM_VOLTAGE_CTL3 */
-        /* ??? Voltage control unimplemented.  */
-        return 0;
-    default:
-        hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
-                 (int)offset);
-        return 0;
-    }
-}
-
-static void integratorcm_do_remap(integratorcm_state *s)
-{
-    /* Sync memory region state with CM_CTRL REMAP bit:
-     * bit 0 => flash at address 0; bit 1 => RAM
-     */
-    memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
-}
-
-static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
-{
-    if (value & 8) {
-        qemu_system_reset_request();
-    }
-    if ((s->cm_ctrl ^ value) & 1) {
-        /* (value & 1) != 0 means the green "MISC LED" is lit.
-         * We don't have any nice place to display LEDs. printf is a bad
-         * idea because Linux uses the LED as a heartbeat and the output
-         * will swamp anything else on the terminal.
-         */
-    }
-    /* Note that the RESET bit [3] always reads as zero */
-    s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
-    integratorcm_do_remap(s);
-}
-
-static void integratorcm_update(integratorcm_state *s)
-{
-    /* ??? The CPU irq/fiq is raised when either the core module or base PIC
-       are active.  */
-    if (s->int_level & (s->irq_enabled | s->fiq_enabled))
-        hw_error("Core module interrupt\n");
-}
-
-static void integratorcm_write(void *opaque, hwaddr offset,
-                               uint64_t value, unsigned size)
-{
-    integratorcm_state *s = (integratorcm_state *)opaque;
-    switch (offset >> 2) {
-    case 2: /* CM_OSC */
-        if (s->cm_lock == 0xa05f)
-            s->cm_osc = value;
-        break;
-    case 3: /* CM_CTRL */
-        integratorcm_set_ctrl(s, value);
-        break;
-    case 5: /* CM_LOCK */
-        s->cm_lock = value & 0xffff;
-        break;
-    case 7: /* CM_AUXOSC */
-        if (s->cm_lock == 0xa05f)
-            s->cm_auxosc = value;
-        break;
-    case 8: /* CM_SDRAM */
-        s->cm_sdram = value;
-        break;
-    case 9: /* CM_INIT */
-        /* ??? This can change the memory bus frequency.  */
-        s->cm_init = value;
-        break;
-    case 12: /* CM_FLAGSS */
-        s->cm_flags |= value;
-        break;
-    case 13: /* CM_FLAGSC */
-        s->cm_flags &= ~value;
-        break;
-    case 14: /* CM_NVFLAGSS */
-        s->cm_nvflags |= value;
-        break;
-    case 15: /* CM_NVFLAGSS */
-        s->cm_nvflags &= ~value;
-        break;
-    case 18: /* CM_IRQ_ENSET */
-        s->irq_enabled |= value;
-        integratorcm_update(s);
-        break;
-    case 19: /* CM_IRQ_ENCLR */
-        s->irq_enabled &= ~value;
-        integratorcm_update(s);
-        break;
-    case 20: /* CM_SOFT_INTSET */
-        s->int_level |= (value & 1);
-        integratorcm_update(s);
-        break;
-    case 21: /* CM_SOFT_INTCLR */
-        s->int_level &= ~(value & 1);
-        integratorcm_update(s);
-        break;
-    case 26: /* CM_FIQ_ENSET */
-        s->fiq_enabled |= value;
-        integratorcm_update(s);
-        break;
-    case 27: /* CM_FIQ_ENCLR */
-        s->fiq_enabled &= ~value;
-        integratorcm_update(s);
-        break;
-    case 32: /* CM_VOLTAGE_CTL0 */
-    case 33: /* CM_VOLTAGE_CTL1 */
-    case 34: /* CM_VOLTAGE_CTL2 */
-    case 35: /* CM_VOLTAGE_CTL3 */
-        /* ??? Voltage control unimplemented.  */
-        break;
-    default:
-        hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
-                 (int)offset);
-        break;
-    }
-}
-
-/* Integrator/CM control registers.  */
-
-static const MemoryRegionOps integratorcm_ops = {
-    .read = integratorcm_read,
-    .write = integratorcm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int integratorcm_init(SysBusDevice *dev)
-{
-    integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
-
-    s->cm_osc = 0x01000048;
-    /* ??? What should the high bits of this value be?  */
-    s->cm_auxosc = 0x0007feff;
-    s->cm_sdram = 0x00011122;
-    if (s->memsz >= 256) {
-        integrator_spd[31] = 64;
-        s->cm_sdram |= 0x10;
-    } else if (s->memsz >= 128) {
-        integrator_spd[31] = 32;
-        s->cm_sdram |= 0x0c;
-    } else if (s->memsz >= 64) {
-        integrator_spd[31] = 16;
-        s->cm_sdram |= 0x08;
-    } else if (s->memsz >= 32) {
-        integrator_spd[31] = 4;
-        s->cm_sdram |= 0x04;
-    } else {
-        integrator_spd[31] = 2;
-    }
-    memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
-    s->cm_init = 0x00000112;
-    memory_region_init_ram(&s->flash, "integrator.flash", 0x100000);
-    vmstate_register_ram_global(&s->flash);
-
-    memory_region_init_io(&s->iomem, &integratorcm_ops, s,
-                          "integratorcm", 0x00800000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    integratorcm_do_remap(s);
-    /* ??? Save/restore.  */
-    return 0;
-}
-
-/* Integrator/CP hardware emulation.  */
-/* Primary interrupt controller.  */
-
-typedef struct icp_pic_state
-{
-  SysBusDevice busdev;
-  MemoryRegion iomem;
-  uint32_t level;
-  uint32_t irq_enabled;
-  uint32_t fiq_enabled;
-  qemu_irq parent_irq;
-  qemu_irq parent_fiq;
-} icp_pic_state;
-
-static void icp_pic_update(icp_pic_state *s)
-{
-    uint32_t flags;
-
-    flags = (s->level & s->irq_enabled);
-    qemu_set_irq(s->parent_irq, flags != 0);
-    flags = (s->level & s->fiq_enabled);
-    qemu_set_irq(s->parent_fiq, flags != 0);
-}
-
-static void icp_pic_set_irq(void *opaque, int irq, int level)
-{
-    icp_pic_state *s = (icp_pic_state *)opaque;
-    if (level)
-        s->level |= 1 << irq;
-    else
-        s->level &= ~(1 << irq);
-    icp_pic_update(s);
-}
-
-static uint64_t icp_pic_read(void *opaque, hwaddr offset,
-                             unsigned size)
-{
-    icp_pic_state *s = (icp_pic_state *)opaque;
-
-    switch (offset >> 2) {
-    case 0: /* IRQ_STATUS */
-        return s->level & s->irq_enabled;
-    case 1: /* IRQ_RAWSTAT */
-        return s->level;
-    case 2: /* IRQ_ENABLESET */
-        return s->irq_enabled;
-    case 4: /* INT_SOFTSET */
-        return s->level & 1;
-    case 8: /* FRQ_STATUS */
-        return s->level & s->fiq_enabled;
-    case 9: /* FRQ_RAWSTAT */
-        return s->level;
-    case 10: /* FRQ_ENABLESET */
-        return s->fiq_enabled;
-    case 3: /* IRQ_ENABLECLR */
-    case 5: /* INT_SOFTCLR */
-    case 11: /* FRQ_ENABLECLR */
-    default:
-        printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
-        return 0;
-    }
-}
-
-static void icp_pic_write(void *opaque, hwaddr offset,
-                          uint64_t value, unsigned size)
-{
-    icp_pic_state *s = (icp_pic_state *)opaque;
-
-    switch (offset >> 2) {
-    case 2: /* IRQ_ENABLESET */
-        s->irq_enabled |= value;
-        break;
-    case 3: /* IRQ_ENABLECLR */
-        s->irq_enabled &= ~value;
-        break;
-    case 4: /* INT_SOFTSET */
-        if (value & 1)
-            icp_pic_set_irq(s, 0, 1);
-        break;
-    case 5: /* INT_SOFTCLR */
-        if (value & 1)
-            icp_pic_set_irq(s, 0, 0);
-        break;
-    case 10: /* FRQ_ENABLESET */
-        s->fiq_enabled |= value;
-        break;
-    case 11: /* FRQ_ENABLECLR */
-        s->fiq_enabled &= ~value;
-        break;
-    case 0: /* IRQ_STATUS */
-    case 1: /* IRQ_RAWSTAT */
-    case 8: /* FRQ_STATUS */
-    case 9: /* FRQ_RAWSTAT */
-    default:
-        printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
-        return;
-    }
-    icp_pic_update(s);
-}
-
-static const MemoryRegionOps icp_pic_ops = {
-    .read = icp_pic_read,
-    .write = icp_pic_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int icp_pic_init(SysBusDevice *dev)
-{
-    icp_pic_state *s = FROM_SYSBUS(icp_pic_state, dev);
-
-    qdev_init_gpio_in(&dev->qdev, icp_pic_set_irq, 32);
-    sysbus_init_irq(dev, &s->parent_irq);
-    sysbus_init_irq(dev, &s->parent_fiq);
-    memory_region_init_io(&s->iomem, &icp_pic_ops, s, "icp-pic", 0x00800000);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-/* CP control registers.  */
-
-static uint64_t icp_control_read(void *opaque, hwaddr offset,
-                                 unsigned size)
-{
-    switch (offset >> 2) {
-    case 0: /* CP_IDFIELD */
-        return 0x41034003;
-    case 1: /* CP_FLASHPROG */
-        return 0;
-    case 2: /* CP_INTREG */
-        return 0;
-    case 3: /* CP_DECODE */
-        return 0x11;
-    default:
-        hw_error("icp_control_read: Bad offset %x\n", (int)offset);
-        return 0;
-    }
-}
-
-static void icp_control_write(void *opaque, hwaddr offset,
-                          uint64_t value, unsigned size)
-{
-    switch (offset >> 2) {
-    case 1: /* CP_FLASHPROG */
-    case 2: /* CP_INTREG */
-    case 3: /* CP_DECODE */
-        /* Nothing interesting implemented yet.  */
-        break;
-    default:
-        hw_error("icp_control_write: Bad offset %x\n", (int)offset);
-    }
-}
-
-static const MemoryRegionOps icp_control_ops = {
-    .read = icp_control_read,
-    .write = icp_control_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void icp_control_init(hwaddr base)
-{
-    MemoryRegion *io;
-
-    io = (MemoryRegion *)g_malloc0(sizeof(MemoryRegion));
-    memory_region_init_io(io, &icp_control_ops, NULL,
-                          "control", 0x00800000);
-    memory_region_add_subregion(get_system_memory(), base, io);
-    /* ??? Save/restore.  */
-}
-
-
-/* Board init.  */
-
-static struct arm_boot_info integrator_binfo = {
-    .loader_start = 0x0,
-    .board_id = 0x113,
-};
-
-static void integratorcp_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    ARMCPU *cpu;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
-    qemu_irq pic[32];
-    qemu_irq *cpu_pic;
-    DeviceState *dev;
-    int i;
-
-    if (!cpu_model) {
-        cpu_model = "arm926";
-    }
-    cpu = cpu_arm_init(cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-
-    memory_region_init_ram(ram, "integrator.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
-    /* ??? RAM should repeat to fill physical memory space.  */
-    /* SDRAM at address zero*/
-    memory_region_add_subregion(address_space_mem, 0, ram);
-    /* And again at address 0x80000000 */
-    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
-    memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
-
-    dev = qdev_create(NULL, "integrator_core");
-    qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
-
-    cpu_pic = arm_pic_init_cpu(cpu);
-    dev = sysbus_create_varargs("integrator_pic", 0x14000000,
-                                cpu_pic[ARM_PIC_CPU_IRQ],
-                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
-    for (i = 0; i < 32; i++) {
-        pic[i] = qdev_get_gpio_in(dev, i);
-    }
-    sysbus_create_simple("integrator_pic", 0xca000000, pic[26]);
-    sysbus_create_varargs("integrator_pit", 0x13000000,
-                          pic[5], pic[6], pic[7], NULL);
-    sysbus_create_simple("pl031", 0x15000000, pic[8]);
-    sysbus_create_simple("pl011", 0x16000000, pic[1]);
-    sysbus_create_simple("pl011", 0x17000000, pic[2]);
-    icp_control_init(0xcb000000);
-    sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
-    sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
-    sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
-    if (nd_table[0].used)
-        smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
-
-    sysbus_create_simple("pl110", 0xc0000000, pic[22]);
-
-    integrator_binfo.ram_size = ram_size;
-    integrator_binfo.kernel_filename = kernel_filename;
-    integrator_binfo.kernel_cmdline = kernel_cmdline;
-    integrator_binfo.initrd_filename = initrd_filename;
-    arm_load_kernel(cpu, &integrator_binfo);
-}
-
-static QEMUMachine integratorcp_machine = {
-    .name = "integratorcp",
-    .desc = "ARM Integrator/CP (ARM926EJ-S)",
-    .init = integratorcp_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void integratorcp_machine_init(void)
-{
-    qemu_register_machine(&integratorcp_machine);
-}
-
-machine_init(integratorcp_machine_init);
-
-static Property core_properties[] = {
-    DEFINE_PROP_UINT32("memsz", integratorcm_state, memsz, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void core_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = integratorcm_init;
-    dc->props = core_properties;
-}
-
-static const TypeInfo core_info = {
-    .name          = "integrator_core",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(integratorcm_state),
-    .class_init    = core_class_init,
-};
-
-static void icp_pic_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = icp_pic_init;
-}
-
-static const TypeInfo icp_pic_info = {
-    .name          = "integrator_pic",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(icp_pic_state),
-    .class_init    = icp_pic_class_init,
-};
-
-static void integratorcp_register_types(void)
-{
-    type_register_static(&icp_pic_info);
-    type_register_static(&core_info);
-}
-
-type_init(integratorcp_register_types)
index 784c229d8f68fd4d3631ac58f63ea7d50358ad2e..728b60fb9a7468ea80dfa6e57d70a6c69b12d48f 100644 (file)
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "pci/pci.h"
-#include "pci/msi.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msi.h"
 #include "qemu/timer.h"
-#include "audiodev.h"
-#include "intel-hda.h"
-#include "intel-hda-defs.h"
+#include "hw/audiodev.h"
+#include "hw/intel-hda.h"
+#include "hw/intel-hda-defs.h"
 #include "sysemu/dma.h"
 
 /* --------------------------------------------------------------------- */
index 22e0968d50a762ea123192eb7ca446443082e047..2544f0a34484427148db9c1502178cb761de61d3 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef HW_INTEL_HDA_H
 #define HW_INTEL_HDA_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 /* --------------------------------------------------------------------- */
 /* hda bus                                                               */
index f06c2dcf2e8a2592e90f6fb8cb4b2db80145d230..78629fac6cc054bb855623feee0efbad6504914e 100644 (file)
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "apic.h"
-#include "ioapic.h"
-#include "ioapic_internal.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/apic.h"
+#include "hw/ioapic.h"
+#include "hw/ioapic_internal.h"
 
 //#define DEBUG_IOAPIC
 
index 7dc552f033c976e28af86299eb1c47c618be5bde..d4aff2954468e4dba475d55cf3c31b77e7ce9b26 100644 (file)
@@ -19,9 +19,9 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ioapic.h"
-#include "ioapic_internal.h"
-#include "sysbus.h"
+#include "hw/ioapic.h"
+#include "hw/ioapic_internal.h"
+#include "hw/sysbus.h"
 
 void ioapic_reset_common(DeviceState *dev)
 {
index c8447d7f3ba8d15bcae38c9d1fbc2bd71100276a..25576c819e5bb7b63f6f17c2f91954fc05000760 100644 (file)
@@ -22,9 +22,9 @@
 #ifndef QEMU_IOAPIC_INTERNAL_H
 #define QEMU_IOAPIC_INTERNAL_H
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "exec/memory.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #define MAX_IOAPICS                     1
 
index 95bceb5347a8a517cb70e7c287d15e3a0611ff9e..43f855427b7b5a35732ad7862e9c5e747c7b2ee9 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci/pci_ids.h"
-#include "pci/msi.h"
-#include "pci/pcie.h"
-#include "ioh3420.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/pcie.h"
+#include "hw/ioh3420.h"
 
 #define PCI_DEVICE_ID_IOH_EPORT         0x3420  /* D0:F0 express mode */
 #define PCI_DEVICE_ID_IOH_REV           0x2
index 046cf2c281d360867795da492a15b48aa90ed4d4..7776e5b02d99815b1d2164b3ba4d2dd71c44ef3e 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef QEMU_IOH3420_H
 #define QEMU_IOH3420_H
 
-#include "pci/pcie_port.h"
+#include "hw/pci/pcie_port.h"
 
 PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
                        const char *bus_name, pci_map_irq_fn map_irq,
index e15540d5cdbf1f52e3706c0b008e582764894230..b1f46c10a42b7bddf12b4ea3e8e2802923d3b296 100644 (file)
@@ -8,7 +8,7 @@
  * later version.
  */
 
-#include "ipack.h"
+#include "hw/ipack.h"
 
 IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot)
 {
index 69e26282d3e932ad1b9d4735fa70c22e7fc4f0bf..f2b7a12e05c02fd20159e7828e26fc55434eaa3f 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef QEMU_IPACK_H
 #define QEMU_IPACK_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 typedef struct IPackBus IPackBus;
 
index c1e3b197b5763c624f440893eed355ac3c2f42b6..1da6a9917505275d65058b9faef1da44e3985de3 100644 (file)
@@ -8,7 +8,7 @@
  * later version.
  */
 
-#include "ipack.h"
+#include "hw/ipack.h"
 #include "qemu/bitops.h"
 #include "char/char.h"
 
index f4e2a7804a3a24528417abbae22334ffadab753f..20785428ef00eff815b67a98a90a8816ccab9987 100644 (file)
--- a/hw/irq.c
+++ b/hw/irq.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 #include "qemu-common.h"
-#include "irq.h"
+#include "hw/irq.h"
 
 struct IRQState {
     qemu_irq_handler handler;
index 6dc34f09f3b3e72984794011a531a7ef1644c2cc..67ff8fd314c62c5143590e3333b82ad25e4bbfbf 100644 (file)
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "monitor/monitor.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
-#include "isa.h"
+#include "hw/isa.h"
 #include "exec/address-spaces.h"
 
 static ISABus *isabus;
index 7a8874abfd3ff2f2716e02c1eac320bc713d3415..82da37c11d288834b037c731164f700f32fd6b9a 100644 (file)
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -5,7 +5,7 @@
 
 #include "exec/ioport.h"
 #include "exec/memory.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 
 #define ISA_NUM_IRQS 16
 
index 487cf6a8fb70675bffe49be27c83771252966c4e..a7860e7459b6613b09b24ef87f8f04d441f7da34 100644 (file)
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 #include "exec/address-spaces.h"
 
 static void isa_mmio_writeb (void *opaque, hwaddr addr,
index afaf9b3bbfcb258d9e861253b37596c611d7f457..68a2cf2e69c943312963d153eaaf1389fdb44314 100644 (file)
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "pc.h"
-#include "pci/pci.h"
-#include "pci/msix.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msix.h"
 #include "sysemu/kvm.h"
 #include "migration/migration.h"
 #include "qapi/qmp/qerror.h"
index 4822c485f208768289a88d7234428d7a94858ce6..a418a7d1b6f13626bb16d30ca366ac9836025b2c 100644 (file)
@@ -26,7 +26,7 @@
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
 #include "trace.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 typedef enum {
     REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c
deleted file mode 100644 (file)
index 9265baf..0000000
+++ /dev/null
@@ -1,822 +0,0 @@
-/*
- * TPR optimization for 32-bit Windows guests (XP and Server 2003)
- *
- * Copyright (C) 2007-2008 Qumranet Technologies
- * Copyright (C) 2012      Jan Kiszka, Siemens AG
- *
- * This work is licensed under the terms of the GNU GPL version 2, or
- * (at your option) any later version. See the COPYING file in the
- * top-level directory.
- */
-#include "sysemu/sysemu.h"
-#include "sysemu/cpus.h"
-#include "sysemu/kvm.h"
-#include "apic_internal.h"
-
-#define APIC_DEFAULT_ADDRESS    0xfee00000
-
-#define VAPIC_IO_PORT           0x7e
-
-#define VAPIC_CPU_SHIFT         7
-
-#define ROM_BLOCK_SIZE          512
-#define ROM_BLOCK_MASK          (~(ROM_BLOCK_SIZE - 1))
-
-typedef enum VAPICMode {
-    VAPIC_INACTIVE = 0,
-    VAPIC_ACTIVE   = 1,
-    VAPIC_STANDBY  = 2,
-} VAPICMode;
-
-typedef struct VAPICHandlers {
-    uint32_t set_tpr;
-    uint32_t set_tpr_eax;
-    uint32_t get_tpr[8];
-    uint32_t get_tpr_stack;
-} QEMU_PACKED VAPICHandlers;
-
-typedef struct GuestROMState {
-    char signature[8];
-    uint32_t vaddr;
-    uint32_t fixup_start;
-    uint32_t fixup_end;
-    uint32_t vapic_vaddr;
-    uint32_t vapic_size;
-    uint32_t vcpu_shift;
-    uint32_t real_tpr_addr;
-    VAPICHandlers up;
-    VAPICHandlers mp;
-} QEMU_PACKED GuestROMState;
-
-typedef struct VAPICROMState {
-    SysBusDevice busdev;
-    MemoryRegion io;
-    MemoryRegion rom;
-    uint32_t state;
-    uint32_t rom_state_paddr;
-    uint32_t rom_state_vaddr;
-    uint32_t vapic_paddr;
-    uint32_t real_tpr_addr;
-    GuestROMState rom_state;
-    size_t rom_size;
-    bool rom_mapped_writable;
-} VAPICROMState;
-
-#define TPR_INSTR_ABS_MODRM             0x1
-#define TPR_INSTR_MATCH_MODRM_REG       0x2
-
-typedef struct TPRInstruction {
-    uint8_t opcode;
-    uint8_t modrm_reg;
-    unsigned int flags;
-    TPRAccess access;
-    size_t length;
-    off_t addr_offset;
-} TPRInstruction;
-
-/* must be sorted by length, shortest first */
-static const TPRInstruction tpr_instr[] = {
-    { /* mov abs to eax */
-        .opcode = 0xa1,
-        .access = TPR_ACCESS_READ,
-        .length = 5,
-        .addr_offset = 1,
-    },
-    { /* mov eax to abs */
-        .opcode = 0xa3,
-        .access = TPR_ACCESS_WRITE,
-        .length = 5,
-        .addr_offset = 1,
-    },
-    { /* mov r32 to r/m32 */
-        .opcode = 0x89,
-        .flags = TPR_INSTR_ABS_MODRM,
-        .access = TPR_ACCESS_WRITE,
-        .length = 6,
-        .addr_offset = 2,
-    },
-    { /* mov r/m32 to r32 */
-        .opcode = 0x8b,
-        .flags = TPR_INSTR_ABS_MODRM,
-        .access = TPR_ACCESS_READ,
-        .length = 6,
-        .addr_offset = 2,
-    },
-    { /* push r/m32 */
-        .opcode = 0xff,
-        .modrm_reg = 6,
-        .flags = TPR_INSTR_ABS_MODRM | TPR_INSTR_MATCH_MODRM_REG,
-        .access = TPR_ACCESS_READ,
-        .length = 6,
-        .addr_offset = 2,
-    },
-    { /* mov imm32, r/m32 (c7/0) */
-        .opcode = 0xc7,
-        .modrm_reg = 0,
-        .flags = TPR_INSTR_ABS_MODRM | TPR_INSTR_MATCH_MODRM_REG,
-        .access = TPR_ACCESS_WRITE,
-        .length = 10,
-        .addr_offset = 2,
-    },
-};
-
-static void read_guest_rom_state(VAPICROMState *s)
-{
-    cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
-                           sizeof(GuestROMState), 0);
-}
-
-static void write_guest_rom_state(VAPICROMState *s)
-{
-    cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
-                           sizeof(GuestROMState), 1);
-}
-
-static void update_guest_rom_state(VAPICROMState *s)
-{
-    read_guest_rom_state(s);
-
-    s->rom_state.real_tpr_addr = cpu_to_le32(s->real_tpr_addr);
-    s->rom_state.vcpu_shift = cpu_to_le32(VAPIC_CPU_SHIFT);
-
-    write_guest_rom_state(s);
-}
-
-static int find_real_tpr_addr(VAPICROMState *s, CPUX86State *env)
-{
-    hwaddr paddr;
-    target_ulong addr;
-
-    if (s->state == VAPIC_ACTIVE) {
-        return 0;
-    }
-    /*
-     * If there is no prior TPR access instruction we could analyze (which is
-     * the case after resume from hibernation), we need to scan the possible
-     * virtual address space for the APIC mapping.
-     */
-    for (addr = 0xfffff000; addr >= 0x80000000; addr -= TARGET_PAGE_SIZE) {
-        paddr = cpu_get_phys_page_debug(env, addr);
-        if (paddr != APIC_DEFAULT_ADDRESS) {
-            continue;
-        }
-        s->real_tpr_addr = addr + 0x80;
-        update_guest_rom_state(s);
-        return 0;
-    }
-    return -1;
-}
-
-static uint8_t modrm_reg(uint8_t modrm)
-{
-    return (modrm >> 3) & 7;
-}
-
-static bool is_abs_modrm(uint8_t modrm)
-{
-    return (modrm & 0xc7) == 0x05;
-}
-
-static bool opcode_matches(uint8_t *opcode, const TPRInstruction *instr)
-{
-    return opcode[0] == instr->opcode &&
-        (!(instr->flags & TPR_INSTR_ABS_MODRM) || is_abs_modrm(opcode[1])) &&
-        (!(instr->flags & TPR_INSTR_MATCH_MODRM_REG) ||
-         modrm_reg(opcode[1]) == instr->modrm_reg);
-}
-
-static int evaluate_tpr_instruction(VAPICROMState *s, CPUX86State *env,
-                                    target_ulong *pip, TPRAccess access)
-{
-    const TPRInstruction *instr;
-    target_ulong ip = *pip;
-    uint8_t opcode[2];
-    uint32_t real_tpr_addr;
-    int i;
-
-    if ((ip & 0xf0000000ULL) != 0x80000000ULL &&
-        (ip & 0xf0000000ULL) != 0xe0000000ULL) {
-        return -1;
-    }
-
-    /*
-     * Early Windows 2003 SMP initialization contains a
-     *
-     *   mov imm32, r/m32
-     *
-     * instruction that is patched by TPR optimization. The problem is that
-     * RSP, used by the patched instruction, is zero, so the guest gets a
-     * double fault and dies.
-     */
-    if (env->regs[R_ESP] == 0) {
-        return -1;
-    }
-
-    if (kvm_enabled() && !kvm_irqchip_in_kernel()) {
-        /*
-         * KVM without kernel-based TPR access reporting will pass an IP that
-         * points after the accessing instruction. So we need to look backward
-         * to find the reason.
-         */
-        for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
-            instr = &tpr_instr[i];
-            if (instr->access != access) {
-                continue;
-            }
-            if (cpu_memory_rw_debug(env, ip - instr->length, opcode,
-                                    sizeof(opcode), 0) < 0) {
-                return -1;
-            }
-            if (opcode_matches(opcode, instr)) {
-                ip -= instr->length;
-                goto instruction_ok;
-            }
-        }
-        return -1;
-    } else {
-        if (cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0) < 0) {
-            return -1;
-        }
-        for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
-            instr = &tpr_instr[i];
-            if (opcode_matches(opcode, instr)) {
-                goto instruction_ok;
-            }
-        }
-        return -1;
-    }
-
-instruction_ok:
-    /*
-     * Grab the virtual TPR address from the instruction
-     * and update the cached values.
-     */
-    if (cpu_memory_rw_debug(env, ip + instr->addr_offset,
-                            (void *)&real_tpr_addr,
-                            sizeof(real_tpr_addr), 0) < 0) {
-        return -1;
-    }
-    real_tpr_addr = le32_to_cpu(real_tpr_addr);
-    if ((real_tpr_addr & 0xfff) != 0x80) {
-        return -1;
-    }
-    s->real_tpr_addr = real_tpr_addr;
-    update_guest_rom_state(s);
-
-    *pip = ip;
-    return 0;
-}
-
-static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong ip)
-{
-    hwaddr paddr;
-    uint32_t rom_state_vaddr;
-    uint32_t pos, patch, offset;
-
-    /* nothing to do if already activated */
-    if (s->state == VAPIC_ACTIVE) {
-        return 0;
-    }
-
-    /* bail out if ROM init code was not executed (missing ROM?) */
-    if (s->state == VAPIC_INACTIVE) {
-        return -1;
-    }
-
-    /* find out virtual address of the ROM */
-    rom_state_vaddr = s->rom_state_paddr + (ip & 0xf0000000);
-    paddr = cpu_get_phys_page_debug(env, rom_state_vaddr);
-    if (paddr == -1) {
-        return -1;
-    }
-    paddr += rom_state_vaddr & ~TARGET_PAGE_MASK;
-    if (paddr != s->rom_state_paddr) {
-        return -1;
-    }
-    read_guest_rom_state(s);
-    if (memcmp(s->rom_state.signature, "kvm aPiC", 8) != 0) {
-        return -1;
-    }
-    s->rom_state_vaddr = rom_state_vaddr;
-
-    /* fixup addresses in ROM if needed */
-    if (rom_state_vaddr == le32_to_cpu(s->rom_state.vaddr)) {
-        return 0;
-    }
-    for (pos = le32_to_cpu(s->rom_state.fixup_start);
-         pos < le32_to_cpu(s->rom_state.fixup_end);
-         pos += 4) {
-        cpu_physical_memory_rw(paddr + pos - s->rom_state.vaddr,
-                               (void *)&offset, sizeof(offset), 0);
-        offset = le32_to_cpu(offset);
-        cpu_physical_memory_rw(paddr + offset, (void *)&patch,
-                               sizeof(patch), 0);
-        patch = le32_to_cpu(patch);
-        patch += rom_state_vaddr - le32_to_cpu(s->rom_state.vaddr);
-        patch = cpu_to_le32(patch);
-        cpu_physical_memory_rw(paddr + offset, (void *)&patch,
-                               sizeof(patch), 1);
-    }
-    read_guest_rom_state(s);
-    s->vapic_paddr = paddr + le32_to_cpu(s->rom_state.vapic_vaddr) -
-        le32_to_cpu(s->rom_state.vaddr);
-
-    return 0;
-}
-
-/*
- * Tries to read the unique processor number from the Kernel Processor Control
- * Region (KPCR) of 32-bit Windows XP and Server 2003. Returns -1 if the KPCR
- * cannot be accessed or is considered invalid. This also ensures that we are
- * not patching the wrong guest.
- */
-static int get_kpcr_number(CPUX86State *env)
-{
-    struct kpcr {
-        uint8_t  fill1[0x1c];
-        uint32_t self;
-        uint8_t  fill2[0x31];
-        uint8_t  number;
-    } QEMU_PACKED kpcr;
-
-    if (cpu_memory_rw_debug(env, env->segs[R_FS].base,
-                            (void *)&kpcr, sizeof(kpcr), 0) < 0 ||
-        kpcr.self != env->segs[R_FS].base) {
-        return -1;
-    }
-    return kpcr.number;
-}
-
-static int vapic_enable(VAPICROMState *s, CPUX86State *env)
-{
-    int cpu_number = get_kpcr_number(env);
-    hwaddr vapic_paddr;
-    static const uint8_t enabled = 1;
-
-    if (cpu_number < 0) {
-        return -1;
-    }
-    vapic_paddr = s->vapic_paddr +
-        (((hwaddr)cpu_number) << VAPIC_CPU_SHIFT);
-    cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled),
-                           (void *)&enabled, sizeof(enabled), 1);
-    apic_enable_vapic(env->apic_state, vapic_paddr);
-
-    s->state = VAPIC_ACTIVE;
-
-    return 0;
-}
-
-static void patch_byte(CPUX86State *env, target_ulong addr, uint8_t byte)
-{
-    cpu_memory_rw_debug(env, addr, &byte, 1, 1);
-}
-
-static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip,
-                       uint32_t target)
-{
-    uint32_t offset;
-
-    offset = cpu_to_le32(target - ip - 5);
-    patch_byte(env, ip, 0xe8); /* call near */
-    cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1);
-}
-
-static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
-{
-    CPUState *cs = CPU(cpu);
-    CPUX86State *env = &cpu->env;
-    VAPICHandlers *handlers;
-    uint8_t opcode[2];
-    uint32_t imm32;
-    target_ulong current_pc = 0;
-    target_ulong current_cs_base = 0;
-    int current_flags = 0;
-
-    if (smp_cpus == 1) {
-        handlers = &s->rom_state.up;
-    } else {
-        handlers = &s->rom_state.mp;
-    }
-
-    if (!kvm_enabled()) {
-        cpu_restore_state(env, env->mem_io_pc);
-        cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
-                             &current_flags);
-    }
-
-    pause_all_vcpus();
-
-    cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0);
-
-    switch (opcode[0]) {
-    case 0x89: /* mov r32 to r/m32 */
-        patch_byte(env, ip, 0x50 + modrm_reg(opcode[1]));  /* push reg */
-        patch_call(s, env, ip + 1, handlers->set_tpr);
-        break;
-    case 0x8b: /* mov r/m32 to r32 */
-        patch_byte(env, ip, 0x90);
-        patch_call(s, env, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
-        break;
-    case 0xa1: /* mov abs to eax */
-        patch_call(s, env, ip, handlers->get_tpr[0]);
-        break;
-    case 0xa3: /* mov eax to abs */
-        patch_call(s, env, ip, handlers->set_tpr_eax);
-        break;
-    case 0xc7: /* mov imm32, r/m32 (c7/0) */
-        patch_byte(env, ip, 0x68);  /* push imm32 */
-        cpu_memory_rw_debug(env, ip + 6, (void *)&imm32, sizeof(imm32), 0);
-        cpu_memory_rw_debug(env, ip + 1, (void *)&imm32, sizeof(imm32), 1);
-        patch_call(s, env, ip + 5, handlers->set_tpr);
-        break;
-    case 0xff: /* push r/m32 */
-        patch_byte(env, ip, 0x50); /* push eax */
-        patch_call(s, env, ip + 1, handlers->get_tpr_stack);
-        break;
-    default:
-        abort();
-    }
-
-    resume_all_vcpus();
-
-    if (!kvm_enabled()) {
-        cs->current_tb = NULL;
-        tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
-        cpu_resume_from_signal(env, NULL);
-    }
-}
-
-void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip,
-                             TPRAccess access)
-{
-    VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
-    X86CPU *cpu = X86_CPU(cs);
-    CPUX86State *env = &cpu->env;
-
-    cpu_synchronize_state(env);
-
-    if (evaluate_tpr_instruction(s, env, &ip, access) < 0) {
-        if (s->state == VAPIC_ACTIVE) {
-            vapic_enable(s, env);
-        }
-        return;
-    }
-    if (update_rom_mapping(s, env, ip) < 0) {
-        return;
-    }
-    if (vapic_enable(s, env) < 0) {
-        return;
-    }
-    patch_instruction(s, cpu, ip);
-}
-
-typedef struct VAPICEnableTPRReporting {
-    DeviceState *apic;
-    bool enable;
-} VAPICEnableTPRReporting;
-
-static void vapic_do_enable_tpr_reporting(void *data)
-{
-    VAPICEnableTPRReporting *info = data;
-
-    apic_enable_tpr_access_reporting(info->apic, info->enable);
-}
-
-static void vapic_enable_tpr_reporting(bool enable)
-{
-    VAPICEnableTPRReporting info = {
-        .enable = enable,
-    };
-    X86CPU *cpu;
-    CPUX86State *env;
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = x86_env_get_cpu(env);
-        info.apic = env->apic_state;
-        run_on_cpu(CPU(cpu), vapic_do_enable_tpr_reporting, &info);
-    }
-}
-
-static void vapic_reset(DeviceState *dev)
-{
-    VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
-
-    if (s->state == VAPIC_ACTIVE) {
-        s->state = VAPIC_STANDBY;
-    }
-    vapic_enable_tpr_reporting(false);
-}
-
-/*
- * Set the IRQ polling hypercalls to the supported variant:
- *  - vmcall if using KVM in-kernel irqchip
- *  - 32-bit VAPIC port write otherwise
- */
-static int patch_hypercalls(VAPICROMState *s)
-{
-    hwaddr rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK;
-    static const uint8_t vmcall_pattern[] = { /* vmcall */
-        0xb8, 0x1, 0, 0, 0, 0xf, 0x1, 0xc1
-    };
-    static const uint8_t outl_pattern[] = { /* nop; outl %eax,0x7e */
-        0xb8, 0x1, 0, 0, 0, 0x90, 0xe7, 0x7e
-    };
-    uint8_t alternates[2];
-    const uint8_t *pattern;
-    const uint8_t *patch;
-    int patches = 0;
-    off_t pos;
-    uint8_t *rom;
-
-    rom = g_malloc(s->rom_size);
-    cpu_physical_memory_rw(rom_paddr, rom, s->rom_size, 0);
-
-    for (pos = 0; pos < s->rom_size - sizeof(vmcall_pattern); pos++) {
-        if (kvm_irqchip_in_kernel()) {
-            pattern = outl_pattern;
-            alternates[0] = outl_pattern[7];
-            alternates[1] = outl_pattern[7];
-            patch = &vmcall_pattern[5];
-        } else {
-            pattern = vmcall_pattern;
-            alternates[0] = vmcall_pattern[7];
-            alternates[1] = 0xd9; /* AMD's VMMCALL */
-            patch = &outl_pattern[5];
-        }
-        if (memcmp(rom + pos, pattern, 7) == 0 &&
-            (rom[pos + 7] == alternates[0] || rom[pos + 7] == alternates[1])) {
-            cpu_physical_memory_rw(rom_paddr + pos + 5, (uint8_t *)patch,
-                                   3, 1);
-            /*
-             * Don't flush the tb here. Under ordinary conditions, the patched
-             * calls are miles away from the current IP. Under malicious
-             * conditions, the guest could trick us to crash.
-             */
-        }
-    }
-
-    g_free(rom);
-
-    if (patches != 0 && patches != 2) {
-        return -1;
-    }
-
-    return 0;
-}
-
-/*
- * For TCG mode or the time KVM honors read-only memory regions, we need to
- * enable write access to the option ROM so that variables can be updated by
- * the guest.
- */
-static void vapic_map_rom_writable(VAPICROMState *s)
-{
-    hwaddr rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK;
-    MemoryRegionSection section;
-    MemoryRegion *as;
-    size_t rom_size;
-    uint8_t *ram;
-
-    as = sysbus_address_space(&s->busdev);
-
-    if (s->rom_mapped_writable) {
-        memory_region_del_subregion(as, &s->rom);
-        memory_region_destroy(&s->rom);
-    }
-
-    /* grab RAM memory region (region @rom_paddr may still be pc.rom) */
-    section = memory_region_find(as, 0, 1);
-
-    /* read ROM size from RAM region */
-    ram = memory_region_get_ram_ptr(section.mr);
-    rom_size = ram[rom_paddr + 2] * ROM_BLOCK_SIZE;
-    s->rom_size = rom_size;
-
-    /* We need to round to avoid creating subpages
-     * from which we cannot run code. */
-    rom_size += rom_paddr & ~TARGET_PAGE_MASK;
-    rom_paddr &= TARGET_PAGE_MASK;
-    rom_size = TARGET_PAGE_ALIGN(rom_size);
-
-    memory_region_init_alias(&s->rom, "kvmvapic-rom", section.mr, rom_paddr,
-                             rom_size);
-    memory_region_add_subregion_overlap(as, rom_paddr, &s->rom, 1000);
-    s->rom_mapped_writable = true;
-}
-
-static int vapic_prepare(VAPICROMState *s)
-{
-    vapic_map_rom_writable(s);
-
-    if (patch_hypercalls(s) < 0) {
-        return -1;
-    }
-
-    vapic_enable_tpr_reporting(true);
-
-    return 0;
-}
-
-static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
-                        unsigned int size)
-{
-    CPUX86State *env = cpu_single_env;
-    hwaddr rom_paddr;
-    VAPICROMState *s = opaque;
-
-    cpu_synchronize_state(env);
-
-    /*
-     * The VAPIC supports two PIO-based hypercalls, both via port 0x7E.
-     *  o 16-bit write access:
-     *    Reports the option ROM initialization to the hypervisor. Written
-     *    value is the offset of the state structure in the ROM.
-     *  o 8-bit write access:
-     *    Reactivates the VAPIC after a guest hibernation, i.e. after the
-     *    option ROM content has been re-initialized by a guest power cycle.
-     *  o 32-bit write access:
-     *    Poll for pending IRQs, considering the current VAPIC state.
-     */
-    switch (size) {
-    case 2:
-        if (s->state == VAPIC_INACTIVE) {
-            rom_paddr = (env->segs[R_CS].base + env->eip) & ROM_BLOCK_MASK;
-            s->rom_state_paddr = rom_paddr + data;
-
-            s->state = VAPIC_STANDBY;
-        }
-        if (vapic_prepare(s) < 0) {
-            s->state = VAPIC_INACTIVE;
-            break;
-        }
-        break;
-    case 1:
-        if (kvm_enabled()) {
-            /*
-             * Disable triggering instruction in ROM by writing a NOP.
-             *
-             * We cannot do this in TCG mode as the reported IP is not
-             * accurate.
-             */
-            pause_all_vcpus();
-            patch_byte(env, env->eip - 2, 0x66);
-            patch_byte(env, env->eip - 1, 0x90);
-            resume_all_vcpus();
-        }
-
-        if (s->state == VAPIC_ACTIVE) {
-            break;
-        }
-        if (update_rom_mapping(s, env, env->eip) < 0) {
-            break;
-        }
-        if (find_real_tpr_addr(s, env) < 0) {
-            break;
-        }
-        vapic_enable(s, env);
-        break;
-    default:
-    case 4:
-        if (!kvm_irqchip_in_kernel()) {
-            apic_poll_irq(env->apic_state);
-        }
-        break;
-    }
-}
-
-static const MemoryRegionOps vapic_ops = {
-    .write = vapic_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int vapic_init(SysBusDevice *dev)
-{
-    VAPICROMState *s = FROM_SYSBUS(VAPICROMState, dev);
-
-    memory_region_init_io(&s->io, &vapic_ops, s, "kvmvapic", 2);
-    sysbus_add_io(dev, VAPIC_IO_PORT, &s->io);
-    sysbus_init_ioports(dev, VAPIC_IO_PORT, 2);
-
-    option_rom[nb_option_roms].name = "kvmvapic.bin";
-    option_rom[nb_option_roms].bootindex = -1;
-    nb_option_roms++;
-
-    return 0;
-}
-
-static void do_vapic_enable(void *data)
-{
-    VAPICROMState *s = data;
-
-    vapic_enable(s, first_cpu);
-}
-
-static int vapic_post_load(void *opaque, int version_id)
-{
-    VAPICROMState *s = opaque;
-    uint8_t *zero;
-
-    /*
-     * The old implementation of qemu-kvm did not provide the state
-     * VAPIC_STANDBY. Reconstruct it.
-     */
-    if (s->state == VAPIC_INACTIVE && s->rom_state_paddr != 0) {
-        s->state = VAPIC_STANDBY;
-    }
-
-    if (s->state != VAPIC_INACTIVE) {
-        if (vapic_prepare(s) < 0) {
-            return -1;
-        }
-    }
-    if (s->state == VAPIC_ACTIVE) {
-        if (smp_cpus == 1) {
-            run_on_cpu(ENV_GET_CPU(first_cpu), do_vapic_enable, s);
-        } else {
-            zero = g_malloc0(s->rom_state.vapic_size);
-            cpu_physical_memory_rw(s->vapic_paddr, zero,
-                                   s->rom_state.vapic_size, 1);
-            g_free(zero);
-        }
-    }
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_handlers = {
-    .name = "kvmvapic-handlers",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(set_tpr, VAPICHandlers),
-        VMSTATE_UINT32(set_tpr_eax, VAPICHandlers),
-        VMSTATE_UINT32_ARRAY(get_tpr, VAPICHandlers, 8),
-        VMSTATE_UINT32(get_tpr_stack, VAPICHandlers),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_guest_rom = {
-    .name = "kvmvapic-guest-rom",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UNUSED(8),     /* signature */
-        VMSTATE_UINT32(vaddr, GuestROMState),
-        VMSTATE_UINT32(fixup_start, GuestROMState),
-        VMSTATE_UINT32(fixup_end, GuestROMState),
-        VMSTATE_UINT32(vapic_vaddr, GuestROMState),
-        VMSTATE_UINT32(vapic_size, GuestROMState),
-        VMSTATE_UINT32(vcpu_shift, GuestROMState),
-        VMSTATE_UINT32(real_tpr_addr, GuestROMState),
-        VMSTATE_STRUCT(up, GuestROMState, 0, vmstate_handlers, VAPICHandlers),
-        VMSTATE_STRUCT(mp, GuestROMState, 0, vmstate_handlers, VAPICHandlers),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_vapic = {
-    .name = "kvm-tpr-opt",      /* compatible with qemu-kvm VAPIC */
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .post_load = vapic_post_load,
-    .fields = (VMStateField[]) {
-        VMSTATE_STRUCT(rom_state, VAPICROMState, 0, vmstate_guest_rom,
-                       GuestROMState),
-        VMSTATE_UINT32(state, VAPICROMState),
-        VMSTATE_UINT32(real_tpr_addr, VAPICROMState),
-        VMSTATE_UINT32(rom_state_vaddr, VAPICROMState),
-        VMSTATE_UINT32(vapic_paddr, VAPICROMState),
-        VMSTATE_UINT32(rom_state_paddr, VAPICROMState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void vapic_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->no_user = 1;
-    dc->reset   = vapic_reset;
-    dc->vmsd    = &vmstate_vapic;
-    sc->init    = vapic_init;
-}
-
-static const TypeInfo vapic_type = {
-    .name          = "kvmvapic",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(VAPICROMState),
-    .class_init    = vapic_class_init,
-};
-
-static void vapic_register(void)
-{
-    type_register_static(&vapic_type);
-}
-
-type_init(vapic_register);
diff --git a/hw/kzm.c b/hw/kzm.c
deleted file mode 100644 (file)
index fb33165..0000000
--- a/hw/kzm.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * KZM Board System emulation.
- *
- * Copyright (c) 2008 OKL and 2011 NICTA
- * Written by Hans at OK-Labs
- * Updated by Peter Chubb.
- *
- * This code is licensed under the GPL, version 2 or later.
- * See the file `COPYING' in the top level directory.
- *
- * It (partially) emulates a Kyoto Microcomputer
- * KZM-ARM11-01 evaluation board, with a Freescale
- * i.MX31 SoC
- */
-
-#include "sysbus.h"
-#include "exec/address-spaces.h"
-#include "hw.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "serial.h"
-#include "imx.h"
-
-    /* Memory map for Kzm Emulation Baseboard:
-     * 0x00000000-0x00003fff 16k secure ROM       IGNORED
-     * 0x00004000-0x00407fff Reserved             IGNORED
-     * 0x00404000-0x00407fff ROM                  IGNORED
-     * 0x00408000-0x0fffffff Reserved             IGNORED
-     * 0x10000000-0x1fffbfff RAM aliasing         IGNORED
-     * 0x1fffc000-0x1fffffff RAM                  EMULATED
-     * 0x20000000-0x2fffffff Reserved             IGNORED
-     * 0x30000000-0x7fffffff I.MX31 Internal Register Space
-     *   0x43f00000 IO_AREA0
-     *   0x43f90000 UART1                         EMULATED
-     *   0x43f94000 UART2                         EMULATED
-     *   0x68000000 AVIC                          EMULATED
-     *   0x53f80000 CCM                           EMULATED
-     *   0x53f94000 PIT 1                         EMULATED
-     *   0x53f98000 PIT 2                         EMULATED
-     *   0x53f90000 GPT                           EMULATED
-     * 0x80000000-0x87ffffff RAM                  EMULATED
-     * 0x88000000-0x8fffffff RAM Aliasing         EMULATED
-     * 0xa0000000-0xafffffff NAND Flash           IGNORED
-     * 0xb0000000-0xb3ffffff Unavailable          IGNORED
-     * 0xb4000000-0xb4000fff 8-bit free space     IGNORED
-     * 0xb4001000-0xb400100f Board control        IGNORED
-     *  0xb4001003           DIP switch
-     * 0xb4001010-0xb400101f 7-segment LED        IGNORED
-     * 0xb4001020-0xb400102f LED                  IGNORED
-     * 0xb4001030-0xb400103f LED                  IGNORED
-     * 0xb4001040-0xb400104f FPGA, UART           EMULATED
-     * 0xb4001050-0xb400105f FPGA, UART           EMULATED
-     * 0xb4001060-0xb40fffff FPGA                 IGNORED
-     * 0xb6000000-0xb61fffff LAN controller       EMULATED
-     * 0xb6200000-0xb62fffff FPGA NAND Controller IGNORED
-     * 0xb6300000-0xb7ffffff Free                 IGNORED
-     * 0xb8000000-0xb8004fff Memory control registers IGNORED
-     * 0xc0000000-0xc3ffffff PCMCIA/CF            IGNORED
-     * 0xc4000000-0xffffffff Reserved             IGNORED
-     */
-
-#define KZM_RAMADDRESS (0x80000000)
-#define KZM_FPGA       (0xb4001040)
-
-static struct arm_boot_info kzm_binfo = {
-    .loader_start = KZM_RAMADDRESS,
-    .board_id = 1722,
-};
-
-static void kzm_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    ARMCPU *cpu;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
-    qemu_irq *cpu_pic;
-    DeviceState *dev;
-    DeviceState *ccm;
-
-    if (!cpu_model) {
-        cpu_model = "arm1136";
-    }
-
-    cpu = cpu_arm_init(cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-
-    /* On a real system, the first 16k is a `secure boot rom' */
-
-    memory_region_init_ram(ram, "kzm.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram);
-
-    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
-    memory_region_add_subregion(address_space_mem, 0x88000000, ram_alias);
-
-    memory_region_init_ram(sram, "kzm.sram", 0x4000);
-    memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram);
-
-    cpu_pic = arm_pic_init_cpu(cpu);
-    dev = sysbus_create_varargs("imx_avic", 0x68000000,
-                                cpu_pic[ARM_PIC_CPU_IRQ],
-                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
-
-
-    imx_serial_create(0, 0x43f90000, qdev_get_gpio_in(dev, 45));
-    imx_serial_create(1, 0x43f94000, qdev_get_gpio_in(dev, 32));
-
-    ccm = sysbus_create_simple("imx_ccm", 0x53f80000, NULL);
-
-    imx_timerp_create(0x53f94000, qdev_get_gpio_in(dev, 28), ccm);
-    imx_timerp_create(0x53f98000, qdev_get_gpio_in(dev, 27), ccm);
-    imx_timerg_create(0x53f90000, qdev_get_gpio_in(dev, 29), ccm);
-
-    if (nd_table[0].used) {
-        lan9118_init(&nd_table[0], 0xb6000000, qdev_get_gpio_in(dev, 52));
-    }
-
-    if (serial_hds[2]) { /* touchscreen */
-        serial_mm_init(address_space_mem, KZM_FPGA+0x10, 0,
-                       qdev_get_gpio_in(dev, 52),
-                       14745600, serial_hds[2],
-                       DEVICE_NATIVE_ENDIAN);
-    }
-
-    kzm_binfo.ram_size = ram_size;
-    kzm_binfo.kernel_filename = kernel_filename;
-    kzm_binfo.kernel_cmdline = kernel_cmdline;
-    kzm_binfo.initrd_filename = initrd_filename;
-    kzm_binfo.nb_cpus = 1;
-    arm_load_kernel(cpu, &kzm_binfo);
-}
-
-static QEMUMachine kzm_machine = {
-    .name = "kzm",
-    .desc = "ARM KZM Emulation Baseboard (ARM1136)",
-    .init = kzm_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void kzm_machine_init(void)
-{
-    qemu_register_machine(&kzm_machine);
-}
-
-machine_init(kzm_machine_init)
index 0e844e535c3a679df6ba9f8ff7204157b560f42b..403fb868aeab3b4d5127f52e30e72f085d6915dd 100644 (file)
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
-#include "devices.h"
+#include "hw/devices.h"
 #include "sysemu/sysemu.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 /* For crc32 */
 #include <zlib.h>
 
index 4b9242529928ab29e734a200bf6d26749b65ed37..acfffaed31091163cc8d168d24e083ad622ced3b 100644 (file)
  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
 #include "qemu/timer.h"
 #include "qemu/sockets.h"
-#include "sun4m.h"
-#include "pcnet.h"
+#include "hw/sun4m.h"
+#include "hw/pcnet.h"
 #include "trace.h"
 
 typedef struct {
diff --git a/hw/leon3.c b/hw/leon3.c
deleted file mode 100644 (file)
index f16a8bb..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * QEMU Leon3 System Emulator
- *
- * Copyright (c) 2010-2011 AdaCore
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "qemu/timer.h"
-#include "ptimer.h"
-#include "char/char.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "loader.h"
-#include "elf.h"
-#include "trace.h"
-#include "exec/address-spaces.h"
-
-#include "grlib.h"
-
-/* Default system clock.  */
-#define CPU_CLK (40 * 1000 * 1000)
-
-#define PROM_FILENAME        "u-boot.bin"
-
-#define MAX_PILS 16
-
-typedef struct ResetData {
-    SPARCCPU *cpu;
-    uint32_t  entry;            /* save kernel entry in case of reset */
-} ResetData;
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetData *s   = (ResetData *)opaque;
-    CPUSPARCState  *env = &s->cpu->env;
-
-    cpu_reset(CPU(s->cpu));
-
-    env->halted = 0;
-    env->pc     = s->entry;
-    env->npc    = s->entry + 4;
-}
-
-void leon3_irq_ack(void *irq_manager, int intno)
-{
-    grlib_irqmp_ack((DeviceState *)irq_manager, intno);
-}
-
-static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
-{
-    CPUSPARCState *env = (CPUSPARCState *)opaque;
-
-    assert(env != NULL);
-
-    env->pil_in = pil_in;
-
-    if (env->pil_in && (env->interrupt_index == 0 ||
-                        (env->interrupt_index & ~15) == TT_EXTINT)) {
-        unsigned int i;
-
-        for (i = 15; i > 0; i--) {
-            if (env->pil_in & (1 << i)) {
-                int old_interrupt = env->interrupt_index;
-
-                env->interrupt_index = TT_EXTINT | i;
-                if (old_interrupt != env->interrupt_index) {
-                    trace_leon3_set_irq(i);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
-                }
-                break;
-            }
-        }
-    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
-        trace_leon3_reset_irq(env->interrupt_index & 15);
-        env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-static void leon3_generic_hw_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    SPARCCPU *cpu;
-    CPUSPARCState   *env;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *prom = g_new(MemoryRegion, 1);
-    int         ret;
-    char       *filename;
-    qemu_irq   *cpu_irqs = NULL;
-    int         bios_size;
-    int         prom_size;
-    ResetData  *reset_info;
-
-    /* Init CPU */
-    if (!cpu_model) {
-        cpu_model = "LEON3";
-    }
-
-    cpu = cpu_sparc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    cpu_sparc_set_id(env, 0);
-
-    /* Reset data */
-    reset_info        = g_malloc0(sizeof(ResetData));
-    reset_info->cpu   = cpu;
-    qemu_register_reset(main_cpu_reset, reset_info);
-
-    /* Allocate IRQ manager */
-    grlib_irqmp_create(0x80000200, env, &cpu_irqs, MAX_PILS, &leon3_set_pil_in);
-
-    env->qemu_irq_ack = leon3_irq_manager;
-
-    /* Allocate RAM */
-    if ((uint64_t)ram_size > (1UL << 30)) {
-        fprintf(stderr,
-                "qemu: Too much memory for this machine: %d, maximum 1G\n",
-                (unsigned int)(ram_size / (1024 * 1024)));
-        exit(1);
-    }
-
-    memory_region_init_ram(ram, "leon3.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, 0x40000000, ram);
-
-    /* Allocate BIOS */
-    prom_size = 8 * 1024 * 1024; /* 8Mb */
-    memory_region_init_ram(prom, "Leon3.bios", prom_size);
-    vmstate_register_ram_global(prom);
-    memory_region_set_readonly(prom, true);
-    memory_region_add_subregion(address_space_mem, 0x00000000, prom);
-
-    /* Load boot prom */
-    if (bios_name == NULL) {
-        bios_name = PROM_FILENAME;
-    }
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-
-    bios_size = get_image_size(filename);
-
-    if (bios_size > prom_size) {
-        fprintf(stderr, "qemu: could not load prom '%s': file too big\n",
-                filename);
-        exit(1);
-    }
-
-    if (bios_size > 0) {
-        ret = load_image_targphys(filename, 0x00000000, bios_size);
-        if (ret < 0 || ret > prom_size) {
-            fprintf(stderr, "qemu: could not load prom '%s'\n", filename);
-            exit(1);
-        }
-    } else if (kernel_filename == NULL) {
-        fprintf(stderr, "Can't read bios image %s\n", filename);
-        exit(1);
-    }
-
-    /* Can directly load an application. */
-    if (kernel_filename != NULL) {
-        long     kernel_size;
-        uint64_t entry;
-
-        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
-                               1 /* big endian */, ELF_MACHINE, 0);
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-        if (bios_size <= 0) {
-            /* If there is no bios/monitor, start the application.  */
-            env->pc = entry;
-            env->npc = entry + 4;
-            reset_info->entry = entry;
-        }
-    }
-
-    /* Allocate timers */
-    grlib_gptimer_create(0x80000300, 2, CPU_CLK, cpu_irqs, 6);
-
-    /* Allocate uart */
-    if (serial_hds[0]) {
-        grlib_apbuart_create(0x80000100, serial_hds[0], cpu_irqs[3]);
-    }
-}
-
-static QEMUMachine leon3_generic_machine = {
-    .name     = "leon3_generic",
-    .desc     = "Leon-3 generic",
-    .init     = leon3_generic_hw_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void leon3_machine_init(void)
-{
-    qemu_register_machine(&leon3_generic_machine);
-}
-
-machine_init(leon3_machine_init);
index 4e1843c11d0fc5b266db73022b1bb5d960de466b..4592fe5fc868826a25098284449d327ffa90b0ca 100644 (file)
@@ -1,7 +1,3 @@
-# LM32 boards
-obj-y += lm32_boards.o
-obj-y += milkymist.o
-
 # LM32 peripherals
 obj-y += lm32_pic.o
 obj-y += lm32_juart.o
@@ -21,3 +17,7 @@ obj-y += milkymist-vgafb.o
 obj-y += framebuffer.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+# LM32 boards
+obj-y += lm32_boards.o
+obj-y += milkymist.o
diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
new file mode 100644 (file)
index 0000000..1ce466a
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ *  QEMU models for LatticeMico32 uclinux and evr32 boards.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "sysemu/blockdev.h"
+#include "elf.h"
+#include "hw/lm32_hwsetup.h"
+#include "hw/lm32.h"
+#include "exec/address-spaces.h"
+
+typedef struct {
+    LM32CPU *cpu;
+    hwaddr bootstrap_pc;
+    hwaddr flash_base;
+    hwaddr hwsetup_base;
+    hwaddr initrd_base;
+    size_t initrd_size;
+    hwaddr cmdline_base;
+} ResetInfo;
+
+static void cpu_irq_handler(void *opaque, int irq, int level)
+{
+    CPULM32State *env = opaque;
+
+    if (level) {
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetInfo *reset_info = opaque;
+    CPULM32State *env = &reset_info->cpu->env;
+
+    cpu_reset(CPU(reset_info->cpu));
+
+    /* init defaults */
+    env->pc = (uint32_t)reset_info->bootstrap_pc;
+    env->regs[R_R1] = (uint32_t)reset_info->hwsetup_base;
+    env->regs[R_R2] = (uint32_t)reset_info->cmdline_base;
+    env->regs[R_R3] = (uint32_t)reset_info->initrd_base;
+    env->regs[R_R4] = (uint32_t)(reset_info->initrd_base +
+        reset_info->initrd_size);
+    env->eba = reset_info->flash_base;
+    env->deba = reset_info->flash_base;
+}
+
+static void lm32_evr_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    LM32CPU *cpu;
+    CPULM32State *env;
+    DriveInfo *dinfo;
+    MemoryRegion *address_space_mem =  get_system_memory();
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    qemu_irq *cpu_irq, irq[32];
+    ResetInfo *reset_info;
+    int i;
+
+    /* memory map */
+    hwaddr flash_base  = 0x04000000;
+    size_t flash_sector_size       = 256 * 1024;
+    size_t flash_size              = 32 * 1024 * 1024;
+    hwaddr ram_base    = 0x08000000;
+    size_t ram_size                = 64 * 1024 * 1024;
+    hwaddr timer0_base = 0x80002000;
+    hwaddr uart0_base  = 0x80006000;
+    hwaddr timer1_base = 0x8000a000;
+    int uart0_irq                  = 0;
+    int timer0_irq                 = 1;
+    int timer1_irq                 = 3;
+
+    reset_info = g_malloc0(sizeof(ResetInfo));
+
+    if (cpu_model == NULL) {
+        cpu_model = "lm32-full";
+    }
+    cpu = cpu_lm32_init(cpu_model);
+    env = &cpu->env;
+    reset_info->cpu = cpu;
+
+    reset_info->flash_base = flash_base;
+
+    memory_region_init_ram(phys_ram, "lm32_evr.sdram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* Spansion S29NS128P */
+    pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size,
+                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
+                          flash_size / flash_sector_size, 1, 2,
+                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
+
+    /* create irq lines */
+    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
+    env->pic_state = lm32_pic_init(*cpu_irq);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(env->pic_state, i);
+    }
+
+    sysbus_create_simple("lm32-uart", uart0_base, irq[uart0_irq]);
+    sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]);
+    sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]);
+
+    /* make sure juart isn't the first chardev */
+    env->juart_state = lm32_juart_init();
+
+    reset_info->bootstrap_pc = flash_base;
+
+    if (kernel_filename) {
+        uint64_t entry;
+        int kernel_size;
+
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+                               1, ELF_MACHINE, 0);
+        reset_info->bootstrap_pc = entry;
+
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename, ram_base,
+                                              ram_size);
+            reset_info->bootstrap_pc = ram_base;
+        }
+
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    qemu_register_reset(main_cpu_reset, reset_info);
+}
+
+static void lm32_uclinux_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    LM32CPU *cpu;
+    CPULM32State *env;
+    DriveInfo *dinfo;
+    MemoryRegion *address_space_mem =  get_system_memory();
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    qemu_irq *cpu_irq, irq[32];
+    HWSetup *hw;
+    ResetInfo *reset_info;
+    int i;
+
+    /* memory map */
+    hwaddr flash_base   = 0x04000000;
+    size_t flash_sector_size        = 256 * 1024;
+    size_t flash_size               = 32 * 1024 * 1024;
+    hwaddr ram_base     = 0x08000000;
+    size_t ram_size                 = 64 * 1024 * 1024;
+    hwaddr uart0_base   = 0x80000000;
+    hwaddr timer0_base  = 0x80002000;
+    hwaddr timer1_base  = 0x80010000;
+    hwaddr timer2_base  = 0x80012000;
+    int uart0_irq                   = 0;
+    int timer0_irq                  = 1;
+    int timer1_irq                  = 20;
+    int timer2_irq                  = 21;
+    hwaddr hwsetup_base = 0x0bffe000;
+    hwaddr cmdline_base = 0x0bfff000;
+    hwaddr initrd_base  = 0x08400000;
+    size_t initrd_max               = 0x01000000;
+
+    reset_info = g_malloc0(sizeof(ResetInfo));
+
+    if (cpu_model == NULL) {
+        cpu_model = "lm32-full";
+    }
+    cpu = cpu_lm32_init(cpu_model);
+    env = &cpu->env;
+    reset_info->cpu = cpu;
+
+    reset_info->flash_base = flash_base;
+
+    memory_region_init_ram(phys_ram, "lm32_uclinux.sdram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* Spansion S29NS128P */
+    pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,
+                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
+                          flash_size / flash_sector_size, 1, 2,
+                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
+
+    /* create irq lines */
+    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
+    env->pic_state = lm32_pic_init(*cpu_irq);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(env->pic_state, i);
+    }
+
+    sysbus_create_simple("lm32-uart", uart0_base, irq[uart0_irq]);
+    sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]);
+    sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]);
+    sysbus_create_simple("lm32-timer", timer2_base, irq[timer2_irq]);
+
+    /* make sure juart isn't the first chardev */
+    env->juart_state = lm32_juart_init();
+
+    reset_info->bootstrap_pc = flash_base;
+
+    if (kernel_filename) {
+        uint64_t entry;
+        int kernel_size;
+
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+                               1, ELF_MACHINE, 0);
+        reset_info->bootstrap_pc = entry;
+
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename, ram_base,
+                                              ram_size);
+            reset_info->bootstrap_pc = ram_base;
+        }
+
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    /* generate a rom with the hardware description */
+    hw = hwsetup_init();
+    hwsetup_add_cpu(hw, "LM32", 75000000);
+    hwsetup_add_flash(hw, "flash", flash_base, flash_size);
+    hwsetup_add_ddr_sdram(hw, "ddr_sdram", ram_base, ram_size);
+    hwsetup_add_timer(hw, "timer0", timer0_base, timer0_irq);
+    hwsetup_add_timer(hw, "timer1_dev_only", timer1_base, timer1_irq);
+    hwsetup_add_timer(hw, "timer2_dev_only", timer2_base, timer2_irq);
+    hwsetup_add_uart(hw, "uart", uart0_base, uart0_irq);
+    hwsetup_add_trailer(hw);
+    hwsetup_create_rom(hw, hwsetup_base);
+    hwsetup_free(hw);
+
+    reset_info->hwsetup_base = hwsetup_base;
+
+    if (kernel_cmdline && strlen(kernel_cmdline)) {
+        pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE,
+                kernel_cmdline);
+        reset_info->cmdline_base = cmdline_base;
+    }
+
+    if (initrd_filename) {
+        size_t initrd_size;
+        initrd_size = load_image_targphys(initrd_filename, initrd_base,
+                initrd_max);
+        reset_info->initrd_base = initrd_base;
+        reset_info->initrd_size = initrd_size;
+    }
+
+    qemu_register_reset(main_cpu_reset, reset_info);
+}
+
+static QEMUMachine lm32_evr_machine = {
+    .name = "lm32-evr",
+    .desc = "LatticeMico32 EVR32 eval system",
+    .init = lm32_evr_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine lm32_uclinux_machine = {
+    .name = "lm32-uclinux",
+    .desc = "lm32 platform for uClinux and u-boot by Theobroma Systems",
+    .init = lm32_uclinux_init,
+    .is_default = 0,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void lm32_machine_init(void)
+{
+    qemu_register_machine(&lm32_uclinux_machine);
+    qemu_register_machine(&lm32_evr_machine);
+}
+
+machine_init(lm32_machine_init);
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
new file mode 100644 (file)
index 0000000..fd36de5
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ *  QEMU model for the Milkymist board.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
+#include "sysemu/sysemu.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "sysemu/blockdev.h"
+#include "hw/milkymist-hw.h"
+#include "hw/lm32.h"
+#include "exec/address-spaces.h"
+
+#define BIOS_FILENAME    "mmone-bios.bin"
+#define BIOS_OFFSET      0x00860000
+#define BIOS_SIZE        (512*1024)
+#define KERNEL_LOAD_ADDR 0x40000000
+
+typedef struct {
+    LM32CPU *cpu;
+    hwaddr bootstrap_pc;
+    hwaddr flash_base;
+    hwaddr initrd_base;
+    size_t initrd_size;
+    hwaddr cmdline_base;
+} ResetInfo;
+
+static void cpu_irq_handler(void *opaque, int irq, int level)
+{
+    CPULM32State *env = opaque;
+
+    if (level) {
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetInfo *reset_info = opaque;
+    CPULM32State *env = &reset_info->cpu->env;
+
+    cpu_reset(CPU(reset_info->cpu));
+
+    /* init defaults */
+    env->pc = reset_info->bootstrap_pc;
+    env->regs[R_R1] = reset_info->cmdline_base;
+    env->regs[R_R2] = reset_info->initrd_base;
+    env->regs[R_R3] = reset_info->initrd_base + reset_info->initrd_size;
+    env->eba = reset_info->flash_base;
+    env->deba = reset_info->flash_base;
+}
+
+static void
+milkymist_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    LM32CPU *cpu;
+    CPULM32State *env;
+    int kernel_size;
+    DriveInfo *dinfo;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *phys_sdram = g_new(MemoryRegion, 1);
+    qemu_irq irq[32], *cpu_irq;
+    int i;
+    char *bios_filename;
+    ResetInfo *reset_info;
+
+    /* memory map */
+    hwaddr flash_base   = 0x00000000;
+    size_t flash_sector_size        = 128 * 1024;
+    size_t flash_size               = 32 * 1024 * 1024;
+    hwaddr sdram_base   = 0x40000000;
+    size_t sdram_size               = 128 * 1024 * 1024;
+
+    hwaddr initrd_base  = sdram_base + 0x1002000;
+    hwaddr cmdline_base = sdram_base + 0x1000000;
+    size_t initrd_max = sdram_size - 0x1002000;
+
+    reset_info = g_malloc0(sizeof(ResetInfo));
+
+    if (cpu_model == NULL) {
+        cpu_model = "lm32-full";
+    }
+    cpu = cpu_lm32_init(cpu_model);
+    env = &cpu->env;
+    reset_info->cpu = cpu;
+
+    cpu_lm32_set_phys_msb_ignore(env, 1);
+
+    memory_region_init_ram(phys_sdram, "milkymist.sdram", sdram_size);
+    vmstate_register_ram_global(phys_sdram);
+    memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* Numonyx JS28F256J3F105 */
+    pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size,
+                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
+                          flash_size / flash_sector_size, 2,
+                          0x00, 0x89, 0x00, 0x1d, 1);
+
+    /* create irq lines */
+    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
+    env->pic_state = lm32_pic_init(*cpu_irq);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(env->pic_state, i);
+    }
+
+    /* load bios rom */
+    if (bios_name == NULL) {
+        bios_name = BIOS_FILENAME;
+    }
+    bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+
+    if (bios_filename) {
+        load_image_targphys(bios_filename, BIOS_OFFSET, BIOS_SIZE);
+    }
+
+    reset_info->bootstrap_pc = BIOS_OFFSET;
+
+    /* if no kernel is given no valid bios rom is a fatal error */
+    if (!kernel_filename && !dinfo && !bios_filename) {
+        fprintf(stderr, "qemu: could not load Milkymist One bios '%s'\n",
+                bios_name);
+        exit(1);
+    }
+
+    milkymist_uart_create(0x60000000, irq[0]);
+    milkymist_sysctl_create(0x60001000, irq[1], irq[2], irq[3],
+            80000000, 0x10014d31, 0x0000041f, 0x00000001);
+    milkymist_hpdmc_create(0x60002000);
+    milkymist_vgafb_create(0x60003000, 0x40000000, 0x0fffffff);
+    milkymist_memcard_create(0x60004000);
+    milkymist_ac97_create(0x60005000, irq[4], irq[5], irq[6], irq[7]);
+    milkymist_pfpu_create(0x60006000, irq[8]);
+    milkymist_tmu2_create(0x60007000, irq[9]);
+    milkymist_minimac2_create(0x60008000, 0x30000000, irq[10], irq[11]);
+    milkymist_softusb_create(0x6000f000, irq[15],
+            0x20000000, 0x1000, 0x20020000, 0x2000);
+
+    /* make sure juart isn't the first chardev */
+    env->juart_state = lm32_juart_init();
+
+    if (kernel_filename) {
+        uint64_t entry;
+
+        /* Boots a kernel elf binary.  */
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+                               1, ELF_MACHINE, 0);
+        reset_info->bootstrap_pc = entry;
+
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename, sdram_base,
+                                              sdram_size);
+            reset_info->bootstrap_pc = sdram_base;
+        }
+
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    if (kernel_cmdline && strlen(kernel_cmdline)) {
+        pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE,
+                kernel_cmdline);
+        reset_info->cmdline_base = (uint32_t)cmdline_base;
+    }
+
+    if (initrd_filename) {
+        size_t initrd_size;
+        initrd_size = load_image_targphys(initrd_filename, initrd_base,
+                initrd_max);
+        reset_info->initrd_base = (uint32_t)initrd_base;
+        reset_info->initrd_size = (uint32_t)initrd_size;
+    }
+
+    qemu_register_reset(main_cpu_reset, reset_info);
+}
+
+static QEMUMachine milkymist_machine = {
+    .name = "milkymist",
+    .desc = "Milkymist One",
+    .init = milkymist_init,
+    .is_default = 0,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void milkymist_machine_init(void)
+{
+    qemu_register_machine(&milkymist_machine);
+}
+
+machine_init(milkymist_machine_init);
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
deleted file mode 100644 (file)
index 2bc06d7..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- *  QEMU models for LatticeMico32 uclinux and evr32 boards.
- *
- *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "sysbus.h"
-#include "hw.h"
-#include "flash.h"
-#include "devices.h"
-#include "boards.h"
-#include "loader.h"
-#include "sysemu/blockdev.h"
-#include "elf.h"
-#include "lm32_hwsetup.h"
-#include "lm32.h"
-#include "exec/address-spaces.h"
-
-typedef struct {
-    LM32CPU *cpu;
-    hwaddr bootstrap_pc;
-    hwaddr flash_base;
-    hwaddr hwsetup_base;
-    hwaddr initrd_base;
-    size_t initrd_size;
-    hwaddr cmdline_base;
-} ResetInfo;
-
-static void cpu_irq_handler(void *opaque, int irq, int level)
-{
-    CPULM32State *env = opaque;
-
-    if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetInfo *reset_info = opaque;
-    CPULM32State *env = &reset_info->cpu->env;
-
-    cpu_reset(CPU(reset_info->cpu));
-
-    /* init defaults */
-    env->pc = (uint32_t)reset_info->bootstrap_pc;
-    env->regs[R_R1] = (uint32_t)reset_info->hwsetup_base;
-    env->regs[R_R2] = (uint32_t)reset_info->cmdline_base;
-    env->regs[R_R3] = (uint32_t)reset_info->initrd_base;
-    env->regs[R_R4] = (uint32_t)(reset_info->initrd_base +
-        reset_info->initrd_size);
-    env->eba = reset_info->flash_base;
-    env->deba = reset_info->flash_base;
-}
-
-static void lm32_evr_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    LM32CPU *cpu;
-    CPULM32State *env;
-    DriveInfo *dinfo;
-    MemoryRegion *address_space_mem =  get_system_memory();
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq *cpu_irq, irq[32];
-    ResetInfo *reset_info;
-    int i;
-
-    /* memory map */
-    hwaddr flash_base  = 0x04000000;
-    size_t flash_sector_size       = 256 * 1024;
-    size_t flash_size              = 32 * 1024 * 1024;
-    hwaddr ram_base    = 0x08000000;
-    size_t ram_size                = 64 * 1024 * 1024;
-    hwaddr timer0_base = 0x80002000;
-    hwaddr uart0_base  = 0x80006000;
-    hwaddr timer1_base = 0x8000a000;
-    int uart0_irq                  = 0;
-    int timer0_irq                 = 1;
-    int timer1_irq                 = 3;
-
-    reset_info = g_malloc0(sizeof(ResetInfo));
-
-    if (cpu_model == NULL) {
-        cpu_model = "lm32-full";
-    }
-    cpu = cpu_lm32_init(cpu_model);
-    env = &cpu->env;
-    reset_info->cpu = cpu;
-
-    reset_info->flash_base = flash_base;
-
-    memory_region_init_ram(phys_ram, "lm32_evr.sdram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    /* Spansion S29NS128P */
-    pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size,
-                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
-                          flash_size / flash_sector_size, 1, 2,
-                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
-
-    /* create irq lines */
-    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
-    env->pic_state = lm32_pic_init(*cpu_irq);
-    for (i = 0; i < 32; i++) {
-        irq[i] = qdev_get_gpio_in(env->pic_state, i);
-    }
-
-    sysbus_create_simple("lm32-uart", uart0_base, irq[uart0_irq]);
-    sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]);
-    sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]);
-
-    /* make sure juart isn't the first chardev */
-    env->juart_state = lm32_juart_init();
-
-    reset_info->bootstrap_pc = flash_base;
-
-    if (kernel_filename) {
-        uint64_t entry;
-        int kernel_size;
-
-        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
-                               1, ELF_MACHINE, 0);
-        reset_info->bootstrap_pc = entry;
-
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename, ram_base,
-                                              ram_size);
-            reset_info->bootstrap_pc = ram_base;
-        }
-
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-    }
-
-    qemu_register_reset(main_cpu_reset, reset_info);
-}
-
-static void lm32_uclinux_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    LM32CPU *cpu;
-    CPULM32State *env;
-    DriveInfo *dinfo;
-    MemoryRegion *address_space_mem =  get_system_memory();
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq *cpu_irq, irq[32];
-    HWSetup *hw;
-    ResetInfo *reset_info;
-    int i;
-
-    /* memory map */
-    hwaddr flash_base   = 0x04000000;
-    size_t flash_sector_size        = 256 * 1024;
-    size_t flash_size               = 32 * 1024 * 1024;
-    hwaddr ram_base     = 0x08000000;
-    size_t ram_size                 = 64 * 1024 * 1024;
-    hwaddr uart0_base   = 0x80000000;
-    hwaddr timer0_base  = 0x80002000;
-    hwaddr timer1_base  = 0x80010000;
-    hwaddr timer2_base  = 0x80012000;
-    int uart0_irq                   = 0;
-    int timer0_irq                  = 1;
-    int timer1_irq                  = 20;
-    int timer2_irq                  = 21;
-    hwaddr hwsetup_base = 0x0bffe000;
-    hwaddr cmdline_base = 0x0bfff000;
-    hwaddr initrd_base  = 0x08400000;
-    size_t initrd_max               = 0x01000000;
-
-    reset_info = g_malloc0(sizeof(ResetInfo));
-
-    if (cpu_model == NULL) {
-        cpu_model = "lm32-full";
-    }
-    cpu = cpu_lm32_init(cpu_model);
-    env = &cpu->env;
-    reset_info->cpu = cpu;
-
-    reset_info->flash_base = flash_base;
-
-    memory_region_init_ram(phys_ram, "lm32_uclinux.sdram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    /* Spansion S29NS128P */
-    pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,
-                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
-                          flash_size / flash_sector_size, 1, 2,
-                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
-
-    /* create irq lines */
-    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
-    env->pic_state = lm32_pic_init(*cpu_irq);
-    for (i = 0; i < 32; i++) {
-        irq[i] = qdev_get_gpio_in(env->pic_state, i);
-    }
-
-    sysbus_create_simple("lm32-uart", uart0_base, irq[uart0_irq]);
-    sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]);
-    sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]);
-    sysbus_create_simple("lm32-timer", timer2_base, irq[timer2_irq]);
-
-    /* make sure juart isn't the first chardev */
-    env->juart_state = lm32_juart_init();
-
-    reset_info->bootstrap_pc = flash_base;
-
-    if (kernel_filename) {
-        uint64_t entry;
-        int kernel_size;
-
-        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
-                               1, ELF_MACHINE, 0);
-        reset_info->bootstrap_pc = entry;
-
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename, ram_base,
-                                              ram_size);
-            reset_info->bootstrap_pc = ram_base;
-        }
-
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-    }
-
-    /* generate a rom with the hardware description */
-    hw = hwsetup_init();
-    hwsetup_add_cpu(hw, "LM32", 75000000);
-    hwsetup_add_flash(hw, "flash", flash_base, flash_size);
-    hwsetup_add_ddr_sdram(hw, "ddr_sdram", ram_base, ram_size);
-    hwsetup_add_timer(hw, "timer0", timer0_base, timer0_irq);
-    hwsetup_add_timer(hw, "timer1_dev_only", timer1_base, timer1_irq);
-    hwsetup_add_timer(hw, "timer2_dev_only", timer2_base, timer2_irq);
-    hwsetup_add_uart(hw, "uart", uart0_base, uart0_irq);
-    hwsetup_add_trailer(hw);
-    hwsetup_create_rom(hw, hwsetup_base);
-    hwsetup_free(hw);
-
-    reset_info->hwsetup_base = hwsetup_base;
-
-    if (kernel_cmdline && strlen(kernel_cmdline)) {
-        pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE,
-                kernel_cmdline);
-        reset_info->cmdline_base = cmdline_base;
-    }
-
-    if (initrd_filename) {
-        size_t initrd_size;
-        initrd_size = load_image_targphys(initrd_filename, initrd_base,
-                initrd_max);
-        reset_info->initrd_base = initrd_base;
-        reset_info->initrd_size = initrd_size;
-    }
-
-    qemu_register_reset(main_cpu_reset, reset_info);
-}
-
-static QEMUMachine lm32_evr_machine = {
-    .name = "lm32-evr",
-    .desc = "LatticeMico32 EVR32 eval system",
-    .init = lm32_evr_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine lm32_uclinux_machine = {
-    .name = "lm32-uclinux",
-    .desc = "lm32 platform for uClinux and u-boot by Theobroma Systems",
-    .init = lm32_uclinux_init,
-    .is_default = 0,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void lm32_machine_init(void)
-{
-    qemu_register_machine(&lm32_uclinux_machine);
-    qemu_register_machine(&lm32_evr_machine);
-}
-
-machine_init(lm32_machine_init);
index 853e9abc7bd62e17fba54a2eb060b0e260231ed7..3449bd8dfc10b6506c71e553b8665f68c58a1c80 100644 (file)
@@ -26,7 +26,7 @@
 #define QEMU_HW_LM32_HWSETUP_H
 
 #include "qemu-common.h"
-#include "loader.h"
+#include "hw/loader.h"
 
 typedef struct {
     void *data;
index 8c82c85f6dc253a276b5615d4f4e3a43fa6cd6bc..472e9c25fd808748726a89295accf4c290d9f688 100644 (file)
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "char/char.h"
 
-#include "lm32_juart.h"
+#include "hw/lm32_juart.h"
 
 enum {
     LM32_JUART_MIN_SAVE_VERSION = 0,
index 42f298ad5103e4279c9bfbcf0cd43edd7b1894ea..d17c310d5c14e7fd77666ca5b0d83588d0550cbc 100644 (file)
 
 #include <assert.h>
 
-#include "hw.h"
-#include "pc.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
 #include "monitor/monitor.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
-#include "lm32_pic.h"
+#include "hw/lm32_pic.h"
 
 struct LM32PicState {
     SysBusDevice busdev;
index 187ef6d0d6f689b8403ae793bcac8add3075bf04..33a3b80ce779410a323dd33b8effa5c50e7e5a9d 100644 (file)
@@ -28,8 +28,8 @@
  * the test is passed or any non-zero value to it if the test is failed.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/log.h"
 #include "qemu/error-report.h"
index db527e9dc6f503b523598fb601dea7c2bd9201ec..e06fac708259e9ae2ab8eb1b1005a51fe327c507 100644 (file)
  *   http://www.latticesemi.com/documents/mico32timer.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "qemu/error-report.h"
 
 #define DEFAULT_FREQUENCY (50*1000000)
index 9c89cca49b5ca06106f1db94fbab55c89ba18454..02f6f89174392f3187bb9b8a428a49fa671c64fe 100644 (file)
@@ -22,8 +22,8 @@
  */
 
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "char/char.h"
 #include "qemu/error-report.h"
index b3c2d5f25d10bb1dc220fe5dc5848d417f244ba7..67335cba615b3af24de97bab7c303005d2e51cce 100644 (file)
@@ -13,9 +13,9 @@
  * It supports only one playback voice and no record voice.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "audio/audio.h"
-#include "lm4549.h"
+#include "hw/lm4549.h"
 
 #if 0
 #define LM4549_DEBUG  1
index 94b8ae06d8e0a37574f03b005f594fefc3d14850..a064dfd17262ac7c5911de48d70c9a74f3f81046 100644 (file)
@@ -18,8 +18,8 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "i2c.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
 #include "qemu/timer.h"
 #include "ui/console.h"
 
index bd2b52d14e7ca66dc77b17f1307eb76c910b4c60..6ce66fb5bb10d4d681a82d370c3307e85d5983ce 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "disas/disas.h"
 #include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
-#include "uboot_image.h"
-#include "loader.h"
-#include "fw_cfg.h"
+#include "hw/uboot_image.h"
+#include "hw/loader.h"
+#include "hw/fw_cfg.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
 
@@ -260,7 +260,7 @@ static void *load_at(int fd, int offset, int size)
 #define elf_word        uint32_t
 #define elf_sword        int32_t
 #define bswapSZs       bswap32s
-#include "elf_ops.h"
+#include "hw/elf_ops.h"
 
 #undef elfhdr
 #undef elf_phdr
@@ -280,7 +280,7 @@ static void *load_at(int fd, int offset, int size)
 #define elf_sword        int64_t
 #define bswapSZs       bswap64s
 #define SZ             64
-#include "elf_ops.h"
+#include "hw/elf_ops.h"
 
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
 int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
index eceb0524201d1a042cb8ccf5d73d1bb4aeb5db9a..0ca0a59ef7c460be5227cfa3ffb11c891eb61080 100644 (file)
  * THE SOFTWARE.
  */
 #include "qemu-common.h"
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/range.h"
-#include "isa.h"
-#include "sysbus.h"
-#include "pc.h"
-#include "apm.h"
-#include "ioapic.h"
-#include "pci/pci.h"
-#include "pci/pcie_host.h"
-#include "pci/pci_bridge.h"
-#include "ich9.h"
-#include "acpi.h"
-#include "acpi_ich9.h"
-#include "pam.h"
-#include "pci/pci_bus.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
+#include "hw/pc.h"
+#include "hw/apm.h"
+#include "hw/ioapic.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/ich9.h"
+#include "hw/acpi.h"
+#include "hw/acpi_ich9.h"
+#include "hw/pam.h"
+#include "hw/pci/pci_bus.h"
 #include "exec/address-spaces.h"
 #include "sysemu/sysemu.h"
 
index 860df328e5945611ba8c2ffa9f222dbd21f506be..5a8bf4d0e9b33a46d860502effec9ad5b934f533 100644 (file)
@@ -12,9 +12,9 @@
 
 #include <assert.h>
 
-#include "hw.h"
-#include "pci/pci.h"
-#include "scsi.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/scsi.h"
 #include "sysemu/dma.h"
 
 //#define DEBUG_LSI
index 1372d06409c3578337e538c0bec9cfcaba801aed..55e9d0d37a1379fd092bf5d56f8dc57368c87d2a 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/blockdev.h"
-#include "ssi.h"
-#include "devices.h"
+#include "hw/ssi.h"
+#include "hw/devices.h"
 
 #ifdef M25P80_ERR_DEBUG
 #define DB_PRINT(...) do { \
index 427d95b5a600caab6882b29ae35ebc66d2d2d1cd..39a9d808cd9e18c072c66a3af9ada6d7f18b2322 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "nvram.h"
+#include "hw/hw.h"
+#include "hw/nvram.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
-#include "sysbus.h"
-#include "isa.h"
+#include "hw/sysbus.h"
+#include "hw/isa.h"
 #include "exec/address-spaces.h"
 
 //#define DEBUG_NVRAM
index 93b6d25baf9a6111f848929167caf4e63e7f1e5e..ede32a7c4ef00bd1a0a0a0ae416f640f25270cf5 100644 (file)
@@ -1,4 +1,8 @@
-obj-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
-obj-y += dummy_m68k.o
+obj-y = mcf_uart.o mcf_fec.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += an5206.o mcf5208.o
+obj-y += dummy_m68k.o
+
+obj-y += mcf5206.o mcf_intc.o
diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c
new file mode 100644 (file)
index 0000000..7c21c66
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Arnewsh 5206 ColdFire system emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+
+#include "hw/hw.h"
+#include "hw/mcf.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+
+#define KERNEL_LOAD_ADDR 0x10000
+#define AN5206_MBAR_ADDR 0x10000000
+#define AN5206_RAMBAR_ADDR 0x20000000
+
+/* Board init.  */
+
+static void an5206_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    M68kCPU *cpu;
+    CPUM68KState *env;
+    int kernel_size;
+    uint64_t elf_entry;
+    hwaddr entry;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+
+    if (!cpu_model) {
+        cpu_model = "m5206";
+    }
+    cpu = cpu_m68k_init(cpu_model);
+    if (!cpu) {
+        hw_error("Unable to find m68k CPU definition\n");
+    }
+    env = &cpu->env;
+
+    /* Initialize CPU registers.  */
+    env->vbr = 0;
+    /* TODO: allow changing MBAR and RAMBAR.  */
+    env->mbar = AN5206_MBAR_ADDR | 1;
+    env->rambar0 = AN5206_RAMBAR_ADDR | 1;
+
+    /* DRAM at address zero */
+    memory_region_init_ram(ram, "an5206.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, 0, ram);
+
+    /* Internal SRAM.  */
+    memory_region_init_ram(sram, "an5206.sram", 512);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram);
+
+    mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, cpu);
+
+    /* Load kernel.  */
+    if (!kernel_filename) {
+        fprintf(stderr, "Kernel image must be specified\n");
+        exit(1);
+    }
+
+    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                           NULL, NULL, 1, ELF_MACHINE, 0);
+    entry = elf_entry;
+    if (kernel_size < 0) {
+        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+    }
+    if (kernel_size < 0) {
+        kernel_size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
+                                          ram_size - KERNEL_LOAD_ADDR);
+        entry = KERNEL_LOAD_ADDR;
+    }
+    if (kernel_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
+        exit(1);
+    }
+
+    env->pc = entry;
+}
+
+static QEMUMachine an5206_machine = {
+    .name = "an5206",
+    .desc = "Arnewsh 5206",
+    .init = an5206_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void an5206_machine_init(void)
+{
+    qemu_register_machine(&an5206_machine);
+}
+
+machine_init(an5206_machine_init);
diff --git a/hw/m68k/dummy_m68k.c b/hw/m68k/dummy_m68k.c
new file mode 100644 (file)
index 0000000..544d56b
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Dummy board with just RAM and CPU for use as an ISS.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+
+#define KERNEL_LOAD_ADDR 0x10000
+
+/* Board init.  */
+
+static void dummy_m68k_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    CPUM68KState *env;
+    MemoryRegion *address_space_mem =  get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    int kernel_size;
+    uint64_t elf_entry;
+    hwaddr entry;
+
+    if (!cpu_model)
+        cpu_model = "cfv4e";
+    env = cpu_init(cpu_model);
+    if (!env) {
+        fprintf(stderr, "Unable to find m68k CPU definition\n");
+        exit(1);
+    }
+
+    /* Initialize CPU registers.  */
+    env->vbr = 0;
+
+    /* RAM at address zero */
+    memory_region_init_ram(ram, "dummy_m68k.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, 0, ram);
+
+    /* Load kernel.  */
+    if (kernel_filename) {
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                               NULL, NULL, 1, ELF_MACHINE, 0);
+        entry = elf_entry;
+        if (kernel_size < 0) {
+            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+        }
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename,
+                                              KERNEL_LOAD_ADDR,
+                                              ram_size - KERNEL_LOAD_ADDR);
+            entry = KERNEL_LOAD_ADDR;
+        }
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    } else {
+        entry = 0;
+    }
+    env->pc = entry;
+}
+
+static QEMUMachine dummy_m68k_machine = {
+    .name = "dummy",
+    .desc = "Dummy board",
+    .init = dummy_m68k_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void dummy_m68k_machine_init(void)
+{
+    qemu_register_machine(&dummy_m68k_machine);
+}
+
+machine_init(dummy_m68k_machine_init);
diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c
new file mode 100644 (file)
index 0000000..58cd8d4
--- /dev/null
@@ -0,0 +1,548 @@
+/*
+ * Motorola ColdFire MCF5206 SoC embedded peripheral emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+#include "hw/hw.h"
+#include "hw/mcf.h"
+#include "qemu/timer.h"
+#include "hw/ptimer.h"
+#include "sysemu/sysemu.h"
+#include "exec/address-spaces.h"
+
+/* General purpose timer module.  */
+typedef struct {
+    uint16_t tmr;
+    uint16_t trr;
+    uint16_t tcr;
+    uint16_t ter;
+    ptimer_state *timer;
+    qemu_irq irq;
+    int irq_state;
+} m5206_timer_state;
+
+#define TMR_RST 0x01
+#define TMR_CLK 0x06
+#define TMR_FRR 0x08
+#define TMR_ORI 0x10
+#define TMR_OM  0x20
+#define TMR_CE  0xc0
+
+#define TER_CAP 0x01
+#define TER_REF 0x02
+
+static void m5206_timer_update(m5206_timer_state *s)
+{
+    if ((s->tmr & TMR_ORI) != 0 && (s->ter & TER_REF))
+        qemu_irq_raise(s->irq);
+    else
+        qemu_irq_lower(s->irq);
+}
+
+static void m5206_timer_reset(m5206_timer_state *s)
+{
+    s->tmr = 0;
+    s->trr = 0;
+}
+
+static void m5206_timer_recalibrate(m5206_timer_state *s)
+{
+    int prescale;
+    int mode;
+
+    ptimer_stop(s->timer);
+
+    if ((s->tmr & TMR_RST) == 0)
+        return;
+
+    prescale = (s->tmr >> 8) + 1;
+    mode = (s->tmr >> 1) & 3;
+    if (mode == 2)
+        prescale *= 16;
+
+    if (mode == 3 || mode == 0)
+        hw_error("m5206_timer: mode %d not implemented\n", mode);
+    if ((s->tmr & TMR_FRR) == 0)
+        hw_error("m5206_timer: free running mode not implemented\n");
+
+    /* Assume 66MHz system clock.  */
+    ptimer_set_freq(s->timer, 66000000 / prescale);
+
+    ptimer_set_limit(s->timer, s->trr, 0);
+
+    ptimer_run(s->timer, 0);
+}
+
+static void m5206_timer_trigger(void *opaque)
+{
+    m5206_timer_state *s = (m5206_timer_state *)opaque;
+    s->ter |= TER_REF;
+    m5206_timer_update(s);
+}
+
+static uint32_t m5206_timer_read(m5206_timer_state *s, uint32_t addr)
+{
+    switch (addr) {
+    case 0:
+        return s->tmr;
+    case 4:
+        return s->trr;
+    case 8:
+        return s->tcr;
+    case 0xc:
+        return s->trr - ptimer_get_count(s->timer);
+    case 0x11:
+        return s->ter;
+    default:
+        return 0;
+    }
+}
+
+static void m5206_timer_write(m5206_timer_state *s, uint32_t addr, uint32_t val)
+{
+    switch (addr) {
+    case 0:
+        if ((s->tmr & TMR_RST) != 0 && (val & TMR_RST) == 0) {
+            m5206_timer_reset(s);
+        }
+        s->tmr = val;
+        m5206_timer_recalibrate(s);
+        break;
+    case 4:
+        s->trr = val;
+        m5206_timer_recalibrate(s);
+        break;
+    case 8:
+        s->tcr = val;
+        break;
+    case 0xc:
+        ptimer_set_count(s->timer, val);
+        break;
+    case 0x11:
+        s->ter &= ~val;
+        break;
+    default:
+        break;
+    }
+    m5206_timer_update(s);
+}
+
+static m5206_timer_state *m5206_timer_init(qemu_irq irq)
+{
+    m5206_timer_state *s;
+    QEMUBH *bh;
+
+    s = (m5206_timer_state *)g_malloc0(sizeof(m5206_timer_state));
+    bh = qemu_bh_new(m5206_timer_trigger, s);
+    s->timer = ptimer_init(bh);
+    s->irq = irq;
+    m5206_timer_reset(s);
+    return s;
+}
+
+/* System Integration Module.  */
+
+typedef struct {
+    M68kCPU *cpu;
+    MemoryRegion iomem;
+    m5206_timer_state *timer[2];
+    void *uart[2];
+    uint8_t scr;
+    uint8_t icr[14];
+    uint16_t imr; /* 1 == interrupt is masked.  */
+    uint16_t ipr;
+    uint8_t rsr;
+    uint8_t swivr;
+    uint8_t par;
+    /* Include the UART vector registers here.  */
+    uint8_t uivr[2];
+} m5206_mbar_state;
+
+/* Interrupt controller.  */
+
+static int m5206_find_pending_irq(m5206_mbar_state *s)
+{
+    int level;
+    int vector;
+    uint16_t active;
+    int i;
+
+    level = 0;
+    vector = 0;
+    active = s->ipr & ~s->imr;
+    if (!active)
+        return 0;
+
+    for (i = 1; i < 14; i++) {
+        if (active & (1 << i)) {
+            if ((s->icr[i] & 0x1f) > level) {
+                level = s->icr[i] & 0x1f;
+                vector = i;
+            }
+        }
+    }
+
+    if (level < 4)
+        vector = 0;
+
+    return vector;
+}
+
+static void m5206_mbar_update(m5206_mbar_state *s)
+{
+    int irq;
+    int vector;
+    int level;
+
+    irq = m5206_find_pending_irq(s);
+    if (irq) {
+        int tmp;
+        tmp = s->icr[irq];
+        level = (tmp >> 2) & 7;
+        if (tmp & 0x80) {
+            /* Autovector.  */
+            vector = 24 + level;
+        } else {
+            switch (irq) {
+            case 8: /* SWT */
+                vector = s->swivr;
+                break;
+            case 12: /* UART1 */
+                vector = s->uivr[0];
+                break;
+            case 13: /* UART2 */
+                vector = s->uivr[1];
+                break;
+            default:
+                /* Unknown vector.  */
+                fprintf(stderr, "Unhandled vector for IRQ %d\n", irq);
+                vector = 0xf;
+                break;
+            }
+        }
+    } else {
+        level = 0;
+        vector = 0;
+    }
+    m68k_set_irq_level(s->cpu, level, vector);
+}
+
+static void m5206_mbar_set_irq(void *opaque, int irq, int level)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    if (level) {
+        s->ipr |= 1 << irq;
+    } else {
+        s->ipr &= ~(1 << irq);
+    }
+    m5206_mbar_update(s);
+}
+
+/* System Integration Module.  */
+
+static void m5206_mbar_reset(m5206_mbar_state *s)
+{
+    s->scr = 0xc0;
+    s->icr[1] = 0x04;
+    s->icr[2] = 0x08;
+    s->icr[3] = 0x0c;
+    s->icr[4] = 0x10;
+    s->icr[5] = 0x14;
+    s->icr[6] = 0x18;
+    s->icr[7] = 0x1c;
+    s->icr[8] = 0x1c;
+    s->icr[9] = 0x80;
+    s->icr[10] = 0x80;
+    s->icr[11] = 0x80;
+    s->icr[12] = 0x00;
+    s->icr[13] = 0x00;
+    s->imr = 0x3ffe;
+    s->rsr = 0x80;
+    s->swivr = 0x0f;
+    s->par = 0;
+}
+
+static uint64_t m5206_mbar_read(m5206_mbar_state *s,
+                                uint64_t offset, unsigned size)
+{
+    if (offset >= 0x100 && offset < 0x120) {
+        return m5206_timer_read(s->timer[0], offset - 0x100);
+    } else if (offset >= 0x120 && offset < 0x140) {
+        return m5206_timer_read(s->timer[1], offset - 0x120);
+    } else if (offset >= 0x140 && offset < 0x160) {
+        return mcf_uart_read(s->uart[0], offset - 0x140, size);
+    } else if (offset >= 0x180 && offset < 0x1a0) {
+        return mcf_uart_read(s->uart[1], offset - 0x180, size);
+    }
+    switch (offset) {
+    case 0x03: return s->scr;
+    case 0x14 ... 0x20: return s->icr[offset - 0x13];
+    case 0x36: return s->imr;
+    case 0x3a: return s->ipr;
+    case 0x40: return s->rsr;
+    case 0x41: return 0;
+    case 0x42: return s->swivr;
+    case 0x50:
+        /* DRAM mask register.  */
+        /* FIXME: currently hardcoded to 128Mb.  */
+        {
+            uint32_t mask = ~0;
+            while (mask > ram_size)
+                mask >>= 1;
+            return mask & 0x0ffe0000;
+        }
+    case 0x5c: return 1; /* DRAM bank 1 empty.  */
+    case 0xcb: return s->par;
+    case 0x170: return s->uivr[0];
+    case 0x1b0: return s->uivr[1];
+    }
+    hw_error("Bad MBAR read offset 0x%x", (int)offset);
+    return 0;
+}
+
+static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset,
+                             uint64_t value, unsigned size)
+{
+    if (offset >= 0x100 && offset < 0x120) {
+        m5206_timer_write(s->timer[0], offset - 0x100, value);
+        return;
+    } else if (offset >= 0x120 && offset < 0x140) {
+        m5206_timer_write(s->timer[1], offset - 0x120, value);
+        return;
+    } else if (offset >= 0x140 && offset < 0x160) {
+        mcf_uart_write(s->uart[0], offset - 0x140, value, size);
+        return;
+    } else if (offset >= 0x180 && offset < 0x1a0) {
+        mcf_uart_write(s->uart[1], offset - 0x180, value, size);
+        return;
+    }
+    switch (offset) {
+    case 0x03:
+        s->scr = value;
+        break;
+    case 0x14 ... 0x20:
+        s->icr[offset - 0x13] = value;
+        m5206_mbar_update(s);
+        break;
+    case 0x36:
+        s->imr = value;
+        m5206_mbar_update(s);
+        break;
+    case 0x40:
+        s->rsr &= ~value;
+        break;
+    case 0x41:
+        /* TODO: implement watchdog.  */
+        break;
+    case 0x42:
+        s->swivr = value;
+        break;
+    case 0xcb:
+        s->par = value;
+        break;
+    case 0x170:
+        s->uivr[0] = value;
+        break;
+    case 0x178: case 0x17c: case 0x1c8: case 0x1bc:
+        /* Not implemented: UART Output port bits.  */
+        break;
+    case 0x1b0:
+        s->uivr[1] = value;
+        break;
+    default:
+        hw_error("Bad MBAR write offset 0x%x", (int)offset);
+        break;
+    }
+}
+
+/* Internal peripherals use a variety of register widths.
+   This lookup table allows a single routine to handle all of them.  */
+static const uint8_t m5206_mbar_width[] =
+{
+  /* 000-040 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  2, 2, 2, 2,
+  /* 040-080 */ 1, 2, 2, 2,  4, 1, 2, 4,  1, 2, 4, 2,  2, 4, 2, 2,
+  /* 080-0c0 */ 4, 2, 2, 4,  2, 2, 4, 2,  2, 4, 2, 2,  4, 2, 2, 4,
+  /* 0c0-100 */ 2, 2, 1, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,
+  /* 100-140 */ 2, 2, 2, 2,  1, 0, 0, 0,  2, 2, 2, 2,  1, 0, 0, 0,
+  /* 140-180 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+  /* 180-1c0 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+  /* 1c0-200 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+};
+
+static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset);
+static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset);
+
+static uint32_t m5206_mbar_readb(void *opaque, hwaddr offset)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR read offset 0x%x", (int)offset);
+    }
+    if (m5206_mbar_width[offset >> 2] > 1) {
+        uint16_t val;
+        val = m5206_mbar_readw(opaque, offset & ~1);
+        if ((offset & 1) == 0) {
+            val >>= 8;
+        }
+        return val & 0xff;
+    }
+    return m5206_mbar_read(s, offset, 1);
+}
+
+static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    int width;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR read offset 0x%x", (int)offset);
+    }
+    width = m5206_mbar_width[offset >> 2];
+    if (width > 2) {
+        uint32_t val;
+        val = m5206_mbar_readl(opaque, offset & ~3);
+        if ((offset & 3) == 0)
+            val >>= 16;
+        return val & 0xffff;
+    } else if (width < 2) {
+        uint16_t val;
+        val = m5206_mbar_readb(opaque, offset) << 8;
+        val |= m5206_mbar_readb(opaque, offset + 1);
+        return val;
+    }
+    return m5206_mbar_read(s, offset, 2);
+}
+
+static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    int width;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR read offset 0x%x", (int)offset);
+    }
+    width = m5206_mbar_width[offset >> 2];
+    if (width < 4) {
+        uint32_t val;
+        val = m5206_mbar_readw(opaque, offset) << 16;
+        val |= m5206_mbar_readw(opaque, offset + 2);
+        return val;
+    }
+    return m5206_mbar_read(s, offset, 4);
+}
+
+static void m5206_mbar_writew(void *opaque, hwaddr offset,
+                              uint32_t value);
+static void m5206_mbar_writel(void *opaque, hwaddr offset,
+                              uint32_t value);
+
+static void m5206_mbar_writeb(void *opaque, hwaddr offset,
+                              uint32_t value)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    int width;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR write offset 0x%x", (int)offset);
+    }
+    width = m5206_mbar_width[offset >> 2];
+    if (width > 1) {
+        uint32_t tmp;
+        tmp = m5206_mbar_readw(opaque, offset & ~1);
+        if (offset & 1) {
+            tmp = (tmp & 0xff00) | value;
+        } else {
+            tmp = (tmp & 0x00ff) | (value << 8);
+        }
+        m5206_mbar_writew(opaque, offset & ~1, tmp);
+        return;
+    }
+    m5206_mbar_write(s, offset, value, 1);
+}
+
+static void m5206_mbar_writew(void *opaque, hwaddr offset,
+                              uint32_t value)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    int width;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR write offset 0x%x", (int)offset);
+    }
+    width = m5206_mbar_width[offset >> 2];
+    if (width > 2) {
+        uint32_t tmp;
+        tmp = m5206_mbar_readl(opaque, offset & ~3);
+        if (offset & 3) {
+            tmp = (tmp & 0xffff0000) | value;
+        } else {
+            tmp = (tmp & 0x0000ffff) | (value << 16);
+        }
+        m5206_mbar_writel(opaque, offset & ~3, tmp);
+        return;
+    } else if (width < 2) {
+        m5206_mbar_writeb(opaque, offset, value >> 8);
+        m5206_mbar_writeb(opaque, offset + 1, value & 0xff);
+        return;
+    }
+    m5206_mbar_write(s, offset, value, 2);
+}
+
+static void m5206_mbar_writel(void *opaque, hwaddr offset,
+                              uint32_t value)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    int width;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR write offset 0x%x", (int)offset);
+    }
+    width = m5206_mbar_width[offset >> 2];
+    if (width < 4) {
+        m5206_mbar_writew(opaque, offset, value >> 16);
+        m5206_mbar_writew(opaque, offset + 2, value & 0xffff);
+        return;
+    }
+    m5206_mbar_write(s, offset, value, 4);
+}
+
+static const MemoryRegionOps m5206_mbar_ops = {
+    .old_mmio = {
+        .read = {
+            m5206_mbar_readb,
+            m5206_mbar_readw,
+            m5206_mbar_readl,
+        },
+        .write = {
+            m5206_mbar_writeb,
+            m5206_mbar_writew,
+            m5206_mbar_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, M68kCPU *cpu)
+{
+    m5206_mbar_state *s;
+    qemu_irq *pic;
+
+    s = (m5206_mbar_state *)g_malloc0(sizeof(m5206_mbar_state));
+
+    memory_region_init_io(&s->iomem, &m5206_mbar_ops, s,
+                          "mbar", 0x00001000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
+
+    pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14);
+    s->timer[0] = m5206_timer_init(pic[9]);
+    s->timer[1] = m5206_timer_init(pic[10]);
+    s->uart[0] = mcf_uart_init(pic[12], serial_hds[0]);
+    s->uart[1] = mcf_uart_init(pic[13], serial_hds[1]);
+    s->cpu = cpu;
+
+    m5206_mbar_reset(s);
+    return pic;
+}
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
new file mode 100644 (file)
index 0000000..748bf56
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Motorola ColdFire MCF5208 SoC emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+#include "hw/hw.h"
+#include "hw/mcf.h"
+#include "qemu/timer.h"
+#include "hw/ptimer.h"
+#include "sysemu/sysemu.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+
+#define SYS_FREQ 66000000
+
+#define PCSR_EN         0x0001
+#define PCSR_RLD        0x0002
+#define PCSR_PIF        0x0004
+#define PCSR_PIE        0x0008
+#define PCSR_OVW        0x0010
+#define PCSR_DBG        0x0020
+#define PCSR_DOZE       0x0040
+#define PCSR_PRE_SHIFT  8
+#define PCSR_PRE_MASK   0x0f00
+
+typedef struct {
+    MemoryRegion iomem;
+    qemu_irq irq;
+    ptimer_state *timer;
+    uint16_t pcsr;
+    uint16_t pmr;
+    uint16_t pcntr;
+} m5208_timer_state;
+
+static void m5208_timer_update(m5208_timer_state *s)
+{
+    if ((s->pcsr & (PCSR_PIE | PCSR_PIF)) == (PCSR_PIE | PCSR_PIF))
+        qemu_irq_raise(s->irq);
+    else
+        qemu_irq_lower(s->irq);
+}
+
+static void m5208_timer_write(void *opaque, hwaddr offset,
+                              uint64_t value, unsigned size)
+{
+    m5208_timer_state *s = (m5208_timer_state *)opaque;
+    int prescale;
+    int limit;
+    switch (offset) {
+    case 0:
+        /* The PIF bit is set-to-clear.  */
+        if (value & PCSR_PIF) {
+            s->pcsr &= ~PCSR_PIF;
+            value &= ~PCSR_PIF;
+        }
+        /* Avoid frobbing the timer if we're just twiddling IRQ bits. */
+        if (((s->pcsr ^ value) & ~PCSR_PIE) == 0) {
+            s->pcsr = value;
+            m5208_timer_update(s);
+            return;
+        }
+
+        if (s->pcsr & PCSR_EN)
+            ptimer_stop(s->timer);
+
+        s->pcsr = value;
+
+        prescale = 1 << ((s->pcsr & PCSR_PRE_MASK) >> PCSR_PRE_SHIFT);
+        ptimer_set_freq(s->timer, (SYS_FREQ / 2) / prescale);
+        if (s->pcsr & PCSR_RLD)
+            limit = s->pmr;
+        else
+            limit = 0xffff;
+        ptimer_set_limit(s->timer, limit, 0);
+
+        if (s->pcsr & PCSR_EN)
+            ptimer_run(s->timer, 0);
+        break;
+    case 2:
+        s->pmr = value;
+        s->pcsr &= ~PCSR_PIF;
+        if ((s->pcsr & PCSR_RLD) == 0) {
+            if (s->pcsr & PCSR_OVW)
+                ptimer_set_count(s->timer, value);
+        } else {
+            ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW);
+        }
+        break;
+    case 4:
+        break;
+    default:
+        hw_error("m5208_timer_write: Bad offset 0x%x\n", (int)offset);
+        break;
+    }
+    m5208_timer_update(s);
+}
+
+static void m5208_timer_trigger(void *opaque)
+{
+    m5208_timer_state *s = (m5208_timer_state *)opaque;
+    s->pcsr |= PCSR_PIF;
+    m5208_timer_update(s);
+}
+
+static uint64_t m5208_timer_read(void *opaque, hwaddr addr,
+                                 unsigned size)
+{
+    m5208_timer_state *s = (m5208_timer_state *)opaque;
+    switch (addr) {
+    case 0:
+        return s->pcsr;
+    case 2:
+        return s->pmr;
+    case 4:
+        return ptimer_get_count(s->timer);
+    default:
+        hw_error("m5208_timer_read: Bad offset 0x%x\n", (int)addr);
+        return 0;
+    }
+}
+
+static const MemoryRegionOps m5208_timer_ops = {
+    .read = m5208_timer_read,
+    .write = m5208_timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static uint64_t m5208_sys_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    switch (addr) {
+    case 0x110: /* SDCS0 */
+        {
+            int n;
+            for (n = 0; n < 32; n++) {
+                if (ram_size < (2u << n))
+                    break;
+            }
+            return (n - 1)  | 0x40000000;
+        }
+    case 0x114: /* SDCS1 */
+        return 0;
+
+    default:
+        hw_error("m5208_sys_read: Bad offset 0x%x\n", (int)addr);
+        return 0;
+    }
+}
+
+static void m5208_sys_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr);
+}
+
+static const MemoryRegionOps m5208_sys_ops = {
+    .read = m5208_sys_read,
+    .write = m5208_sys_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
+{
+    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+    m5208_timer_state *s;
+    QEMUBH *bh;
+    int i;
+
+    /* SDRAMC.  */
+    memory_region_init_io(iomem, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000);
+    memory_region_add_subregion(address_space, 0xfc0a8000, iomem);
+    /* Timers.  */
+    for (i = 0; i < 2; i++) {
+        s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state));
+        bh = qemu_bh_new(m5208_timer_trigger, s);
+        s->timer = ptimer_init(bh);
+        memory_region_init_io(&s->iomem, &m5208_timer_ops, s,
+                              "m5208-timer", 0x00004000);
+        memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
+                                    &s->iomem);
+        s->irq = pic[4 + i];
+    }
+}
+
+static void mcf5208evb_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    M68kCPU *cpu;
+    CPUM68KState *env;
+    int kernel_size;
+    uint64_t elf_entry;
+    hwaddr entry;
+    qemu_irq *pic;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+
+    if (!cpu_model) {
+        cpu_model = "m5208";
+    }
+    cpu = cpu_m68k_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find m68k CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    /* Initialize CPU registers.  */
+    env->vbr = 0;
+    /* TODO: Configure BARs.  */
+
+    /* DRAM at 0x40000000 */
+    memory_region_init_ram(ram, "mcf5208.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, 0x40000000, ram);
+
+    /* Internal SRAM.  */
+    memory_region_init_ram(sram, "mcf5208.sram", 16384);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(address_space_mem, 0x80000000, sram);
+
+    /* Internal peripherals.  */
+    pic = mcf_intc_init(address_space_mem, 0xfc048000, cpu);
+
+    mcf_uart_mm_init(address_space_mem, 0xfc060000, pic[26], serial_hds[0]);
+    mcf_uart_mm_init(address_space_mem, 0xfc064000, pic[27], serial_hds[1]);
+    mcf_uart_mm_init(address_space_mem, 0xfc068000, pic[28], serial_hds[2]);
+
+    mcf5208_sys_init(address_space_mem, pic);
+
+    if (nb_nics > 1) {
+        fprintf(stderr, "Too many NICs\n");
+        exit(1);
+    }
+    if (nd_table[0].used)
+        mcf_fec_init(address_space_mem, &nd_table[0],
+                     0xfc030000, pic + 36);
+
+    /*  0xfc000000 SCM.  */
+    /*  0xfc004000 XBS.  */
+    /*  0xfc008000 FlexBus CS.  */
+    /* 0xfc030000 FEC.  */
+    /*  0xfc040000 SCM + Power management.  */
+    /*  0xfc044000 eDMA.  */
+    /* 0xfc048000 INTC.  */
+    /*  0xfc058000 I2C.  */
+    /*  0xfc05c000 QSPI.  */
+    /* 0xfc060000 UART0.  */
+    /* 0xfc064000 UART0.  */
+    /* 0xfc068000 UART0.  */
+    /*  0xfc070000 DMA timers.  */
+    /* 0xfc080000 PIT0.  */
+    /* 0xfc084000 PIT1.  */
+    /*  0xfc088000 EPORT.  */
+    /*  0xfc08c000 Watchdog.  */
+    /*  0xfc090000 clock module.  */
+    /*  0xfc0a0000 CCM + reset.  */
+    /*  0xfc0a4000 GPIO.  */
+    /* 0xfc0a8000 SDRAM controller.  */
+
+    /* Load kernel.  */
+    if (!kernel_filename) {
+        fprintf(stderr, "Kernel image must be specified\n");
+        exit(1);
+    }
+
+    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                           NULL, NULL, 1, ELF_MACHINE, 0);
+    entry = elf_entry;
+    if (kernel_size < 0) {
+        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+    }
+    if (kernel_size < 0) {
+        kernel_size = load_image_targphys(kernel_filename, 0x40000000,
+                                          ram_size);
+        entry = 0x40000000;
+    }
+    if (kernel_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
+        exit(1);
+    }
+
+    env->pc = entry;
+}
+
+static QEMUMachine mcf5208evb_machine = {
+    .name = "mcf5208evb",
+    .desc = "MCF5206EVB",
+    .init = mcf5208evb_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mcf5208evb_machine_init(void)
+{
+    qemu_register_machine(&mcf5208evb_machine);
+}
+
+machine_init(mcf5208evb_machine_init);
diff --git a/hw/m68k/mcf_intc.c b/hw/m68k/mcf_intc.c
new file mode 100644 (file)
index 0000000..fff27b3
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * ColdFire Interrupt Controller emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+#include "hw/hw.h"
+#include "hw/mcf.h"
+#include "exec/address-spaces.h"
+
+typedef struct {
+    MemoryRegion iomem;
+    uint64_t ipr;
+    uint64_t imr;
+    uint64_t ifr;
+    uint64_t enabled;
+    uint8_t icr[64];
+    M68kCPU *cpu;
+    int active_vector;
+} mcf_intc_state;
+
+static void mcf_intc_update(mcf_intc_state *s)
+{
+    uint64_t active;
+    int i;
+    int best;
+    int best_level;
+
+    active = (s->ipr | s->ifr) & s->enabled & ~s->imr;
+    best_level = 0;
+    best = 64;
+    if (active) {
+        for (i = 0; i < 64; i++) {
+            if ((active & 1) != 0 && s->icr[i] >= best_level) {
+                best_level = s->icr[i];
+                best = i;
+            }
+            active >>= 1;
+        }
+    }
+    s->active_vector = ((best == 64) ? 24 : (best + 64));
+    m68k_set_irq_level(s->cpu, best_level, s->active_vector);
+}
+
+static uint64_t mcf_intc_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    int offset;
+    mcf_intc_state *s = (mcf_intc_state *)opaque;
+    offset = addr & 0xff;
+    if (offset >= 0x40 && offset < 0x80) {
+        return s->icr[offset - 0x40];
+    }
+    switch (offset) {
+    case 0x00:
+        return (uint32_t)(s->ipr >> 32);
+    case 0x04:
+        return (uint32_t)s->ipr;
+    case 0x08:
+        return (uint32_t)(s->imr >> 32);
+    case 0x0c:
+        return (uint32_t)s->imr;
+    case 0x10:
+        return (uint32_t)(s->ifr >> 32);
+    case 0x14:
+        return (uint32_t)s->ifr;
+    case 0xe0: /* SWIACK.  */
+        return s->active_vector;
+    case 0xe1: case 0xe2: case 0xe3: case 0xe4:
+    case 0xe5: case 0xe6: case 0xe7:
+        /* LnIACK */
+        hw_error("mcf_intc_read: LnIACK not implemented\n");
+    default:
+        return 0;
+    }
+}
+
+static void mcf_intc_write(void *opaque, hwaddr addr,
+                           uint64_t val, unsigned size)
+{
+    int offset;
+    mcf_intc_state *s = (mcf_intc_state *)opaque;
+    offset = addr & 0xff;
+    if (offset >= 0x40 && offset < 0x80) {
+        int n = offset - 0x40;
+        s->icr[n] = val;
+        if (val == 0)
+            s->enabled &= ~(1ull << n);
+        else
+            s->enabled |= (1ull << n);
+        mcf_intc_update(s);
+        return;
+    }
+    switch (offset) {
+    case 0x00: case 0x04:
+        /* Ignore IPR writes.  */
+        return;
+    case 0x08:
+        s->imr = (s->imr & 0xffffffff) | ((uint64_t)val << 32);
+        break;
+    case 0x0c:
+        s->imr = (s->imr & 0xffffffff00000000ull) | (uint32_t)val;
+        break;
+    default:
+        hw_error("mcf_intc_write: Bad write offset %d\n", offset);
+        break;
+    }
+    mcf_intc_update(s);
+}
+
+static void mcf_intc_set_irq(void *opaque, int irq, int level)
+{
+    mcf_intc_state *s = (mcf_intc_state *)opaque;
+    if (irq >= 64)
+        return;
+    if (level)
+        s->ipr |= 1ull << irq;
+    else
+        s->ipr &= ~(1ull << irq);
+    mcf_intc_update(s);
+}
+
+static void mcf_intc_reset(mcf_intc_state *s)
+{
+    s->imr = ~0ull;
+    s->ipr = 0;
+    s->ifr = 0;
+    s->enabled = 0;
+    memset(s->icr, 0, 64);
+    s->active_vector = 24;
+}
+
+static const MemoryRegionOps mcf_intc_ops = {
+    .read = mcf_intc_read,
+    .write = mcf_intc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+qemu_irq *mcf_intc_init(MemoryRegion *sysmem,
+                        hwaddr base,
+                        M68kCPU *cpu)
+{
+    mcf_intc_state *s;
+
+    s = g_malloc0(sizeof(mcf_intc_state));
+    s->cpu = cpu;
+    mcf_intc_reset(s);
+
+    memory_region_init_io(&s->iomem, &mcf_intc_ops, s, "mcf", 0x100);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
+
+    return qemu_allocate_irqs(mcf_intc_set_irq, s, 64);
+}
index 73d74c2c594d4183740af2f2324ddc9ecd34d820..61d2f35c8e6ff5fb4948e60b61c353e4190f1c4d 100644 (file)
@@ -36,9 +36,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "isa.h"
-#include "mac_dbdma.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
+#include "hw/mac_dbdma.h"
 #include "qemu/main-loop.h"
 
 /* debug DBDMA */
index 25121fa482c1e50df70048edcb5a237568898582..ed32bde5aba2fbc2b7e385bb3b16afd9bc2b0e2d 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "firmware_abi.h"
+#include "hw/hw.h"
+#include "hw/firmware_abi.h"
 #include "sysemu/sysemu.h"
-#include "ppc/mac.h"
+#include "hw/ppc/mac.h"
 
 /* debug NVR */
 //#define DEBUG_NVR
index 0c6a6b8e7abb6c49bcc82d1c4ba779ce57f4af4b..e91143e3315aceebed7989b231ebaebb881f7bee 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc/mac.h"
-#include "pci/pci.h"
-#include "mac_dbdma.h"
-#include "escc.h"
+#include "hw/hw.h"
+#include "hw/ppc/mac.h"
+#include "hw/pci/pci.h"
+#include "hw/mac_dbdma.h"
+#include "hw/escc.h"
 
 #define TYPE_MACIO "macio"
 #define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO)
diff --git a/hw/mainstone.c b/hw/mainstone.c
deleted file mode 100644 (file)
index d1ff6e7..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * PXA270-based Intel Mainstone platforms.
- *
- * Copyright (c) 2007 by Armin Kuster <akuster@kama-aina.net> or
- *                                    <akuster@mvista.com>
- *
- * Code based on spitz platform by Andrzej Zaborowski <balrog@zabor.org>
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-#include "hw.h"
-#include "pxa.h"
-#include "arm-misc.h"
-#include "net/net.h"
-#include "devices.h"
-#include "boards.h"
-#include "flash.h"
-#include "sysemu/blockdev.h"
-#include "sysbus.h"
-#include "exec/address-spaces.h"
-
-/* Device addresses */
-#define MST_FPGA_PHYS  0x08000000
-#define MST_ETH_PHYS   0x10000300
-#define MST_FLASH_0            0x00000000
-#define MST_FLASH_1            0x04000000
-
-/* IRQ definitions */
-#define MMC_IRQ       0
-#define USIM_IRQ      1
-#define USBC_IRQ      2
-#define ETHERNET_IRQ  3
-#define AC97_IRQ      4
-#define PEN_IRQ       5
-#define MSINS_IRQ     6
-#define EXBRD_IRQ     7
-#define S0_CD_IRQ     9
-#define S0_STSCHG_IRQ 10
-#define S0_IRQ        11
-#define S1_CD_IRQ     13
-#define S1_STSCHG_IRQ 14
-#define S1_IRQ        15
-
-static struct keymap map[0xE0] = {
-    [0 ... 0xDF] = { -1, -1 },
-    [0x1e] = {0,0}, /* a */
-    [0x30] = {0,1}, /* b */
-    [0x2e] = {0,2}, /* c */
-    [0x20] = {0,3}, /* d */
-    [0x12] = {0,4}, /* e */
-    [0x21] = {0,5}, /* f */
-    [0x22] = {1,0}, /* g */
-    [0x23] = {1,1}, /* h */
-    [0x17] = {1,2}, /* i */
-    [0x24] = {1,3}, /* j */
-    [0x25] = {1,4}, /* k */
-    [0x26] = {1,5}, /* l */
-    [0x32] = {2,0}, /* m */
-    [0x31] = {2,1}, /* n */
-    [0x18] = {2,2}, /* o */
-    [0x19] = {2,3}, /* p */
-    [0x10] = {2,4}, /* q */
-    [0x13] = {2,5}, /* r */
-    [0x1f] = {3,0}, /* s */
-    [0x14] = {3,1}, /* t */
-    [0x16] = {3,2}, /* u */
-    [0x2f] = {3,3}, /* v */
-    [0x11] = {3,4}, /* w */
-    [0x2d] = {3,5}, /* x */
-    [0x15] = {4,2}, /* y */
-    [0x2c] = {4,3}, /* z */
-    [0xc7] = {5,0}, /* Home */
-    [0x2a] = {5,1}, /* shift */
-    [0x39] = {5,2}, /* space */
-    [0x39] = {5,3}, /* space */
-    [0x1c] = {5,5}, /*  enter */
-    [0xc8] = {6,0}, /* up */
-    [0xd0] = {6,1}, /* down */
-    [0xcb] = {6,2}, /* left */
-    [0xcd] = {6,3}, /* right */
-};
-
-enum mainstone_model_e { mainstone };
-
-#define MAINSTONE_RAM  0x04000000
-#define MAINSTONE_ROM  0x00800000
-#define MAINSTONE_FLASH        0x02000000
-
-static struct arm_boot_info mainstone_binfo = {
-    .loader_start = PXA2XX_SDRAM_BASE,
-    .ram_size = 0x04000000,
-};
-
-static void mainstone_common_init(MemoryRegion *address_space_mem,
-                                  QEMUMachineInitArgs *args,
-                                  enum mainstone_model_e model, int arm_id)
-{
-    uint32_t sector_len = 256 * 1024;
-    hwaddr mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
-    PXA2xxState *mpu;
-    DeviceState *mst_irq;
-    DriveInfo *dinfo;
-    int i;
-    int be;
-    MemoryRegion *rom = g_new(MemoryRegion, 1);
-    const char *cpu_model = args->cpu_model;
-
-    if (!cpu_model)
-        cpu_model = "pxa270-c5";
-
-    /* Setup CPU & memory */
-    mpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model);
-    memory_region_init_ram(rom, "mainstone.rom", MAINSTONE_ROM);
-    vmstate_register_ram_global(rom);
-    memory_region_set_readonly(rom, true);
-    memory_region_add_subregion(address_space_mem, 0, rom);
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    /* There are two 32MiB flash devices on the board */
-    for (i = 0; i < 2; i ++) {
-        dinfo = drive_get(IF_PFLASH, 0, i);
-        if (!dinfo) {
-            fprintf(stderr, "Two flash images must be given with the "
-                    "'pflash' parameter\n");
-            exit(1);
-        }
-
-        if (!pflash_cfi01_register(mainstone_flash_base[i], NULL,
-                                   i ? "mainstone.flash1" : "mainstone.flash0",
-                                   MAINSTONE_FLASH,
-                                   dinfo->bdrv, sector_len,
-                                   MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
-                                   be)) {
-            fprintf(stderr, "qemu: Error registering flash memory.\n");
-            exit(1);
-        }
-    }
-
-    mst_irq = sysbus_create_simple("mainstone-fpga", MST_FPGA_PHYS,
-                    qdev_get_gpio_in(mpu->gpio, 0));
-
-    /* setup keypad */
-    printf("map addr %p\n", &map);
-    pxa27x_register_keypad(mpu->kp, map, 0xe0);
-
-    /* MMC/SD host */
-    pxa2xx_mmci_handlers(mpu->mmc, NULL, qdev_get_gpio_in(mst_irq, MMC_IRQ));
-
-    pxa2xx_pcmcia_set_irq_cb(mpu->pcmcia[0],
-            qdev_get_gpio_in(mst_irq, S0_IRQ),
-            qdev_get_gpio_in(mst_irq, S0_CD_IRQ));
-    pxa2xx_pcmcia_set_irq_cb(mpu->pcmcia[1],
-            qdev_get_gpio_in(mst_irq, S1_IRQ),
-            qdev_get_gpio_in(mst_irq, S1_CD_IRQ));
-
-    smc91c111_init(&nd_table[0], MST_ETH_PHYS,
-                    qdev_get_gpio_in(mst_irq, ETHERNET_IRQ));
-
-    mainstone_binfo.kernel_filename = args->kernel_filename;
-    mainstone_binfo.kernel_cmdline = args->kernel_cmdline;
-    mainstone_binfo.initrd_filename = args->initrd_filename;
-    mainstone_binfo.board_id = arm_id;
-    arm_load_kernel(mpu->cpu, &mainstone_binfo);
-}
-
-static void mainstone_init(QEMUMachineInitArgs *args)
-{
-    mainstone_common_init(get_system_memory(), args, mainstone, 0x196);
-}
-
-static QEMUMachine mainstone2_machine = {
-    .name = "mainstone",
-    .desc = "Mainstone II (PXA27x)",
-    .init = mainstone_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mainstone_machine_init(void)
-{
-    qemu_register_machine(&mainstone2_machine);
-}
-
-machine_init(mainstone_machine_init);
index c792caf2717e7d3ffecc25a842117b173c5e843d..e042046e4f15d7d7ed8c6ad5d92b221ff5f9fd43 100644 (file)
@@ -9,10 +9,10 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "sysbus.h"
-#include "hw.h"
-#include "i2c.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
+#include "hw/sysbus.h"
 #include "audio/audio.h"
 
 #define MP_AUDIO_SIZE           0x00001000
index de1be4ddd6cf9c96aee289b341269ca0ddb50a8d..d477ecdb29c0a88ebe3086c674d53150bd59899f 100644 (file)
@@ -10,7 +10,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "ssi.h"
+#include "hw/ssi.h"
 
 typedef struct {
     SSISlave ssidev;
index c2df0b49ebb242b30dccf13c2796338f222d901f..e5cb810a276494218c2d1204cf034f7750f48512 100644 (file)
@@ -7,7 +7,7 @@
  * This file is licensed under GNU GPL.
  */
 
-#include "i2c.h"
+#include "hw/i2c.h"
 
 typedef struct {
     I2CSlave i2c;
index 2fb11f69a31760e1603d7ea11212836b26a8f361..a2119ad2f1b2a2ecd03a27b8a0feb1c9dfe42e5d 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
-#include "mc146818rtc.h"
+#include "hw/mc146818rtc.h"
 #include "qapi/visitor.h"
 
 #ifdef TARGET_I386
-#include "apic.h"
+#include "hw/apic.h"
 #endif
 
 //#define DEBUG_CMOS
index f286b6a12ae36326bfdb9855403ffc73fb4f1dac..967403edb5384237ce390a2d509c27038251eaae 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef MC146818RTC_H
 #define MC146818RTC_H
 
-#include "isa.h"
-#include "mc146818rtc_regs.h"
+#include "hw/isa.h"
+#include "hw/mc146818rtc_regs.h"
 
 ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq);
 void rtc_set_memory(ISADevice *dev, int addr, int val);
diff --git a/hw/mcf5206.c b/hw/mcf5206.c
deleted file mode 100644 (file)
index ea2db23..0000000
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
- * Motorola ColdFire MCF5206 SoC embedded peripheral emulation.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-#include "hw.h"
-#include "mcf.h"
-#include "qemu/timer.h"
-#include "ptimer.h"
-#include "sysemu/sysemu.h"
-#include "exec/address-spaces.h"
-
-/* General purpose timer module.  */
-typedef struct {
-    uint16_t tmr;
-    uint16_t trr;
-    uint16_t tcr;
-    uint16_t ter;
-    ptimer_state *timer;
-    qemu_irq irq;
-    int irq_state;
-} m5206_timer_state;
-
-#define TMR_RST 0x01
-#define TMR_CLK 0x06
-#define TMR_FRR 0x08
-#define TMR_ORI 0x10
-#define TMR_OM  0x20
-#define TMR_CE  0xc0
-
-#define TER_CAP 0x01
-#define TER_REF 0x02
-
-static void m5206_timer_update(m5206_timer_state *s)
-{
-    if ((s->tmr & TMR_ORI) != 0 && (s->ter & TER_REF))
-        qemu_irq_raise(s->irq);
-    else
-        qemu_irq_lower(s->irq);
-}
-
-static void m5206_timer_reset(m5206_timer_state *s)
-{
-    s->tmr = 0;
-    s->trr = 0;
-}
-
-static void m5206_timer_recalibrate(m5206_timer_state *s)
-{
-    int prescale;
-    int mode;
-
-    ptimer_stop(s->timer);
-
-    if ((s->tmr & TMR_RST) == 0)
-        return;
-
-    prescale = (s->tmr >> 8) + 1;
-    mode = (s->tmr >> 1) & 3;
-    if (mode == 2)
-        prescale *= 16;
-
-    if (mode == 3 || mode == 0)
-        hw_error("m5206_timer: mode %d not implemented\n", mode);
-    if ((s->tmr & TMR_FRR) == 0)
-        hw_error("m5206_timer: free running mode not implemented\n");
-
-    /* Assume 66MHz system clock.  */
-    ptimer_set_freq(s->timer, 66000000 / prescale);
-
-    ptimer_set_limit(s->timer, s->trr, 0);
-
-    ptimer_run(s->timer, 0);
-}
-
-static void m5206_timer_trigger(void *opaque)
-{
-    m5206_timer_state *s = (m5206_timer_state *)opaque;
-    s->ter |= TER_REF;
-    m5206_timer_update(s);
-}
-
-static uint32_t m5206_timer_read(m5206_timer_state *s, uint32_t addr)
-{
-    switch (addr) {
-    case 0:
-        return s->tmr;
-    case 4:
-        return s->trr;
-    case 8:
-        return s->tcr;
-    case 0xc:
-        return s->trr - ptimer_get_count(s->timer);
-    case 0x11:
-        return s->ter;
-    default:
-        return 0;
-    }
-}
-
-static void m5206_timer_write(m5206_timer_state *s, uint32_t addr, uint32_t val)
-{
-    switch (addr) {
-    case 0:
-        if ((s->tmr & TMR_RST) != 0 && (val & TMR_RST) == 0) {
-            m5206_timer_reset(s);
-        }
-        s->tmr = val;
-        m5206_timer_recalibrate(s);
-        break;
-    case 4:
-        s->trr = val;
-        m5206_timer_recalibrate(s);
-        break;
-    case 8:
-        s->tcr = val;
-        break;
-    case 0xc:
-        ptimer_set_count(s->timer, val);
-        break;
-    case 0x11:
-        s->ter &= ~val;
-        break;
-    default:
-        break;
-    }
-    m5206_timer_update(s);
-}
-
-static m5206_timer_state *m5206_timer_init(qemu_irq irq)
-{
-    m5206_timer_state *s;
-    QEMUBH *bh;
-
-    s = (m5206_timer_state *)g_malloc0(sizeof(m5206_timer_state));
-    bh = qemu_bh_new(m5206_timer_trigger, s);
-    s->timer = ptimer_init(bh);
-    s->irq = irq;
-    m5206_timer_reset(s);
-    return s;
-}
-
-/* System Integration Module.  */
-
-typedef struct {
-    M68kCPU *cpu;
-    MemoryRegion iomem;
-    m5206_timer_state *timer[2];
-    void *uart[2];
-    uint8_t scr;
-    uint8_t icr[14];
-    uint16_t imr; /* 1 == interrupt is masked.  */
-    uint16_t ipr;
-    uint8_t rsr;
-    uint8_t swivr;
-    uint8_t par;
-    /* Include the UART vector registers here.  */
-    uint8_t uivr[2];
-} m5206_mbar_state;
-
-/* Interrupt controller.  */
-
-static int m5206_find_pending_irq(m5206_mbar_state *s)
-{
-    int level;
-    int vector;
-    uint16_t active;
-    int i;
-
-    level = 0;
-    vector = 0;
-    active = s->ipr & ~s->imr;
-    if (!active)
-        return 0;
-
-    for (i = 1; i < 14; i++) {
-        if (active & (1 << i)) {
-            if ((s->icr[i] & 0x1f) > level) {
-                level = s->icr[i] & 0x1f;
-                vector = i;
-            }
-        }
-    }
-
-    if (level < 4)
-        vector = 0;
-
-    return vector;
-}
-
-static void m5206_mbar_update(m5206_mbar_state *s)
-{
-    int irq;
-    int vector;
-    int level;
-
-    irq = m5206_find_pending_irq(s);
-    if (irq) {
-        int tmp;
-        tmp = s->icr[irq];
-        level = (tmp >> 2) & 7;
-        if (tmp & 0x80) {
-            /* Autovector.  */
-            vector = 24 + level;
-        } else {
-            switch (irq) {
-            case 8: /* SWT */
-                vector = s->swivr;
-                break;
-            case 12: /* UART1 */
-                vector = s->uivr[0];
-                break;
-            case 13: /* UART2 */
-                vector = s->uivr[1];
-                break;
-            default:
-                /* Unknown vector.  */
-                fprintf(stderr, "Unhandled vector for IRQ %d\n", irq);
-                vector = 0xf;
-                break;
-            }
-        }
-    } else {
-        level = 0;
-        vector = 0;
-    }
-    m68k_set_irq_level(s->cpu, level, vector);
-}
-
-static void m5206_mbar_set_irq(void *opaque, int irq, int level)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    if (level) {
-        s->ipr |= 1 << irq;
-    } else {
-        s->ipr &= ~(1 << irq);
-    }
-    m5206_mbar_update(s);
-}
-
-/* System Integration Module.  */
-
-static void m5206_mbar_reset(m5206_mbar_state *s)
-{
-    s->scr = 0xc0;
-    s->icr[1] = 0x04;
-    s->icr[2] = 0x08;
-    s->icr[3] = 0x0c;
-    s->icr[4] = 0x10;
-    s->icr[5] = 0x14;
-    s->icr[6] = 0x18;
-    s->icr[7] = 0x1c;
-    s->icr[8] = 0x1c;
-    s->icr[9] = 0x80;
-    s->icr[10] = 0x80;
-    s->icr[11] = 0x80;
-    s->icr[12] = 0x00;
-    s->icr[13] = 0x00;
-    s->imr = 0x3ffe;
-    s->rsr = 0x80;
-    s->swivr = 0x0f;
-    s->par = 0;
-}
-
-static uint64_t m5206_mbar_read(m5206_mbar_state *s,
-                                uint64_t offset, unsigned size)
-{
-    if (offset >= 0x100 && offset < 0x120) {
-        return m5206_timer_read(s->timer[0], offset - 0x100);
-    } else if (offset >= 0x120 && offset < 0x140) {
-        return m5206_timer_read(s->timer[1], offset - 0x120);
-    } else if (offset >= 0x140 && offset < 0x160) {
-        return mcf_uart_read(s->uart[0], offset - 0x140, size);
-    } else if (offset >= 0x180 && offset < 0x1a0) {
-        return mcf_uart_read(s->uart[1], offset - 0x180, size);
-    }
-    switch (offset) {
-    case 0x03: return s->scr;
-    case 0x14 ... 0x20: return s->icr[offset - 0x13];
-    case 0x36: return s->imr;
-    case 0x3a: return s->ipr;
-    case 0x40: return s->rsr;
-    case 0x41: return 0;
-    case 0x42: return s->swivr;
-    case 0x50:
-        /* DRAM mask register.  */
-        /* FIXME: currently hardcoded to 128Mb.  */
-        {
-            uint32_t mask = ~0;
-            while (mask > ram_size)
-                mask >>= 1;
-            return mask & 0x0ffe0000;
-        }
-    case 0x5c: return 1; /* DRAM bank 1 empty.  */
-    case 0xcb: return s->par;
-    case 0x170: return s->uivr[0];
-    case 0x1b0: return s->uivr[1];
-    }
-    hw_error("Bad MBAR read offset 0x%x", (int)offset);
-    return 0;
-}
-
-static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset,
-                             uint64_t value, unsigned size)
-{
-    if (offset >= 0x100 && offset < 0x120) {
-        m5206_timer_write(s->timer[0], offset - 0x100, value);
-        return;
-    } else if (offset >= 0x120 && offset < 0x140) {
-        m5206_timer_write(s->timer[1], offset - 0x120, value);
-        return;
-    } else if (offset >= 0x140 && offset < 0x160) {
-        mcf_uart_write(s->uart[0], offset - 0x140, value, size);
-        return;
-    } else if (offset >= 0x180 && offset < 0x1a0) {
-        mcf_uart_write(s->uart[1], offset - 0x180, value, size);
-        return;
-    }
-    switch (offset) {
-    case 0x03:
-        s->scr = value;
-        break;
-    case 0x14 ... 0x20:
-        s->icr[offset - 0x13] = value;
-        m5206_mbar_update(s);
-        break;
-    case 0x36:
-        s->imr = value;
-        m5206_mbar_update(s);
-        break;
-    case 0x40:
-        s->rsr &= ~value;
-        break;
-    case 0x41:
-        /* TODO: implement watchdog.  */
-        break;
-    case 0x42:
-        s->swivr = value;
-        break;
-    case 0xcb:
-        s->par = value;
-        break;
-    case 0x170:
-        s->uivr[0] = value;
-        break;
-    case 0x178: case 0x17c: case 0x1c8: case 0x1bc:
-        /* Not implemented: UART Output port bits.  */
-        break;
-    case 0x1b0:
-        s->uivr[1] = value;
-        break;
-    default:
-        hw_error("Bad MBAR write offset 0x%x", (int)offset);
-        break;
-    }
-}
-
-/* Internal peripherals use a variety of register widths.
-   This lookup table allows a single routine to handle all of them.  */
-static const uint8_t m5206_mbar_width[] =
-{
-  /* 000-040 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  2, 2, 2, 2,
-  /* 040-080 */ 1, 2, 2, 2,  4, 1, 2, 4,  1, 2, 4, 2,  2, 4, 2, 2,
-  /* 080-0c0 */ 4, 2, 2, 4,  2, 2, 4, 2,  2, 4, 2, 2,  4, 2, 2, 4,
-  /* 0c0-100 */ 2, 2, 1, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,
-  /* 100-140 */ 2, 2, 2, 2,  1, 0, 0, 0,  2, 2, 2, 2,  1, 0, 0, 0,
-  /* 140-180 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-  /* 180-1c0 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-  /* 1c0-200 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-};
-
-static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset);
-static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset);
-
-static uint32_t m5206_mbar_readb(void *opaque, hwaddr offset)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR read offset 0x%x", (int)offset);
-    }
-    if (m5206_mbar_width[offset >> 2] > 1) {
-        uint16_t val;
-        val = m5206_mbar_readw(opaque, offset & ~1);
-        if ((offset & 1) == 0) {
-            val >>= 8;
-        }
-        return val & 0xff;
-    }
-    return m5206_mbar_read(s, offset, 1);
-}
-
-static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    int width;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR read offset 0x%x", (int)offset);
-    }
-    width = m5206_mbar_width[offset >> 2];
-    if (width > 2) {
-        uint32_t val;
-        val = m5206_mbar_readl(opaque, offset & ~3);
-        if ((offset & 3) == 0)
-            val >>= 16;
-        return val & 0xffff;
-    } else if (width < 2) {
-        uint16_t val;
-        val = m5206_mbar_readb(opaque, offset) << 8;
-        val |= m5206_mbar_readb(opaque, offset + 1);
-        return val;
-    }
-    return m5206_mbar_read(s, offset, 2);
-}
-
-static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    int width;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR read offset 0x%x", (int)offset);
-    }
-    width = m5206_mbar_width[offset >> 2];
-    if (width < 4) {
-        uint32_t val;
-        val = m5206_mbar_readw(opaque, offset) << 16;
-        val |= m5206_mbar_readw(opaque, offset + 2);
-        return val;
-    }
-    return m5206_mbar_read(s, offset, 4);
-}
-
-static void m5206_mbar_writew(void *opaque, hwaddr offset,
-                              uint32_t value);
-static void m5206_mbar_writel(void *opaque, hwaddr offset,
-                              uint32_t value);
-
-static void m5206_mbar_writeb(void *opaque, hwaddr offset,
-                              uint32_t value)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    int width;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR write offset 0x%x", (int)offset);
-    }
-    width = m5206_mbar_width[offset >> 2];
-    if (width > 1) {
-        uint32_t tmp;
-        tmp = m5206_mbar_readw(opaque, offset & ~1);
-        if (offset & 1) {
-            tmp = (tmp & 0xff00) | value;
-        } else {
-            tmp = (tmp & 0x00ff) | (value << 8);
-        }
-        m5206_mbar_writew(opaque, offset & ~1, tmp);
-        return;
-    }
-    m5206_mbar_write(s, offset, value, 1);
-}
-
-static void m5206_mbar_writew(void *opaque, hwaddr offset,
-                              uint32_t value)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    int width;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR write offset 0x%x", (int)offset);
-    }
-    width = m5206_mbar_width[offset >> 2];
-    if (width > 2) {
-        uint32_t tmp;
-        tmp = m5206_mbar_readl(opaque, offset & ~3);
-        if (offset & 3) {
-            tmp = (tmp & 0xffff0000) | value;
-        } else {
-            tmp = (tmp & 0x0000ffff) | (value << 16);
-        }
-        m5206_mbar_writel(opaque, offset & ~3, tmp);
-        return;
-    } else if (width < 2) {
-        m5206_mbar_writeb(opaque, offset, value >> 8);
-        m5206_mbar_writeb(opaque, offset + 1, value & 0xff);
-        return;
-    }
-    m5206_mbar_write(s, offset, value, 2);
-}
-
-static void m5206_mbar_writel(void *opaque, hwaddr offset,
-                              uint32_t value)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    int width;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR write offset 0x%x", (int)offset);
-    }
-    width = m5206_mbar_width[offset >> 2];
-    if (width < 4) {
-        m5206_mbar_writew(opaque, offset, value >> 16);
-        m5206_mbar_writew(opaque, offset + 2, value & 0xffff);
-        return;
-    }
-    m5206_mbar_write(s, offset, value, 4);
-}
-
-static const MemoryRegionOps m5206_mbar_ops = {
-    .old_mmio = {
-        .read = {
-            m5206_mbar_readb,
-            m5206_mbar_readw,
-            m5206_mbar_readl,
-        },
-        .write = {
-            m5206_mbar_writeb,
-            m5206_mbar_writew,
-            m5206_mbar_writel,
-        },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, M68kCPU *cpu)
-{
-    m5206_mbar_state *s;
-    qemu_irq *pic;
-
-    s = (m5206_mbar_state *)g_malloc0(sizeof(m5206_mbar_state));
-
-    memory_region_init_io(&s->iomem, &m5206_mbar_ops, s,
-                          "mbar", 0x00001000);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-
-    pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14);
-    s->timer[0] = m5206_timer_init(pic[9]);
-    s->timer[1] = m5206_timer_init(pic[10]);
-    s->uart[0] = mcf_uart_init(pic[12], serial_hds[0]);
-    s->uart[1] = mcf_uart_init(pic[13], serial_hds[1]);
-    s->cpu = cpu;
-
-    m5206_mbar_reset(s);
-    return pic;
-}
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
deleted file mode 100644 (file)
index 86402d3..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Motorola ColdFire MCF5208 SoC emulation.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-#include "hw.h"
-#include "mcf.h"
-#include "qemu/timer.h"
-#include "ptimer.h"
-#include "sysemu/sysemu.h"
-#include "net/net.h"
-#include "boards.h"
-#include "loader.h"
-#include "elf.h"
-#include "exec/address-spaces.h"
-
-#define SYS_FREQ 66000000
-
-#define PCSR_EN         0x0001
-#define PCSR_RLD        0x0002
-#define PCSR_PIF        0x0004
-#define PCSR_PIE        0x0008
-#define PCSR_OVW        0x0010
-#define PCSR_DBG        0x0020
-#define PCSR_DOZE       0x0040
-#define PCSR_PRE_SHIFT  8
-#define PCSR_PRE_MASK   0x0f00
-
-typedef struct {
-    MemoryRegion iomem;
-    qemu_irq irq;
-    ptimer_state *timer;
-    uint16_t pcsr;
-    uint16_t pmr;
-    uint16_t pcntr;
-} m5208_timer_state;
-
-static void m5208_timer_update(m5208_timer_state *s)
-{
-    if ((s->pcsr & (PCSR_PIE | PCSR_PIF)) == (PCSR_PIE | PCSR_PIF))
-        qemu_irq_raise(s->irq);
-    else
-        qemu_irq_lower(s->irq);
-}
-
-static void m5208_timer_write(void *opaque, hwaddr offset,
-                              uint64_t value, unsigned size)
-{
-    m5208_timer_state *s = (m5208_timer_state *)opaque;
-    int prescale;
-    int limit;
-    switch (offset) {
-    case 0:
-        /* The PIF bit is set-to-clear.  */
-        if (value & PCSR_PIF) {
-            s->pcsr &= ~PCSR_PIF;
-            value &= ~PCSR_PIF;
-        }
-        /* Avoid frobbing the timer if we're just twiddling IRQ bits. */
-        if (((s->pcsr ^ value) & ~PCSR_PIE) == 0) {
-            s->pcsr = value;
-            m5208_timer_update(s);
-            return;
-        }
-
-        if (s->pcsr & PCSR_EN)
-            ptimer_stop(s->timer);
-
-        s->pcsr = value;
-
-        prescale = 1 << ((s->pcsr & PCSR_PRE_MASK) >> PCSR_PRE_SHIFT);
-        ptimer_set_freq(s->timer, (SYS_FREQ / 2) / prescale);
-        if (s->pcsr & PCSR_RLD)
-            limit = s->pmr;
-        else
-            limit = 0xffff;
-        ptimer_set_limit(s->timer, limit, 0);
-
-        if (s->pcsr & PCSR_EN)
-            ptimer_run(s->timer, 0);
-        break;
-    case 2:
-        s->pmr = value;
-        s->pcsr &= ~PCSR_PIF;
-        if ((s->pcsr & PCSR_RLD) == 0) {
-            if (s->pcsr & PCSR_OVW)
-                ptimer_set_count(s->timer, value);
-        } else {
-            ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW);
-        }
-        break;
-    case 4:
-        break;
-    default:
-        hw_error("m5208_timer_write: Bad offset 0x%x\n", (int)offset);
-        break;
-    }
-    m5208_timer_update(s);
-}
-
-static void m5208_timer_trigger(void *opaque)
-{
-    m5208_timer_state *s = (m5208_timer_state *)opaque;
-    s->pcsr |= PCSR_PIF;
-    m5208_timer_update(s);
-}
-
-static uint64_t m5208_timer_read(void *opaque, hwaddr addr,
-                                 unsigned size)
-{
-    m5208_timer_state *s = (m5208_timer_state *)opaque;
-    switch (addr) {
-    case 0:
-        return s->pcsr;
-    case 2:
-        return s->pmr;
-    case 4:
-        return ptimer_get_count(s->timer);
-    default:
-        hw_error("m5208_timer_read: Bad offset 0x%x\n", (int)addr);
-        return 0;
-    }
-}
-
-static const MemoryRegionOps m5208_timer_ops = {
-    .read = m5208_timer_read,
-    .write = m5208_timer_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static uint64_t m5208_sys_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    switch (addr) {
-    case 0x110: /* SDCS0 */
-        {
-            int n;
-            for (n = 0; n < 32; n++) {
-                if (ram_size < (2u << n))
-                    break;
-            }
-            return (n - 1)  | 0x40000000;
-        }
-    case 0x114: /* SDCS1 */
-        return 0;
-
-    default:
-        hw_error("m5208_sys_read: Bad offset 0x%x\n", (int)addr);
-        return 0;
-    }
-}
-
-static void m5208_sys_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr);
-}
-
-static const MemoryRegionOps m5208_sys_ops = {
-    .read = m5208_sys_read,
-    .write = m5208_sys_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
-{
-    MemoryRegion *iomem = g_new(MemoryRegion, 1);
-    m5208_timer_state *s;
-    QEMUBH *bh;
-    int i;
-
-    /* SDRAMC.  */
-    memory_region_init_io(iomem, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000);
-    memory_region_add_subregion(address_space, 0xfc0a8000, iomem);
-    /* Timers.  */
-    for (i = 0; i < 2; i++) {
-        s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state));
-        bh = qemu_bh_new(m5208_timer_trigger, s);
-        s->timer = ptimer_init(bh);
-        memory_region_init_io(&s->iomem, &m5208_timer_ops, s,
-                              "m5208-timer", 0x00004000);
-        memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
-                                    &s->iomem);
-        s->irq = pic[4 + i];
-    }
-}
-
-static void mcf5208evb_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    M68kCPU *cpu;
-    CPUM68KState *env;
-    int kernel_size;
-    uint64_t elf_entry;
-    hwaddr entry;
-    qemu_irq *pic;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-
-    if (!cpu_model) {
-        cpu_model = "m5208";
-    }
-    cpu = cpu_m68k_init(cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find m68k CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    /* Initialize CPU registers.  */
-    env->vbr = 0;
-    /* TODO: Configure BARs.  */
-
-    /* DRAM at 0x40000000 */
-    memory_region_init_ram(ram, "mcf5208.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, 0x40000000, ram);
-
-    /* Internal SRAM.  */
-    memory_region_init_ram(sram, "mcf5208.sram", 16384);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(address_space_mem, 0x80000000, sram);
-
-    /* Internal peripherals.  */
-    pic = mcf_intc_init(address_space_mem, 0xfc048000, cpu);
-
-    mcf_uart_mm_init(address_space_mem, 0xfc060000, pic[26], serial_hds[0]);
-    mcf_uart_mm_init(address_space_mem, 0xfc064000, pic[27], serial_hds[1]);
-    mcf_uart_mm_init(address_space_mem, 0xfc068000, pic[28], serial_hds[2]);
-
-    mcf5208_sys_init(address_space_mem, pic);
-
-    if (nb_nics > 1) {
-        fprintf(stderr, "Too many NICs\n");
-        exit(1);
-    }
-    if (nd_table[0].used)
-        mcf_fec_init(address_space_mem, &nd_table[0],
-                     0xfc030000, pic + 36);
-
-    /*  0xfc000000 SCM.  */
-    /*  0xfc004000 XBS.  */
-    /*  0xfc008000 FlexBus CS.  */
-    /* 0xfc030000 FEC.  */
-    /*  0xfc040000 SCM + Power management.  */
-    /*  0xfc044000 eDMA.  */
-    /* 0xfc048000 INTC.  */
-    /*  0xfc058000 I2C.  */
-    /*  0xfc05c000 QSPI.  */
-    /* 0xfc060000 UART0.  */
-    /* 0xfc064000 UART0.  */
-    /* 0xfc068000 UART0.  */
-    /*  0xfc070000 DMA timers.  */
-    /* 0xfc080000 PIT0.  */
-    /* 0xfc084000 PIT1.  */
-    /*  0xfc088000 EPORT.  */
-    /*  0xfc08c000 Watchdog.  */
-    /*  0xfc090000 clock module.  */
-    /*  0xfc0a0000 CCM + reset.  */
-    /*  0xfc0a4000 GPIO.  */
-    /* 0xfc0a8000 SDRAM controller.  */
-
-    /* Load kernel.  */
-    if (!kernel_filename) {
-        fprintf(stderr, "Kernel image must be specified\n");
-        exit(1);
-    }
-
-    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                           NULL, NULL, 1, ELF_MACHINE, 0);
-    entry = elf_entry;
-    if (kernel_size < 0) {
-        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
-    }
-    if (kernel_size < 0) {
-        kernel_size = load_image_targphys(kernel_filename, 0x40000000,
-                                          ram_size);
-        entry = 0x40000000;
-    }
-    if (kernel_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
-        exit(1);
-    }
-
-    env->pc = entry;
-}
-
-static QEMUMachine mcf5208evb_machine = {
-    .name = "mcf5208evb",
-    .desc = "MCF5206EVB",
-    .init = mcf5208evb_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mcf5208evb_machine_init(void)
-{
-    qemu_register_machine(&mcf5208evb_machine);
-}
-
-machine_init(mcf5208evb_machine_init);
index 8e60f09fbbf371ac1615681cb912556f37852d0b..0227bd852c4b77ae54d7dc04f61715b548f18c04 100644 (file)
@@ -5,9 +5,9 @@
  *
  * This code is licensed under the GPL
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "net/net.h"
-#include "mcf.h"
+#include "hw/mcf.h"
 /* For crc32 */
 #include <zlib.h>
 #include "exec/address-spaces.h"
diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c
deleted file mode 100644 (file)
index b213656..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * ColdFire Interrupt Controller emulation.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-#include "hw.h"
-#include "mcf.h"
-#include "exec/address-spaces.h"
-
-typedef struct {
-    MemoryRegion iomem;
-    uint64_t ipr;
-    uint64_t imr;
-    uint64_t ifr;
-    uint64_t enabled;
-    uint8_t icr[64];
-    M68kCPU *cpu;
-    int active_vector;
-} mcf_intc_state;
-
-static void mcf_intc_update(mcf_intc_state *s)
-{
-    uint64_t active;
-    int i;
-    int best;
-    int best_level;
-
-    active = (s->ipr | s->ifr) & s->enabled & ~s->imr;
-    best_level = 0;
-    best = 64;
-    if (active) {
-        for (i = 0; i < 64; i++) {
-            if ((active & 1) != 0 && s->icr[i] >= best_level) {
-                best_level = s->icr[i];
-                best = i;
-            }
-            active >>= 1;
-        }
-    }
-    s->active_vector = ((best == 64) ? 24 : (best + 64));
-    m68k_set_irq_level(s->cpu, best_level, s->active_vector);
-}
-
-static uint64_t mcf_intc_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    int offset;
-    mcf_intc_state *s = (mcf_intc_state *)opaque;
-    offset = addr & 0xff;
-    if (offset >= 0x40 && offset < 0x80) {
-        return s->icr[offset - 0x40];
-    }
-    switch (offset) {
-    case 0x00:
-        return (uint32_t)(s->ipr >> 32);
-    case 0x04:
-        return (uint32_t)s->ipr;
-    case 0x08:
-        return (uint32_t)(s->imr >> 32);
-    case 0x0c:
-        return (uint32_t)s->imr;
-    case 0x10:
-        return (uint32_t)(s->ifr >> 32);
-    case 0x14:
-        return (uint32_t)s->ifr;
-    case 0xe0: /* SWIACK.  */
-        return s->active_vector;
-    case 0xe1: case 0xe2: case 0xe3: case 0xe4:
-    case 0xe5: case 0xe6: case 0xe7:
-        /* LnIACK */
-        hw_error("mcf_intc_read: LnIACK not implemented\n");
-    default:
-        return 0;
-    }
-}
-
-static void mcf_intc_write(void *opaque, hwaddr addr,
-                           uint64_t val, unsigned size)
-{
-    int offset;
-    mcf_intc_state *s = (mcf_intc_state *)opaque;
-    offset = addr & 0xff;
-    if (offset >= 0x40 && offset < 0x80) {
-        int n = offset - 0x40;
-        s->icr[n] = val;
-        if (val == 0)
-            s->enabled &= ~(1ull << n);
-        else
-            s->enabled |= (1ull << n);
-        mcf_intc_update(s);
-        return;
-    }
-    switch (offset) {
-    case 0x00: case 0x04:
-        /* Ignore IPR writes.  */
-        return;
-    case 0x08:
-        s->imr = (s->imr & 0xffffffff) | ((uint64_t)val << 32);
-        break;
-    case 0x0c:
-        s->imr = (s->imr & 0xffffffff00000000ull) | (uint32_t)val;
-        break;
-    default:
-        hw_error("mcf_intc_write: Bad write offset %d\n", offset);
-        break;
-    }
-    mcf_intc_update(s);
-}
-
-static void mcf_intc_set_irq(void *opaque, int irq, int level)
-{
-    mcf_intc_state *s = (mcf_intc_state *)opaque;
-    if (irq >= 64)
-        return;
-    if (level)
-        s->ipr |= 1ull << irq;
-    else
-        s->ipr &= ~(1ull << irq);
-    mcf_intc_update(s);
-}
-
-static void mcf_intc_reset(mcf_intc_state *s)
-{
-    s->imr = ~0ull;
-    s->ipr = 0;
-    s->ifr = 0;
-    s->enabled = 0;
-    memset(s->icr, 0, 64);
-    s->active_vector = 24;
-}
-
-static const MemoryRegionOps mcf_intc_ops = {
-    .read = mcf_intc_read,
-    .write = mcf_intc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-qemu_irq *mcf_intc_init(MemoryRegion *sysmem,
-                        hwaddr base,
-                        M68kCPU *cpu)
-{
-    mcf_intc_state *s;
-
-    s = g_malloc0(sizeof(mcf_intc_state));
-    s->cpu = cpu;
-    mcf_intc_reset(s);
-
-    memory_region_init_io(&s->iomem, &mcf_intc_ops, s, "mcf", 0x100);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-
-    return qemu_allocate_irqs(mcf_intc_set_irq, s, 64);
-}
index c44344317a960035611e2938e8a19fe73f26cb1b..aacf0f05ed3a500040de2bba960d782408c356aa 100644 (file)
@@ -5,8 +5,8 @@
  *
  * This code is licensed under the GPL
  */
-#include "hw.h"
-#include "mcf.h"
+#include "hw/hw.h"
+#include "hw/mcf.h"
 #include "char/char.h"
 #include "exec/address-spaces.h"
 
index eb191f5e12c033ef2d2a45208de61aaf06deadeb..9b815d4b8fc6191dbc41951da07fd8886b940f0d 100644 (file)
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "sysemu/dma.h"
-#include "pci/msix.h"
+#include "hw/pci/msix.h"
 #include "qemu/iov.h"
-#include "scsi.h"
-#include "scsi-defs.h"
+#include "hw/scsi.h"
+#include "hw/scsi-defs.h"
 #include "trace.h"
 
-#include "mfi.h"
+#include "hw/mfi.h"
 
 #define MEGASAS_VERSION "1.70"
 #define MEGASAS_MAX_FRAMES 2048         /* Firmware limit at 65535 */
index 3028e651c8fcaa59f425f31b7b68f709186f508d..9e7f249941a7f6b6e003f61c9986851106ab765a 100644 (file)
@@ -1,10 +1,9 @@
-obj-y = petalogix_s3adsp1800_mmu.o
-obj-y += petalogix_ml605_mmu.o
-obj-y += microblaze_boot.o
 obj-y += xilinx_spi.o
-
-obj-y += microblaze_pic_cpu.o
 obj-y += xilinx_ethlite.o
-obj-$(CONFIG_FDT) += ../device_tree.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += petalogix_s3adsp1800_mmu.o
+obj-y += petalogix_ml605_mmu.o
+obj-y += boot.o
+obj-y += pic_cpu.o
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
new file mode 100644 (file)
index 0000000..e13b3e1
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Microblaze kernel loader
+ *
+ * Copyright (c) 2012 Peter Crosthwaite <peter.crosthwaite@petalogix.com>
+ * Copyright (c) 2012 PetaLogix
+ * Copyright (c) 2009 Edgar E. Iglesias.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/option.h"
+#include "qemu/config-file.h"
+#include "qemu-common.h"
+#include "sysemu/device_tree.h"
+#include "hw/loader.h"
+#include "elf.h"
+
+#include "hw/microblaze_boot.h"
+
+static struct
+{
+    void (*machine_cpu_reset)(MicroBlazeCPU *);
+    uint32_t bootstrap_pc;
+    uint32_t cmdline;
+    uint32_t fdt;
+} boot_info;
+
+static void main_cpu_reset(void *opaque)
+{
+    MicroBlazeCPU *cpu = opaque;
+    CPUMBState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+    env->regs[5] = boot_info.cmdline;
+    env->regs[7] = boot_info.fdt;
+    env->sregs[SR_PC] = boot_info.bootstrap_pc;
+    if (boot_info.machine_cpu_reset) {
+        boot_info.machine_cpu_reset(cpu);
+    }
+}
+
+static int microblaze_load_dtb(hwaddr addr,
+                                      uint32_t ramsize,
+                                      const char *kernel_cmdline,
+                                      const char *dtb_filename)
+{
+    int fdt_size;
+#ifdef CONFIG_FDT
+    void *fdt = NULL;
+    int r;
+
+    if (dtb_filename) {
+        fdt = load_device_tree(dtb_filename, &fdt_size);
+    }
+    if (!fdt) {
+        return 0;
+    }
+
+    if (kernel_cmdline) {
+        r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
+                                                        kernel_cmdline);
+        if (r < 0) {
+            fprintf(stderr, "couldn't set /chosen/bootargs\n");
+        }
+    }
+
+    cpu_physical_memory_write(addr, (void *)fdt, fdt_size);
+#else
+    /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
+       to the kernel.  */
+    if (dtb_filename) {
+        fdt_size = load_image_targphys(dtb_filename, addr, 0x10000);
+    }
+    if (kernel_cmdline) {
+        fprintf(stderr,
+                "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
+    }
+#endif
+    return fdt_size;
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return addr - 0x30000000LL;
+}
+
+void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
+                            uint32_t ramsize, const char *dtb_filename,
+                            void (*machine_cpu_reset)(MicroBlazeCPU *))
+{
+    QemuOpts *machine_opts;
+    const char *kernel_filename = NULL;
+    const char *kernel_cmdline = NULL;
+
+    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+    if (machine_opts) {
+        const char *dtb_arg;
+        kernel_filename = qemu_opt_get(machine_opts, "kernel");
+        kernel_cmdline = qemu_opt_get(machine_opts, "append");
+        dtb_arg = qemu_opt_get(machine_opts, "dtb");
+        if (dtb_arg) { /* Preference a -dtb argument */
+            dtb_filename = dtb_arg;
+        } else { /* default to pcbios dtb as passed by machine_init */
+            dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
+        }
+    }
+
+    boot_info.machine_cpu_reset = machine_cpu_reset;
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    if (kernel_filename) {
+        int kernel_size;
+        uint64_t entry, low, high;
+        uint32_t base32;
+        int big_endian = 0;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+        big_endian = 1;
+#endif
+
+        /* Boots a kernel elf binary.  */
+        kernel_size = load_elf(kernel_filename, NULL, NULL,
+                               &entry, &low, &high,
+                               big_endian, ELF_MACHINE, 0);
+        base32 = entry;
+        if (base32 == 0xc0000000) {
+            kernel_size = load_elf(kernel_filename, translate_kernel_address,
+                                   NULL, &entry, NULL, NULL,
+                                   big_endian, ELF_MACHINE, 0);
+        }
+        /* Always boot into physical ram.  */
+        boot_info.bootstrap_pc = ddr_base + (entry & 0x0fffffff);
+
+        /* If it wasn't an ELF image, try an u-boot image.  */
+        if (kernel_size < 0) {
+            hwaddr uentry, loadaddr;
+
+            kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0);
+            boot_info.bootstrap_pc = uentry;
+            high = (loadaddr + kernel_size + 3) & ~3;
+        }
+
+        /* Not an ELF image nor an u-boot image, try a RAW image.  */
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename, ddr_base,
+                                              ram_size);
+            boot_info.bootstrap_pc = ddr_base;
+            high = (ddr_base + kernel_size + 3) & ~3;
+        }
+
+        boot_info.cmdline = high + 4096;
+        if (kernel_cmdline && strlen(kernel_cmdline)) {
+            pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
+        }
+        /* Provide a device-tree.  */
+        boot_info.fdt = boot_info.cmdline + 4096;
+        microblaze_load_dtb(boot_info.fdt, ram_size, kernel_cmdline,
+                                                     dtb_filename);
+    }
+
+}
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
new file mode 100644 (file)
index 0000000..cfc0220
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Model of Petalogix linux reference design targeting Xilinx Spartan ml605
+ * board.
+ *
+ * Copyright (c) 2011 Michal Simek <monstr@monstr.eu>
+ * Copyright (c) 2011 PetaLogix
+ * Copyright (c) 2009 Edgar E. Iglesias.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "net/net.h"
+#include "hw/flash.h"
+#include "sysemu/sysemu.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/xilinx.h"
+#include "sysemu/blockdev.h"
+#include "hw/serial.h"
+#include "exec/address-spaces.h"
+#include "hw/ssi.h"
+
+#include "hw/microblaze_boot.h"
+#include "hw/microblaze_pic_cpu.h"
+
+#include "hw/stream.h"
+
+#define LMB_BRAM_SIZE  (128 * 1024)
+#define FLASH_SIZE     (32 * 1024 * 1024)
+
+#define BINARY_DEVICE_TREE_FILE "petalogix-ml605.dtb"
+
+#define NUM_SPI_FLASHES 4
+
+#define MEMORY_BASEADDR 0x50000000
+#define FLASH_BASEADDR 0x86000000
+#define INTC_BASEADDR 0x81800000
+#define TIMER_BASEADDR 0x83c00000
+#define UART16550_BASEADDR 0x83e00000
+#define AXIENET_BASEADDR 0x82780000
+#define AXIDMA_BASEADDR 0x84600000
+
+static void machine_cpu_reset(MicroBlazeCPU *cpu)
+{
+    CPUMBState *env = &cpu->env;
+
+    env->pvr.regs[10] = 0x0e000000; /* virtex 6 */
+    /* setup pvr to match kernel setting */
+    env->pvr.regs[5] |= PVR5_DCACHE_WRITEBACK_MASK;
+    env->pvr.regs[0] |= PVR0_USE_FPU_MASK | PVR0_ENDI;
+    env->pvr.regs[0] = (env->pvr.regs[0] & ~PVR0_VERSION_MASK) | (0x14 << 8);
+    env->pvr.regs[2] ^= PVR2_USE_FPU2_MASK;
+    env->pvr.regs[4] = 0xc56b8000;
+    env->pvr.regs[5] = 0xc56be000;
+}
+
+static void
+petalogix_ml605_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    MemoryRegion *address_space_mem = get_system_memory();
+    DeviceState *dev, *dma, *eth0;
+    MicroBlazeCPU *cpu;
+    SysBusDevice *busdev;
+    CPUMBState *env;
+    DriveInfo *dinfo;
+    int i;
+    hwaddr ddr_base = MEMORY_BASEADDR;
+    MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    qemu_irq irq[32], *cpu_irq;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "microblaze";
+    }
+    cpu = cpu_mb_init(cpu_model);
+    env = &cpu->env;
+
+    /* Attach emulated BRAM through the LMB.  */
+    memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram",
+                           LMB_BRAM_SIZE);
+    vmstate_register_ram_global(phys_lmb_bram);
+    memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram);
+
+    memory_region_init_ram(phys_ram, "petalogix_ml605.ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(address_space_mem, ddr_base, phys_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* 5th parameter 2 means bank-width
+     * 10th paremeter 0 means little-endian */
+    pflash_cfi01_register(FLASH_BASEADDR,
+                          NULL, "petalogix_ml605.flash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+                          FLASH_SIZE >> 16,
+                          2, 0x89, 0x18, 0x0000, 0x0, 0);
+
+
+    cpu_irq = microblaze_pic_init_cpu(env);
+    dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 4);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    serial_mm_init(address_space_mem, UART16550_BASEADDR + 0x1000, 2,
+                   irq[5], 115200, serial_hds[0], DEVICE_LITTLE_ENDIAN);
+
+    /* 2 timers at irq 2 @ 100 Mhz.  */
+    xilinx_timer_create(TIMER_BASEADDR, irq[2], 0, 100 * 1000000);
+
+    /* axi ethernet and dma initialization. */
+    qemu_check_nic_model(&nd_table[0], "xlnx.axi-ethernet");
+    eth0 = qdev_create(NULL, "xlnx.axi-ethernet");
+    dma = qdev_create(NULL, "xlnx.axi-dma");
+
+    /* FIXME: attach to the sysbus instead */
+    object_property_add_child(container_get(qdev_get_machine(), "/unattached"),
+                                  "xilinx-dma", OBJECT(dma), NULL);
+
+    xilinx_axiethernet_init(eth0, &nd_table[0], STREAM_SLAVE(dma),
+                                   0x82780000, irq[3], 0x1000, 0x1000);
+
+    xilinx_axidma_init(dma, STREAM_SLAVE(eth0), 0x84600000, irq[1], irq[0],
+                       100 * 1000000);
+
+    {
+        SSIBus *spi;
+
+        dev = qdev_create(NULL, "xlnx.xps-spi");
+        qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES);
+        qdev_init_nofail(dev);
+        busdev = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(busdev, 0, 0x40a00000);
+        sysbus_connect_irq(busdev, 0, irq[4]);
+
+        spi = (SSIBus *)qdev_get_child_bus(dev, "spi");
+
+        for (i = 0; i < NUM_SPI_FLASHES; i++) {
+            qemu_irq cs_line;
+
+            dev = ssi_create_slave_no_init(spi, "n25q128");
+            qdev_init_nofail(dev);
+            cs_line = qdev_get_gpio_in(dev, 0);
+            sysbus_connect_irq(busdev, i+1, cs_line);
+        }
+    }
+
+    microblaze_load_kernel(cpu, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
+                                                            machine_cpu_reset);
+
+}
+
+static QEMUMachine petalogix_ml605_machine = {
+    .name = "petalogix-ml605",
+    .desc = "PetaLogix linux refdesign for xilinx ml605 little endian",
+    .init = petalogix_ml605_init,
+    .is_default = 0,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void petalogix_ml605_machine_init(void)
+{
+    qemu_register_machine(&petalogix_ml605_machine);
+}
+
+machine_init(petalogix_ml605_machine_init);
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
new file mode 100644 (file)
index 0000000..2498362
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Model of Petalogix linux reference design targeting Xilinx Spartan 3ADSP-1800
+ * boards.
+ *
+ * Copyright (c) 2009 Edgar E. Iglesias.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "net/net.h"
+#include "hw/flash.h"
+#include "sysemu/sysemu.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/xilinx.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#include "hw/microblaze_boot.h"
+#include "hw/microblaze_pic_cpu.h"
+
+#define LMB_BRAM_SIZE  (128 * 1024)
+#define FLASH_SIZE     (16 * 1024 * 1024)
+
+#define BINARY_DEVICE_TREE_FILE "petalogix-s3adsp1800.dtb"
+
+#define MEMORY_BASEADDR 0x90000000
+#define FLASH_BASEADDR 0xa0000000
+#define INTC_BASEADDR 0x81800000
+#define TIMER_BASEADDR 0x83c00000
+#define UARTLITE_BASEADDR 0x84000000
+#define ETHLITE_BASEADDR 0x81000000
+
+static void machine_cpu_reset(MicroBlazeCPU *cpu)
+{
+    CPUMBState *env = &cpu->env;
+
+    env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family.  */
+}
+
+static void
+petalogix_s3adsp1800_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    DeviceState *dev;
+    MicroBlazeCPU *cpu;
+    CPUMBState *env;
+    DriveInfo *dinfo;
+    int i;
+    hwaddr ddr_base = MEMORY_BASEADDR;
+    MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    qemu_irq irq[32], *cpu_irq;
+    MemoryRegion *sysmem = get_system_memory();
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "microblaze";
+    }
+    cpu = cpu_mb_init(cpu_model);
+    env = &cpu->env;
+
+    /* Attach emulated BRAM through the LMB.  */
+    memory_region_init_ram(phys_lmb_bram,
+                           "petalogix_s3adsp1800.lmb_bram", LMB_BRAM_SIZE);
+    vmstate_register_ram_global(phys_lmb_bram);
+    memory_region_add_subregion(sysmem, 0x00000000, phys_lmb_bram);
+
+    memory_region_init_ram(phys_ram, "petalogix_s3adsp1800.ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(sysmem, ddr_base, phys_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    pflash_cfi01_register(FLASH_BASEADDR,
+                          NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+                          FLASH_SIZE >> 16,
+                          1, 0x89, 0x18, 0x0000, 0x0, 1);
+
+    cpu_irq = microblaze_pic_init_cpu(env);
+    dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 2);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    sysbus_create_simple("xlnx.xps-uartlite", UARTLITE_BASEADDR, irq[3]);
+    /* 2 timers at irq 2 @ 62 Mhz.  */
+    xilinx_timer_create(TIMER_BASEADDR, irq[0], 0, 62 * 1000000);
+    xilinx_ethlite_create(&nd_table[0], ETHLITE_BASEADDR, irq[1], 0, 0);
+
+    microblaze_load_kernel(cpu, ddr_base, ram_size,
+                    BINARY_DEVICE_TREE_FILE, machine_cpu_reset);
+}
+
+static QEMUMachine petalogix_s3adsp1800_machine = {
+    .name = "petalogix-s3adsp1800",
+    .desc = "PetaLogix linux refdesign for xilinx Spartan 3ADSP1800",
+    .init = petalogix_s3adsp1800_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void petalogix_s3adsp1800_machine_init(void)
+{
+    qemu_register_machine(&petalogix_s3adsp1800_machine);
+}
+
+machine_init(petalogix_s3adsp1800_machine_init);
diff --git a/hw/microblaze/pic_cpu.c b/hw/microblaze/pic_cpu.c
new file mode 100644 (file)
index 0000000..d4743ab
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * QEMU MicroBlaze CPU interrupt wrapper logic.
+ *
+ * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/microblaze_pic_cpu.h"
+
+#define D(x)
+
+static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    CPUMBState *env = (CPUMBState *)opaque;
+    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+
+    if (level)
+        cpu_interrupt(env, type);
+    else
+        cpu_reset_interrupt(env, type);
+}
+
+qemu_irq *microblaze_pic_init_cpu(CPUMBState *env)
+{
+    return qemu_allocate_irqs(microblaze_pic_cpu_handler, env, 2);
+}
diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c
deleted file mode 100644 (file)
index 3ec5c0f..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Microblaze kernel loader
- *
- * Copyright (c) 2012 Peter Crosthwaite <peter.crosthwaite@petalogix.com>
- * Copyright (c) 2012 PetaLogix
- * Copyright (c) 2009 Edgar E. Iglesias.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/option.h"
-#include "qemu/config-file.h"
-#include "qemu-common.h"
-#include "sysemu/device_tree.h"
-#include "loader.h"
-#include "elf.h"
-
-#include "microblaze_boot.h"
-
-static struct
-{
-    void (*machine_cpu_reset)(MicroBlazeCPU *);
-    uint32_t bootstrap_pc;
-    uint32_t cmdline;
-    uint32_t fdt;
-} boot_info;
-
-static void main_cpu_reset(void *opaque)
-{
-    MicroBlazeCPU *cpu = opaque;
-    CPUMBState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-    env->regs[5] = boot_info.cmdline;
-    env->regs[7] = boot_info.fdt;
-    env->sregs[SR_PC] = boot_info.bootstrap_pc;
-    if (boot_info.machine_cpu_reset) {
-        boot_info.machine_cpu_reset(cpu);
-    }
-}
-
-static int microblaze_load_dtb(hwaddr addr,
-                                      uint32_t ramsize,
-                                      const char *kernel_cmdline,
-                                      const char *dtb_filename)
-{
-    int fdt_size;
-#ifdef CONFIG_FDT
-    void *fdt = NULL;
-    int r;
-
-    if (dtb_filename) {
-        fdt = load_device_tree(dtb_filename, &fdt_size);
-    }
-    if (!fdt) {
-        return 0;
-    }
-
-    if (kernel_cmdline) {
-        r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
-                                                        kernel_cmdline);
-        if (r < 0) {
-            fprintf(stderr, "couldn't set /chosen/bootargs\n");
-        }
-    }
-
-    cpu_physical_memory_write(addr, (void *)fdt, fdt_size);
-#else
-    /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
-       to the kernel.  */
-    if (dtb_filename) {
-        fdt_size = load_image_targphys(dtb_filename, addr, 0x10000);
-    }
-    if (kernel_cmdline) {
-        fprintf(stderr,
-                "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
-    }
-#endif
-    return fdt_size;
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return addr - 0x30000000LL;
-}
-
-void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
-                            uint32_t ramsize, const char *dtb_filename,
-                            void (*machine_cpu_reset)(MicroBlazeCPU *))
-{
-    QemuOpts *machine_opts;
-    const char *kernel_filename = NULL;
-    const char *kernel_cmdline = NULL;
-
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        const char *dtb_arg;
-        kernel_filename = qemu_opt_get(machine_opts, "kernel");
-        kernel_cmdline = qemu_opt_get(machine_opts, "append");
-        dtb_arg = qemu_opt_get(machine_opts, "dtb");
-        if (dtb_arg) { /* Preference a -dtb argument */
-            dtb_filename = dtb_arg;
-        } else { /* default to pcbios dtb as passed by machine_init */
-            dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
-        }
-    }
-
-    boot_info.machine_cpu_reset = machine_cpu_reset;
-    qemu_register_reset(main_cpu_reset, cpu);
-
-    if (kernel_filename) {
-        int kernel_size;
-        uint64_t entry, low, high;
-        uint32_t base32;
-        int big_endian = 0;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-        big_endian = 1;
-#endif
-
-        /* Boots a kernel elf binary.  */
-        kernel_size = load_elf(kernel_filename, NULL, NULL,
-                               &entry, &low, &high,
-                               big_endian, ELF_MACHINE, 0);
-        base32 = entry;
-        if (base32 == 0xc0000000) {
-            kernel_size = load_elf(kernel_filename, translate_kernel_address,
-                                   NULL, &entry, NULL, NULL,
-                                   big_endian, ELF_MACHINE, 0);
-        }
-        /* Always boot into physical ram.  */
-        boot_info.bootstrap_pc = ddr_base + (entry & 0x0fffffff);
-
-        /* If it wasn't an ELF image, try an u-boot image.  */
-        if (kernel_size < 0) {
-            hwaddr uentry, loadaddr;
-
-            kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0);
-            boot_info.bootstrap_pc = uentry;
-            high = (loadaddr + kernel_size + 3) & ~3;
-        }
-
-        /* Not an ELF image nor an u-boot image, try a RAW image.  */
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename, ddr_base,
-                                              ram_size);
-            boot_info.bootstrap_pc = ddr_base;
-            high = (ddr_base + kernel_size + 3) & ~3;
-        }
-
-        boot_info.cmdline = high + 4096;
-        if (kernel_cmdline && strlen(kernel_cmdline)) {
-            pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
-        }
-        /* Provide a device-tree.  */
-        boot_info.fdt = boot_info.cmdline + 4096;
-        microblaze_load_dtb(boot_info.fdt, ram_size, kernel_cmdline,
-                                                     dtb_filename);
-    }
-
-}
index c1cf836b99397ba5cc36c338e8a0276572914637..b14ef2b99276192bd21899d265bedd5f56fa8db4 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __MICROBLAZE_BOOT__
 #define __MICROBLAZE_BOOT__
 
-#include "hw.h"
+#include "hw/hw.h"
 
 void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
                             uint32_t ramsize, const char *dtb_filename,
diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c
deleted file mode 100644 (file)
index ff36a52..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * QEMU MicroBlaze CPU interrupt wrapper logic.
- *
- * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw.h"
-#include "microblaze_pic_cpu.h"
-
-#define D(x)
-
-static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
-{
-    CPUMBState *env = (CPUMBState *)opaque;
-    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
-
-    if (level)
-        cpu_interrupt(env, type);
-    else
-        cpu_reset_interrupt(env, type);
-}
-
-qemu_irq *microblaze_pic_init_cpu(CPUMBState *env)
-{
-    return qemu_allocate_irqs(microblaze_pic_cpu_handler, env, 2);
-}
index d51d1ac9937f6364c30f595654cc4090551a2d1c..e08e9dca166e88ea237489697b735bcd8a6529b0 100644 (file)
@@ -21,8 +21,8 @@
  *   http://www.milkymist.org/socdoc/ac97.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "audio/audio.h"
 #include "qemu/error-report.h"
index ea4d210685d1f4330e27ae479500d71e1fe805cc..d922f6ffad19ff338e9389d576dbf8a66ec357ff 100644 (file)
@@ -21,8 +21,8 @@
  *   http://www.milkymist.org/socdoc/hpdmc.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/error-report.h"
 
index c8bd7e93dd159ab02c6733e93f00e2958130e518..ced1c5f54e528affa5a9c0f6b753c691e353611a 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef QEMU_HW_MILKYMIST_H
 #define QEMU_HW_MILKYMIST_H
 
-#include "qdev.h"
-#include "qdev-addr.h"
+#include "hw/qdev.h"
+#include "hw/qdev-addr.h"
 #include "net/net.h"
 
 static inline DeviceState *milkymist_uart_create(hwaddr base,
@@ -170,22 +170,6 @@ static inline DeviceState *milkymist_ac97_create(hwaddr base,
     return dev;
 }
 
-static inline DeviceState *milkymist_minimac_create(hwaddr base,
-        qemu_irq rx_irq, qemu_irq tx_irq)
-{
-    DeviceState *dev;
-
-    qemu_check_nic_model(&nd_table[0], "minimac");
-    dev = qdev_create(NULL, "milkymist-minimac");
-    qdev_set_nic_properties(dev, &nd_table[0]);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, rx_irq);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, tx_irq);
-
-    return dev;
-}
-
 static inline DeviceState *milkymist_minimac2_create(hwaddr base,
         hwaddr buffers_base, qemu_irq rx_irq, qemu_irq tx_irq)
 {
index 9d15309ab79b3ee86a332c7c5ec901d66dffa5b5..d5944bca69b11cdc78433e48129954dfaceaa8e4 100644 (file)
  *   http://www.milkymist.org/socdoc/memcard.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
 #include "qemu/error-report.h"
 #include "sysemu/blockdev.h"
-#include "sd.h"
+#include "hw/sd.h"
 
 enum {
     ENABLE_CMD_TX   = (1<<0),
index 9992dcceafaba596a9a599da860982dbaea020c6..c20ff904ecdfce74f3d28fa69c52ce140416c68c 100644 (file)
  *
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "net/net.h"
 #include "qemu/error-report.h"
-#include "qdev-addr.h"
+#include "hw/qdev-addr.h"
 
 #include <zlib.h>
 
index c347680ad74368debf93592fec01bfb2c3154f80..ad44b4db22f6b964745dd5058c63e0d35fc4a960 100644 (file)
@@ -22,8 +22,8 @@
  *
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/log.h"
 #include "qemu/error-report.h"
index 01660bebf0581927ee76943a8f5f613858d800a9..d911686de7aa2b1757b12871a60f5255861e8471 100644 (file)
  *   not available yet
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "ui/console.h"
-#include "hid.h"
+#include "hw/hid.h"
 #include "qemu/error-report.h"
 
 enum {
index e69ac6f047997751a814fa304a8fb00741941daa..e083a280c4355d6f8c96073c21743a7e4fce9628 100644 (file)
  *   http://www.milkymist.org/socdoc/sysctl.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "qemu/error-report.h"
 
 enum {
index 42de10aafdea0a793bb9cd10233f3bf6b2f8d695..b723a04cc9473f6b48cdb97aa5c61e7729fe484c 100644 (file)
@@ -24,8 +24,8 @@
  *
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/error-report.h"
 
index e73eb8476c0dfac7176c55b56145827a609d255f..ac6f5373add3ba4c9ee83dd0357caaafd6e075c8 100644 (file)
@@ -21,8 +21,8 @@
  *   http://www.milkymist.org/socdoc/uart.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "char/char.h"
 #include "qemu/error-report.h"
index 4d0a5dfb78dab213d8a6cf2fdef663109a9266f8..85ebb851bda36726faecee9d82a0bd4c7ea9df5f 100644 (file)
  *   http://www.milkymist.org/socdoc/vgafb.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "ui/console.h"
-#include "framebuffer.h"
+#include "hw/framebuffer.h"
 #include "ui/pixel_ops.h"
 #include "qemu/error-report.h"
 
 #define BITS 8
-#include "milkymist-vgafb_template.h"
+#include "hw/milkymist-vgafb_template.h"
 #define BITS 15
-#include "milkymist-vgafb_template.h"
+#include "hw/milkymist-vgafb_template.h"
 #define BITS 16
-#include "milkymist-vgafb_template.h"
+#include "hw/milkymist-vgafb_template.h"
 #define BITS 24
-#include "milkymist-vgafb_template.h"
+#include "hw/milkymist-vgafb_template.h"
 #define BITS 32
-#include "milkymist-vgafb_template.h"
+#include "hw/milkymist-vgafb_template.h"
 
 enum {
     R_CTRL = 0,
diff --git a/hw/milkymist.c b/hw/milkymist.c
deleted file mode 100644 (file)
index c04eb35..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- *  QEMU model for the Milkymist board.
- *
- *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "sysbus.h"
-#include "hw.h"
-#include "flash.h"
-#include "sysemu/sysemu.h"
-#include "devices.h"
-#include "boards.h"
-#include "loader.h"
-#include "elf.h"
-#include "sysemu/blockdev.h"
-#include "milkymist-hw.h"
-#include "lm32.h"
-#include "exec/address-spaces.h"
-
-#define BIOS_FILENAME    "mmone-bios.bin"
-#define BIOS_OFFSET      0x00860000
-#define BIOS_SIZE        (512*1024)
-#define KERNEL_LOAD_ADDR 0x40000000
-
-typedef struct {
-    LM32CPU *cpu;
-    hwaddr bootstrap_pc;
-    hwaddr flash_base;
-    hwaddr initrd_base;
-    size_t initrd_size;
-    hwaddr cmdline_base;
-} ResetInfo;
-
-static void cpu_irq_handler(void *opaque, int irq, int level)
-{
-    CPULM32State *env = opaque;
-
-    if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetInfo *reset_info = opaque;
-    CPULM32State *env = &reset_info->cpu->env;
-
-    cpu_reset(CPU(reset_info->cpu));
-
-    /* init defaults */
-    env->pc = reset_info->bootstrap_pc;
-    env->regs[R_R1] = reset_info->cmdline_base;
-    env->regs[R_R2] = reset_info->initrd_base;
-    env->regs[R_R3] = reset_info->initrd_base + reset_info->initrd_size;
-    env->eba = reset_info->flash_base;
-    env->deba = reset_info->flash_base;
-}
-
-static void
-milkymist_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    LM32CPU *cpu;
-    CPULM32State *env;
-    int kernel_size;
-    DriveInfo *dinfo;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *phys_sdram = g_new(MemoryRegion, 1);
-    qemu_irq irq[32], *cpu_irq;
-    int i;
-    char *bios_filename;
-    ResetInfo *reset_info;
-
-    /* memory map */
-    hwaddr flash_base   = 0x00000000;
-    size_t flash_sector_size        = 128 * 1024;
-    size_t flash_size               = 32 * 1024 * 1024;
-    hwaddr sdram_base   = 0x40000000;
-    size_t sdram_size               = 128 * 1024 * 1024;
-
-    hwaddr initrd_base  = sdram_base + 0x1002000;
-    hwaddr cmdline_base = sdram_base + 0x1000000;
-    size_t initrd_max = sdram_size - 0x1002000;
-
-    reset_info = g_malloc0(sizeof(ResetInfo));
-
-    if (cpu_model == NULL) {
-        cpu_model = "lm32-full";
-    }
-    cpu = cpu_lm32_init(cpu_model);
-    env = &cpu->env;
-    reset_info->cpu = cpu;
-
-    cpu_lm32_set_phys_msb_ignore(env, 1);
-
-    memory_region_init_ram(phys_sdram, "milkymist.sdram", sdram_size);
-    vmstate_register_ram_global(phys_sdram);
-    memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    /* Numonyx JS28F256J3F105 */
-    pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size,
-                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
-                          flash_size / flash_sector_size, 2,
-                          0x00, 0x89, 0x00, 0x1d, 1);
-
-    /* create irq lines */
-    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
-    env->pic_state = lm32_pic_init(*cpu_irq);
-    for (i = 0; i < 32; i++) {
-        irq[i] = qdev_get_gpio_in(env->pic_state, i);
-    }
-
-    /* load bios rom */
-    if (bios_name == NULL) {
-        bios_name = BIOS_FILENAME;
-    }
-    bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-
-    if (bios_filename) {
-        load_image_targphys(bios_filename, BIOS_OFFSET, BIOS_SIZE);
-    }
-
-    reset_info->bootstrap_pc = BIOS_OFFSET;
-
-    /* if no kernel is given no valid bios rom is a fatal error */
-    if (!kernel_filename && !dinfo && !bios_filename) {
-        fprintf(stderr, "qemu: could not load Milkymist One bios '%s'\n",
-                bios_name);
-        exit(1);
-    }
-
-    milkymist_uart_create(0x60000000, irq[0]);
-    milkymist_sysctl_create(0x60001000, irq[1], irq[2], irq[3],
-            80000000, 0x10014d31, 0x0000041f, 0x00000001);
-    milkymist_hpdmc_create(0x60002000);
-    milkymist_vgafb_create(0x60003000, 0x40000000, 0x0fffffff);
-    milkymist_memcard_create(0x60004000);
-    milkymist_ac97_create(0x60005000, irq[4], irq[5], irq[6], irq[7]);
-    milkymist_pfpu_create(0x60006000, irq[8]);
-    milkymist_tmu2_create(0x60007000, irq[9]);
-    milkymist_minimac2_create(0x60008000, 0x30000000, irq[10], irq[11]);
-    milkymist_softusb_create(0x6000f000, irq[15],
-            0x20000000, 0x1000, 0x20020000, 0x2000);
-
-    /* make sure juart isn't the first chardev */
-    env->juart_state = lm32_juart_init();
-
-    if (kernel_filename) {
-        uint64_t entry;
-
-        /* Boots a kernel elf binary.  */
-        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
-                               1, ELF_MACHINE, 0);
-        reset_info->bootstrap_pc = entry;
-
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename, sdram_base,
-                                              sdram_size);
-            reset_info->bootstrap_pc = sdram_base;
-        }
-
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-    }
-
-    if (kernel_cmdline && strlen(kernel_cmdline)) {
-        pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE,
-                kernel_cmdline);
-        reset_info->cmdline_base = (uint32_t)cmdline_base;
-    }
-
-    if (initrd_filename) {
-        size_t initrd_size;
-        initrd_size = load_image_targphys(initrd_filename, initrd_base,
-                initrd_max);
-        reset_info->initrd_base = (uint32_t)initrd_base;
-        reset_info->initrd_size = (uint32_t)initrd_size;
-    }
-
-    qemu_register_reset(main_cpu_reset, reset_info);
-}
-
-static QEMUMachine milkymist_machine = {
-    .name = "milkymist",
-    .desc = "Milkymist One",
-    .init = milkymist_init,
-    .is_default = 0,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void milkymist_machine_init(void)
-{
-    qemu_register_machine(&milkymist_machine);
-}
-
-machine_init(milkymist_machine_init);
index 29a5d0db049a88e90b250ee7b757d055d104e0b7..1e3bca1c373785a3bf5542eb99a2e261e5a87080 100644 (file)
@@ -1,6 +1,8 @@
-obj-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
-obj-y += mips_addr.o mips_timer.o mips_int.o
 obj-y += gt64xxx.o mc146818rtc.o
-obj-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
+obj-$(CONFIG_FULONG) += bonito.o vt82c686.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
+obj-y += addr.o cputimer.o mips_int.o
+obj-$(CONFIG_FULONG) += mips_fulong2e.o
diff --git a/hw/mips/addr.c b/hw/mips/addr.c
new file mode 100644 (file)
index 0000000..cddc25c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * QEMU MIPS address translation support
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/mips_cpudevs.h"
+
+uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
+{
+    return addr & 0x7fffffffll;
+}
+
+uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr)
+{
+    return addr | ~0x7fffffffll;
+}
diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
new file mode 100644 (file)
index 0000000..9ad13f3
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * QEMU MIPS timer support
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/mips_cpudevs.h"
+#include "qemu/timer.h"
+
+#define TIMER_FREQ     100 * 1000 * 1000
+
+/* XXX: do not use a global */
+uint32_t cpu_mips_get_random (CPUMIPSState *env)
+{
+    static uint32_t lfsr = 1;
+    static uint32_t prev_idx = 0;
+    uint32_t idx;
+    /* Don't return same value twice, so get another value */
+    do {
+        lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u);
+        idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
+    } while (idx == prev_idx);
+    prev_idx = idx;
+    return idx;
+}
+
+/* MIPS R4K timer */
+static void cpu_mips_timer_update(CPUMIPSState *env)
+{
+    uint64_t now, next;
+    uint32_t wait;
+
+    now = qemu_get_clock_ns(vm_clock);
+    wait = env->CP0_Compare - env->CP0_Count -
+           (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
+    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
+    qemu_mod_timer(env->timer, next);
+}
+
+/* Expire the timer.  */
+static void cpu_mips_timer_expire(CPUMIPSState *env)
+{
+    cpu_mips_timer_update(env);
+    if (env->insn_flags & ISA_MIPS32R2) {
+        env->CP0_Cause |= 1 << CP0Ca_TI;
+    }
+    qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
+}
+
+uint32_t cpu_mips_get_count (CPUMIPSState *env)
+{
+    if (env->CP0_Cause & (1 << CP0Ca_DC)) {
+        return env->CP0_Count;
+    } else {
+        uint64_t now;
+
+        now = qemu_get_clock_ns(vm_clock);
+        if (qemu_timer_pending(env->timer)
+            && qemu_timer_expired(env->timer, now)) {
+            /* The timer has already expired.  */
+            cpu_mips_timer_expire(env);
+        }
+
+        return env->CP0_Count +
+            (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
+    }
+}
+
+void cpu_mips_store_count (CPUMIPSState *env, uint32_t count)
+{
+    if (env->CP0_Cause & (1 << CP0Ca_DC))
+        env->CP0_Count = count;
+    else {
+        /* Store new count register */
+        env->CP0_Count =
+            count - (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
+                                       TIMER_FREQ, get_ticks_per_sec());
+        /* Update timer timer */
+        cpu_mips_timer_update(env);
+    }
+}
+
+void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value)
+{
+    env->CP0_Compare = value;
+    if (!(env->CP0_Cause & (1 << CP0Ca_DC)))
+        cpu_mips_timer_update(env);
+    if (env->insn_flags & ISA_MIPS32R2)
+        env->CP0_Cause &= ~(1 << CP0Ca_TI);
+    qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
+}
+
+void cpu_mips_start_count(CPUMIPSState *env)
+{
+    cpu_mips_store_count(env, env->CP0_Count);
+}
+
+void cpu_mips_stop_count(CPUMIPSState *env)
+{
+    /* Store the current value */
+    env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
+                                         TIMER_FREQ, get_ticks_per_sec());
+}
+
+static void mips_timer_cb (void *opaque)
+{
+    CPUMIPSState *env;
+
+    env = opaque;
+#if 0
+    qemu_log("%s\n", __func__);
+#endif
+
+    if (env->CP0_Cause & (1 << CP0Ca_DC))
+        return;
+
+    /* ??? This callback should occur when the counter is exactly equal to
+       the comparator value.  Offset the count by one to avoid immediately
+       retriggering the callback before any virtual time has passed.  */
+    env->CP0_Count++;
+    cpu_mips_timer_expire(env);
+    env->CP0_Count--;
+}
+
+void cpu_mips_clock_init (CPUMIPSState *env)
+{
+    env->timer = qemu_new_timer_ns(vm_clock, &mips_timer_cb, env);
+    env->CP0_Compare = 0;
+    cpu_mips_store_count(env, 1);
+}
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
new file mode 100644 (file)
index 0000000..766aa9d
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * QEMU fulong 2e mini pc support
+ *
+ * Copyright (c) 2008 yajin (yajin@vm-kernel.org)
+ * Copyright (c) 2009 chenming (chenming@rdc.faw.com.cn)
+ * Copyright (c) 2010 Huacai Chen (zltjiangshi@gmail.com)
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+/*
+ * Fulong 2e mini pc is based on ICT/ST Loongson 2e CPU (MIPS III like, 800MHz)
+ * http://www.linux-mips.org/wiki/Fulong
+ *
+ * Loongson 2e user manual:
+ * http://www.loongsondeveloper.com/doc/Loongson2EUserGuide.pdf
+ */
+
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/fdc.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "hw/smbus.h"
+#include "block/block.h"
+#include "hw/flash.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pci/pci.h"
+#include "char/char.h"
+#include "sysemu/sysemu.h"
+#include "audio/audio.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+#include "hw/mips-bios.h"
+#include "hw/ide.h"
+#include "elf.h"
+#include "hw/vt82c686.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define DEBUG_FULONG2E_INIT
+
+#define ENVP_ADDR       0x80002000l
+#define ENVP_NB_ENTRIES                16
+#define ENVP_ENTRY_SIZE                256
+
+#define MAX_IDE_BUS 2
+
+/*
+ * PMON is not part of qemu and released with BSD license, anyone
+ * who want to build a pmon binary please first git-clone the source
+ * from the git repository at:
+ * http://www.loongson.cn/support/git/pmon
+ * Then follow the "Compile Guide" available at:
+ * http://dev.lemote.com/code/pmon
+ *
+ * Notes:
+ * 1, don't use the source at http://dev.lemote.com/http_git/pmon.git
+ * 2, use "Bonito2edev" to replace "dir_corresponding_to_your_target_hardware"
+ * in the "Compile Guide".
+ */
+#define FULONG_BIOSNAME "pmon_fulong2e.bin"
+
+/* PCI SLOT in fulong 2e */
+#define FULONG2E_VIA_SLOT        5
+#define FULONG2E_ATI_SLOT        6
+#define FULONG2E_RTL8139_SLOT    7
+
+static ISADevice *pit;
+
+static struct _loaderparams {
+    int ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+} loaderparams;
+
+static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
+                                        const char *string, ...)
+{
+    va_list ap;
+    int32_t table_addr;
+
+    if (index >= ENVP_NB_ENTRIES)
+        return;
+
+    if (string == NULL) {
+        prom_buf[index] = 0;
+        return;
+    }
+
+    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
+    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
+
+    va_start(ap, string);
+    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
+    va_end(ap);
+}
+
+static int64_t load_kernel (CPUMIPSState *env)
+{
+    int64_t kernel_entry, kernel_low, kernel_high;
+    int index = 0;
+    long initrd_size;
+    ram_addr_t initrd_offset;
+    uint32_t *prom_buf;
+    long prom_size;
+
+    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
+                 (uint64_t *)&kernel_high, 0, ELF_MACHINE, 1) < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                loaderparams.kernel_filename);
+        exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (loaderparams.initrd_filename) {
+        initrd_size = get_image_size (loaderparams.initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        loaderparams.initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image_targphys(loaderparams.initrd_filename,
+                                     initrd_offset, ram_size - initrd_offset);
+        }
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    loaderparams.initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* Setup prom parameters. */
+    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
+    prom_buf = g_malloc(prom_size);
+
+    prom_set(prom_buf, index++, "%s", loaderparams.kernel_filename);
+    if (initrd_size > 0) {
+        prom_set(prom_buf, index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
+                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
+                 loaderparams.kernel_cmdline);
+    } else {
+        prom_set(prom_buf, index++, "%s", loaderparams.kernel_cmdline);
+    }
+
+    /* Setup minimum environment variables */
+    prom_set(prom_buf, index++, "busclock=33000000");
+    prom_set(prom_buf, index++, "cpuclock=100000000");
+    prom_set(prom_buf, index++, "memsize=%i", loaderparams.ram_size/1024/1024);
+    prom_set(prom_buf, index++, "modetty0=38400n8r");
+    prom_set(prom_buf, index++, NULL);
+
+    rom_add_blob_fixed("prom", prom_buf, prom_size,
+                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
+
+    return kernel_entry;
+}
+
+static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_addr)
+{
+    uint32_t *p;
+
+    /* Small bootloader */
+    p = (uint32_t *) base;
+
+    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+
+    /* Second part of the bootloader */
+    p = (uint32_t *) (base + 0x040);
+
+    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
+    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
+    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
+    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
+    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));      /* lui a3, high(env->ram_size) */
+    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));   /* ori a3, a3, low(env->ram_size) */
+    stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
+    stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
+    stl_raw(p++, 0x03e00008);                                      /* jr ra */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+}
+
+
+static void main_cpu_reset(void *opaque)
+{
+    MIPSCPU *cpu = opaque;
+    CPUMIPSState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+    /* TODO: 2E reset stuff */
+    if (loaderparams.kernel_filename) {
+        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
+    }
+}
+
+uint8_t eeprom_spd[0x80] = {
+    0x80,0x08,0x07,0x0d,0x09,0x02,0x40,0x00,0x04,0x70,
+    0x70,0x00,0x82,0x10,0x00,0x01,0x0e,0x04,0x0c,0x01,
+    0x02,0x20,0x80,0x75,0x70,0x00,0x00,0x50,0x3c,0x50,
+    0x2d,0x20,0xb0,0xb0,0x50,0x50,0x00,0x00,0x00,0x00,
+    0x00,0x41,0x48,0x3c,0x32,0x75,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x9c,0x7b,0x07,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x48,0x42,0x35,0x34,0x41,0x32,
+    0x35,0x36,0x38,0x4b,0x4e,0x2d,0x41,0x37,0x35,0x42,
+    0x20,0x30,0x20
+};
+
+/* Audio support */
+static void audio_init (PCIBus *pci_bus)
+{
+    vt82c686b_ac97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 5));
+    vt82c686b_mc97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 6));
+}
+
+/* Network support */
+static void network_init (void)
+{
+    int i;
+
+    for(i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+        const char *default_devaddr = NULL;
+
+        if (i == 0 && (!nd->model || strcmp(nd->model, "rtl8139") == 0)) {
+            /* The fulong board has a RTL8139 card using PCI SLOT 7 */
+            default_devaddr = "07";
+        }
+
+        pci_nic_init_nofail(nd, "rtl8139", default_devaddr);
+    }
+}
+
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+    CPUMIPSState *env = cpu_single_env;
+
+    if (env && level) {
+        cpu_exit(env);
+    }
+}
+
+static void mips_fulong2e_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
+    long bios_size;
+    int64_t kernel_entry;
+    qemu_irq *i8259;
+    qemu_irq *cpu_exit_irq;
+    PCIBus *pci_bus;
+    ISABus *isa_bus;
+    i2c_bus *smbus;
+    int i;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "Loongson-2E";
+    }
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    /* fulong 2e has 256M ram. */
+    ram_size = 256 * 1024 * 1024;
+
+    /* fulong 2e has a 1M flash.Winbond W39L040AP70Z */
+    bios_size = 1024 * 1024;
+
+    /* allocate RAM */
+    memory_region_init_ram(ram, "fulong2e.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_init_ram(bios, "fulong2e.bios", bios_size);
+    vmstate_register_ram_global(bios);
+    memory_region_set_readonly(bios, true);
+
+    memory_region_add_subregion(address_space_mem, 0, ram);
+    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
+
+    /* We do not support flash operation, just loading pmon.bin as raw BIOS.
+     * Please use -L to set the BIOS path and -bios to set bios name. */
+
+    if (kernel_filename) {
+        loaderparams.ram_size = ram_size;
+        loaderparams.kernel_filename = kernel_filename;
+        loaderparams.kernel_cmdline = kernel_cmdline;
+        loaderparams.initrd_filename = initrd_filename;
+        kernel_entry = load_kernel (env);
+        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
+    } else {
+        if (bios_name == NULL) {
+                bios_name = FULONG_BIOSNAME;
+        }
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (filename) {
+            bios_size = load_image_targphys(filename, 0x1fc00000LL,
+                                            BIOS_SIZE);
+            g_free(filename);
+        } else {
+            bios_size = -1;
+        }
+
+        if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
+            fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", bios_name);
+            exit(1);
+        }
+    }
+
+    /* Init internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+
+    /* North bridge, Bonito --> IP2 */
+    pci_bus = bonito_init((qemu_irq *)&(env->irq[2]));
+
+    /* South bridge */
+    ide_drive_get(hd, MAX_IDE_BUS);
+
+    isa_bus = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0));
+    if (!isa_bus) {
+        fprintf(stderr, "vt82c686b_init error\n");
+        exit(1);
+    }
+
+    /* Interrupt controller */
+    /* The 8259 -> IP5  */
+    i8259 = i8259_init(isa_bus, env->irq[5]);
+    isa_bus_irqs(isa_bus, i8259);
+
+    vt82c686b_ide_init(pci_bus, hd, PCI_DEVFN(FULONG2E_VIA_SLOT, 1));
+    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 2),
+                      "vt82c686b-usb-uhci");
+    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 3),
+                      "vt82c686b-usb-uhci");
+
+    smbus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 4),
+                              0xeee1, NULL);
+    /* TODO: Populate SPD eeprom data.  */
+    smbus_eeprom_init(smbus, 1, eeprom_spd, sizeof(eeprom_spd));
+
+    /* init other devices */
+    pit = pit_init(isa_bus, 0x40, 0, NULL);
+    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+    DMA_init(0, cpu_exit_irq);
+
+    /* Super I/O */
+    isa_create_simple(isa_bus, "i8042");
+
+    rtc_init(isa_bus, 2000, NULL);
+
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_isa_init(isa_bus, i, serial_hds[i]);
+        }
+    }
+
+    if (parallel_hds[0]) {
+        parallel_init(isa_bus, 0, parallel_hds[0]);
+    }
+
+    /* Sound card */
+    audio_init(pci_bus);
+    /* Network card */
+    network_init();
+}
+
+static QEMUMachine mips_fulong2e_machine = {
+    .name = "fulong2e",
+    .desc = "Fulong 2e mini pc",
+    .init = mips_fulong2e_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mips_fulong2e_machine_init(void)
+{
+    qemu_register_machine(&mips_fulong2e_machine);
+}
+
+machine_init(mips_fulong2e_machine_init);
diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
new file mode 100644 (file)
index 0000000..ddd3b1b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * QEMU MIPS interrupt support
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/mips_cpudevs.h"
+#include "cpu.h"
+
+static void cpu_mips_irq_request(void *opaque, int irq, int level)
+{
+    CPUMIPSState *env = (CPUMIPSState *)opaque;
+
+    if (irq < 0 || irq > 7)
+        return;
+
+    if (level) {
+        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
+    } else {
+        env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
+    }
+
+    if (env->CP0_Cause & CP0Ca_IP_mask) {
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+void cpu_mips_irq_init_cpu(CPUMIPSState *env)
+{
+    qemu_irq *qi;
+    int i;
+
+    qi = qemu_allocate_irqs(cpu_mips_irq_request, env, 8);
+    for (i = 0; i < 8; i++) {
+        env->irq[i] = qi[i];
+    }
+}
+
+void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level)
+{
+    if (irq < 0 || irq > 2) {
+        return;
+    }
+
+    qemu_set_irq(env->irq[irq], level);
+}
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
new file mode 100644 (file)
index 0000000..daeb985
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * QEMU MIPS Jazz support
+ *
+ * Copyright (c) 2007-2008 Hervé Poussineau
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/isa.h"
+#include "hw/fdc.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/arch_init.h"
+#include "hw/boards.h"
+#include "net/net.h"
+#include "hw/esp.h"
+#include "hw/mips-bios.h"
+#include "hw/loader.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "hw/pcspk.h"
+#include "sysemu/blockdev.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+enum jazz_model_e
+{
+    JAZZ_MAGNUM,
+    JAZZ_PICA61,
+};
+
+static void main_cpu_reset(void *opaque)
+{
+    MIPSCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return cpu_inw(0x71);
+}
+
+static void rtc_write(void *opaque, hwaddr addr,
+                      uint64_t val, unsigned size)
+{
+    cpu_outw(0x71, val & 0xff);
+}
+
+static const MemoryRegionOps rtc_ops = {
+    .read = rtc_read,
+    .write = rtc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static uint64_t dma_dummy_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    /* Nothing to do. That is only to ensure that
+     * the current DMA acknowledge cycle is completed. */
+    return 0xff;
+}
+
+static void dma_dummy_write(void *opaque, hwaddr addr,
+                            uint64_t val, unsigned size)
+{
+    /* Nothing to do. That is only to ensure that
+     * the current DMA acknowledge cycle is completed. */
+}
+
+static const MemoryRegionOps dma_dummy_ops = {
+    .read = dma_dummy_read,
+    .write = dma_dummy_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+#define MAGNUM_BIOS_SIZE_MAX 0x7e000
+#define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
+
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+    CPUMIPSState *env = cpu_single_env;
+
+    if (env && level) {
+        cpu_exit(env);
+    }
+}
+
+static void mips_jazz_init(MemoryRegion *address_space,
+                           MemoryRegion *address_space_io,
+                           ram_addr_t ram_size,
+                           const char *cpu_model,
+                           enum jazz_model_e jazz_model)
+{
+    char *filename;
+    int bios_size, n;
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+    qemu_irq *rc4030, *i8259;
+    rc4030_dma *dmas;
+    void* rc4030_opaque;
+    MemoryRegion *rtc = g_new(MemoryRegion, 1);
+    MemoryRegion *i8042 = g_new(MemoryRegion, 1);
+    MemoryRegion *dma_dummy = g_new(MemoryRegion, 1);
+    NICInfo *nd;
+    DeviceState *dev;
+    SysBusDevice *sysbus;
+    ISABus *isa_bus;
+    ISADevice *pit;
+    DriveInfo *fds[MAX_FD];
+    qemu_irq esp_reset, dma_enable;
+    qemu_irq *cpu_exit_irq;
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
+    MemoryRegion *bios2 = g_new(MemoryRegion, 1);
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "R4000";
+#else
+        /* FIXME: All wrong, this maybe should be R3000 for the older JAZZs. */
+        cpu_model = "24Kf";
+#endif
+    }
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    /* allocate RAM */
+    memory_region_init_ram(ram, "mips_jazz.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space, 0, ram);
+
+    memory_region_init_ram(bios, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
+    vmstate_register_ram_global(bios);
+    memory_region_set_readonly(bios, true);
+    memory_region_init_alias(bios2, "mips_jazz.bios", bios,
+                             0, MAGNUM_BIOS_SIZE);
+    memory_region_add_subregion(address_space, 0x1fc00000LL, bios);
+    memory_region_add_subregion(address_space, 0xfff00000LL, bios2);
+
+    /* load the BIOS image. */
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (filename) {
+        bios_size = load_image_targphys(filename, 0xfff00000LL,
+                                        MAGNUM_BIOS_SIZE);
+        g_free(filename);
+    } else {
+        bios_size = -1;
+    }
+    if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) {
+        fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n",
+                bios_name);
+        exit(1);
+    }
+
+    /* Init CPU internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+
+    /* Chipset */
+    rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas,
+                                address_space);
+    memory_region_init_io(dma_dummy, &dma_dummy_ops, NULL, "dummy_dma", 0x1000);
+    memory_region_add_subregion(address_space, 0x8000d000, dma_dummy);
+
+    /* ISA devices */
+    isa_bus = isa_bus_new(NULL, address_space_io);
+    i8259 = i8259_init(isa_bus, env->irq[4]);
+    isa_bus_irqs(isa_bus, i8259);
+    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+    DMA_init(0, cpu_exit_irq);
+    pit = pit_init(isa_bus, 0x40, 0, NULL);
+    pcspk_init(isa_bus, pit);
+
+    /* ISA IO space at 0x90000000 */
+    isa_mmio_init(0x90000000, 0x01000000);
+    isa_mem_base = 0x11000000;
+
+    /* Video card */
+    switch (jazz_model) {
+    case JAZZ_MAGNUM:
+        dev = qdev_create(NULL, "sysbus-g364");
+        qdev_init_nofail(dev);
+        sysbus = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(sysbus, 0, 0x60080000);
+        sysbus_mmio_map(sysbus, 1, 0x40000000);
+        sysbus_connect_irq(sysbus, 0, rc4030[3]);
+        {
+            /* Simple ROM, so user doesn't have to provide one */
+            MemoryRegion *rom_mr = g_new(MemoryRegion, 1);
+            memory_region_init_ram(rom_mr, "g364fb.rom", 0x80000);
+            vmstate_register_ram_global(rom_mr);
+            memory_region_set_readonly(rom_mr, true);
+            uint8_t *rom = memory_region_get_ram_ptr(rom_mr);
+            memory_region_add_subregion(address_space, 0x60000000, rom_mr);
+            rom[0] = 0x10; /* Mips G364 */
+        }
+        break;
+    case JAZZ_PICA61:
+        isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory());
+        break;
+    default:
+        break;
+    }
+
+    /* Network controller */
+    for (n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+        if (!nd->model)
+            nd->model = g_strdup("dp83932");
+        if (strcmp(nd->model, "dp83932") == 0) {
+            dp83932_init(nd, 0x80001000, 2, get_system_memory(), rc4030[4],
+                         rc4030_opaque, rc4030_dma_memory_rw);
+            break;
+        } else if (is_help_option(nd->model)) {
+            fprintf(stderr, "qemu: Supported NICs: dp83932\n");
+            exit(1);
+        } else {
+            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
+            exit(1);
+        }
+    }
+
+    /* SCSI adapter */
+    esp_init(0x80002000, 0,
+             rc4030_dma_read, rc4030_dma_write, dmas[0],
+             rc4030[5], &esp_reset, &dma_enable);
+
+    /* Floppy */
+    if (drive_get_max_bus(IF_FLOPPY) >= MAX_FD) {
+        fprintf(stderr, "qemu: too many floppy drives\n");
+        exit(1);
+    }
+    for (n = 0; n < MAX_FD; n++) {
+        fds[n] = drive_get(IF_FLOPPY, 0, n);
+    }
+    fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
+
+    /* Real time clock */
+    rtc_init(isa_bus, 1980, NULL);
+    memory_region_init_io(rtc, &rtc_ops, NULL, "rtc", 0x1000);
+    memory_region_add_subregion(address_space, 0x80004000, rtc);
+
+    /* Keyboard (i8042) */
+    i8042_mm_init(rc4030[6], rc4030[7], i8042, 0x1000, 0x1);
+    memory_region_add_subregion(address_space, 0x80005000, i8042);
+
+    /* Serial ports */
+    if (serial_hds[0]) {
+        serial_mm_init(address_space, 0x80006000, 0, rc4030[8], 8000000/16,
+                       serial_hds[0], DEVICE_NATIVE_ENDIAN);
+    }
+    if (serial_hds[1]) {
+        serial_mm_init(address_space, 0x80007000, 0, rc4030[9], 8000000/16,
+                       serial_hds[1], DEVICE_NATIVE_ENDIAN);
+    }
+
+    /* Parallel port */
+    if (parallel_hds[0])
+        parallel_mm_init(address_space, 0x80008000, 0, rc4030[0],
+                         parallel_hds[0]);
+
+    /* Sound card */
+    /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
+    audio_init(isa_bus, NULL);
+
+    /* NVRAM */
+    dev = qdev_create(NULL, "ds1225y");
+    qdev_init_nofail(dev);
+    sysbus = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(sysbus, 0, 0x80009000);
+
+    /* LED indicator */
+    sysbus_create_simple("jazz-led", 0x8000f000, NULL);
+}
+
+static
+void mips_magnum_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+        mips_jazz_init(get_system_memory(), get_system_io(),
+                       ram_size, cpu_model, JAZZ_MAGNUM);
+}
+
+static
+void mips_pica61_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    mips_jazz_init(get_system_memory(), get_system_io(),
+                   ram_size, cpu_model, JAZZ_PICA61);
+}
+
+static QEMUMachine mips_magnum_machine = {
+    .name = "magnum",
+    .desc = "MIPS Magnum",
+    .init = mips_magnum_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine mips_pica61_machine = {
+    .name = "pica61",
+    .desc = "Acer Pica 61",
+    .init = mips_pica61_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mips_jazz_machine_init(void)
+{
+    qemu_register_machine(&mips_magnum_machine);
+    qemu_register_machine(&mips_pica61_machine);
+}
+
+machine_init(mips_jazz_machine_init);
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
new file mode 100644 (file)
index 0000000..9a67dce
--- /dev/null
@@ -0,0 +1,1037 @@
+/*
+ * QEMU Malta board support
+ *
+ * Copyright (c) 2006 Aurelien Jarno
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/fdc.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "hw/smbus.h"
+#include "block/block.h"
+#include "hw/flash.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pci/pci.h"
+#include "char/char.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/arch_init.h"
+#include "hw/boards.h"
+#include "qemu/log.h"
+#include "hw/mips-bios.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+#include "hw/sysbus.h"             /* SysBusDevice */
+
+//#define DEBUG_BOARD_INIT
+
+#define ENVP_ADDR              0x80002000l
+#define ENVP_NB_ENTRIES                16
+#define ENVP_ENTRY_SIZE                256
+
+/* Hardware addresses */
+#define FLASH_ADDRESS 0x1e000000ULL
+#define FPGA_ADDRESS  0x1f000000ULL
+#define RESET_ADDRESS 0x1fc00000ULL
+
+#define FLASH_SIZE    0x400000
+
+#define MAX_IDE_BUS 2
+
+typedef struct {
+    MemoryRegion iomem;
+    MemoryRegion iomem_lo; /* 0 - 0x900 */
+    MemoryRegion iomem_hi; /* 0xa00 - 0x100000 */
+    uint32_t leds;
+    uint32_t brk;
+    uint32_t gpout;
+    uint32_t i2cin;
+    uint32_t i2coe;
+    uint32_t i2cout;
+    uint32_t i2csel;
+    CharDriverState *display;
+    char display_text[9];
+    SerialState *uart;
+} MaltaFPGAState;
+
+typedef struct {
+    SysBusDevice busdev;
+    qemu_irq *i8259;
+} MaltaState;
+
+static ISADevice *pit;
+
+static struct _loaderparams {
+    int ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+} loaderparams;
+
+/* Malta FPGA */
+static void malta_fpga_update_display(void *opaque)
+{
+    char leds_text[9];
+    int i;
+    MaltaFPGAState *s = opaque;
+
+    for (i = 7 ; i >= 0 ; i--) {
+        if (s->leds & (1 << i))
+            leds_text[i] = '#';
+        else
+            leds_text[i] = ' ';
+    }
+    leds_text[8] = '\0';
+
+    qemu_chr_fe_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
+    qemu_chr_fe_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
+}
+
+/*
+ * EEPROM 24C01 / 24C02 emulation.
+ *
+ * Emulation for serial EEPROMs:
+ * 24C01 - 1024 bit (128 x 8)
+ * 24C02 - 2048 bit (256 x 8)
+ *
+ * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
+ */
+
+//~ #define DEBUG
+
+#if defined(DEBUG)
+#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
+#else
+#  define logout(fmt, ...) ((void)0)
+#endif
+
+struct _eeprom24c0x_t {
+  uint8_t tick;
+  uint8_t address;
+  uint8_t command;
+  uint8_t ack;
+  uint8_t scl;
+  uint8_t sda;
+  uint8_t data;
+  //~ uint16_t size;
+  uint8_t contents[256];
+};
+
+typedef struct _eeprom24c0x_t eeprom24c0x_t;
+
+static eeprom24c0x_t eeprom = {
+    .contents = {
+        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
+        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
+        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
+        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
+        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
+        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
+        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
+    },
+};
+
+static uint8_t eeprom24c0x_read(void)
+{
+    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
+        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
+    return eeprom.sda;
+}
+
+static void eeprom24c0x_write(int scl, int sda)
+{
+    if (eeprom.scl && scl && (eeprom.sda != sda)) {
+        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
+        if (!sda) {
+            eeprom.tick = 1;
+            eeprom.command = 0;
+        }
+    } else if (eeprom.tick == 0 && !eeprom.ack) {
+        /* Waiting for start. */
+        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+    } else if (!eeprom.scl && scl) {
+        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+        if (eeprom.ack) {
+            logout("\ti2c ack bit = 0\n");
+            sda = 0;
+            eeprom.ack = 0;
+        } else if (eeprom.sda == sda) {
+            uint8_t bit = (sda != 0);
+            logout("\ti2c bit = %d\n", bit);
+            if (eeprom.tick < 9) {
+                eeprom.command <<= 1;
+                eeprom.command += bit;
+                eeprom.tick++;
+                if (eeprom.tick == 9) {
+                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
+                    eeprom.ack = 1;
+                }
+            } else if (eeprom.tick < 17) {
+                if (eeprom.command & 1) {
+                    sda = ((eeprom.data & 0x80) != 0);
+                }
+                eeprom.address <<= 1;
+                eeprom.address += bit;
+                eeprom.tick++;
+                eeprom.data <<= 1;
+                if (eeprom.tick == 17) {
+                    eeprom.data = eeprom.contents[eeprom.address];
+                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
+                    eeprom.ack = 1;
+                    eeprom.tick = 0;
+                }
+            } else if (eeprom.tick >= 17) {
+                sda = 0;
+            }
+        } else {
+            logout("\tsda changed with raising scl\n");
+        }
+    } else {
+        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+    }
+    eeprom.scl = scl;
+    eeprom.sda = sda;
+}
+
+static uint64_t malta_fpga_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    MaltaFPGAState *s = opaque;
+    uint32_t val = 0;
+    uint32_t saddr;
+
+    saddr = (addr & 0xfffff);
+
+    switch (saddr) {
+
+    /* SWITCH Register */
+    case 0x00200:
+        val = 0x00000000;              /* All switches closed */
+        break;
+
+    /* STATUS Register */
+    case 0x00208:
+#ifdef TARGET_WORDS_BIGENDIAN
+        val = 0x00000012;
+#else
+        val = 0x00000010;
+#endif
+        break;
+
+    /* JMPRS Register */
+    case 0x00210:
+        val = 0x00;
+        break;
+
+    /* LEDBAR Register */
+    case 0x00408:
+        val = s->leds;
+        break;
+
+    /* BRKRES Register */
+    case 0x00508:
+        val = s->brk;
+        break;
+
+    /* UART Registers are handled directly by the serial device */
+
+    /* GPOUT Register */
+    case 0x00a00:
+        val = s->gpout;
+        break;
+
+    /* XXX: implement a real I2C controller */
+
+    /* GPINP Register */
+    case 0x00a08:
+        /* IN = OUT until a real I2C control is implemented */
+        if (s->i2csel)
+            val = s->i2cout;
+        else
+            val = 0x00;
+        break;
+
+    /* I2CINP Register */
+    case 0x00b00:
+        val = ((s->i2cin & ~1) | eeprom24c0x_read());
+        break;
+
+    /* I2COE Register */
+    case 0x00b08:
+        val = s->i2coe;
+        break;
+
+    /* I2COUT Register */
+    case 0x00b10:
+        val = s->i2cout;
+        break;
+
+    /* I2CSEL Register */
+    case 0x00b18:
+        val = s->i2csel;
+        break;
+
+    default:
+#if 0
+        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
+                addr);
+#endif
+        break;
+    }
+    return val;
+}
+
+static void malta_fpga_write(void *opaque, hwaddr addr,
+                             uint64_t val, unsigned size)
+{
+    MaltaFPGAState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & 0xfffff);
+
+    switch (saddr) {
+
+    /* SWITCH Register */
+    case 0x00200:
+        break;
+
+    /* JMPRS Register */
+    case 0x00210:
+        break;
+
+    /* LEDBAR Register */
+    case 0x00408:
+        s->leds = val & 0xff;
+        malta_fpga_update_display(s);
+        break;
+
+    /* ASCIIWORD Register */
+    case 0x00410:
+        snprintf(s->display_text, 9, "%08X", (uint32_t)val);
+        malta_fpga_update_display(s);
+        break;
+
+    /* ASCIIPOS0 to ASCIIPOS7 Registers */
+    case 0x00418:
+    case 0x00420:
+    case 0x00428:
+    case 0x00430:
+    case 0x00438:
+    case 0x00440:
+    case 0x00448:
+    case 0x00450:
+        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
+        malta_fpga_update_display(s);
+        break;
+
+    /* SOFTRES Register */
+    case 0x00500:
+        if (val == 0x42)
+            qemu_system_reset_request ();
+        break;
+
+    /* BRKRES Register */
+    case 0x00508:
+        s->brk = val & 0xff;
+        break;
+
+    /* UART Registers are handled directly by the serial device */
+
+    /* GPOUT Register */
+    case 0x00a00:
+        s->gpout = val & 0xff;
+        break;
+
+    /* I2COE Register */
+    case 0x00b08:
+        s->i2coe = val & 0x03;
+        break;
+
+    /* I2COUT Register */
+    case 0x00b10:
+        eeprom24c0x_write(val & 0x02, val & 0x01);
+        s->i2cout = val;
+        break;
+
+    /* I2CSEL Register */
+    case 0x00b18:
+        s->i2csel = val & 0x01;
+        break;
+
+    default:
+#if 0
+        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
+                addr);
+#endif
+        break;
+    }
+}
+
+static const MemoryRegionOps malta_fpga_ops = {
+    .read = malta_fpga_read,
+    .write = malta_fpga_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void malta_fpga_reset(void *opaque)
+{
+    MaltaFPGAState *s = opaque;
+
+    s->leds   = 0x00;
+    s->brk    = 0x0a;
+    s->gpout  = 0x00;
+    s->i2cin  = 0x3;
+    s->i2coe  = 0x0;
+    s->i2cout = 0x3;
+    s->i2csel = 0x1;
+
+    s->display_text[8] = '\0';
+    snprintf(s->display_text, 9, "        ");
+}
+
+static void malta_fpga_led_init(CharDriverState *chr)
+{
+    qemu_chr_fe_printf(chr, "\e[HMalta LEDBAR\r\n");
+    qemu_chr_fe_printf(chr, "+--------+\r\n");
+    qemu_chr_fe_printf(chr, "+        +\r\n");
+    qemu_chr_fe_printf(chr, "+--------+\r\n");
+    qemu_chr_fe_printf(chr, "\n");
+    qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
+    qemu_chr_fe_printf(chr, "+--------+\r\n");
+    qemu_chr_fe_printf(chr, "+        +\r\n");
+    qemu_chr_fe_printf(chr, "+--------+\r\n");
+}
+
+static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
+         hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr)
+{
+    MaltaFPGAState *s;
+
+    s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
+
+    memory_region_init_io(&s->iomem, &malta_fpga_ops, s,
+                          "malta-fpga", 0x100000);
+    memory_region_init_alias(&s->iomem_lo, "malta-fpga",
+                             &s->iomem, 0, 0x900);
+    memory_region_init_alias(&s->iomem_hi, "malta-fpga",
+                             &s->iomem, 0xa00, 0x10000-0xa00);
+
+    memory_region_add_subregion(address_space, base, &s->iomem_lo);
+    memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
+
+    s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
+
+    s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
+                             230400, uart_chr, DEVICE_NATIVE_ENDIAN);
+
+    malta_fpga_reset(s);
+    qemu_register_reset(malta_fpga_reset, s);
+
+    return s;
+}
+
+/* Network support */
+static void network_init(void)
+{
+    int i;
+
+    for(i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+        const char *default_devaddr = NULL;
+
+        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
+            /* The malta board has a PCNet card using PCI SLOT 11 */
+            default_devaddr = "0b";
+
+        pci_nic_init_nofail(nd, "pcnet", default_devaddr);
+    }
+}
+
+/* ROM and pseudo bootloader
+
+   The following code implements a very very simple bootloader. It first
+   loads the registers a0 to a3 to the values expected by the OS, and
+   then jump at the kernel address.
+
+   The bootloader should pass the locations of the kernel arguments and
+   environment variables tables. Those tables contain the 32-bit address
+   of NULL terminated strings. The environment variables table should be
+   terminated by a NULL address.
+
+   For a simpler implementation, the number of kernel arguments is fixed
+   to two (the name of the kernel and the command line), and the two
+   tables are actually the same one.
+
+   The registers a0 to a3 should contain the following values:
+     a0 - number of kernel arguments
+     a1 - 32-bit address of the kernel arguments table
+     a2 - 32-bit address of the environment variables table
+     a3 - RAM size in bytes
+*/
+
+static void write_bootloader (CPUMIPSState *env, uint8_t *base,
+                              int64_t kernel_entry)
+{
+    uint32_t *p;
+
+    /* Small bootloader */
+    p = (uint32_t *)base;
+    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+
+    /* YAMON service vector */
+    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
+    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
+    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
+    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
+    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
+    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
+    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
+    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
+    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
+    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
+    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
+    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
+    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
+
+
+    /* Second part of the bootloader */
+    p = (uint32_t *) (base + 0x580);
+    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
+    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
+    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
+    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
+    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
+    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
+    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
+
+    /* Load BAR registers as done by YAMON */
+    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
+#else
+    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
+#endif
+    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
+
+    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
+#else
+    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
+#endif
+    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
+#else
+    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
+#endif
+    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
+#else
+    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
+#endif
+    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
+#else
+    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
+#endif
+    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
+#else
+    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
+#endif
+    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
+#else
+    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
+#endif
+    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
+
+    /* Jump to kernel code */
+    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
+    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
+    stl_raw(p++, 0x03e00008);                                      /* jr ra */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+
+    /* YAMON subroutines */
+    p = (uint32_t *) (base + 0x800);
+    stl_raw(p++, 0x03e00008);                                     /* jr ra */
+    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
+   /* 808 YAMON print */
+    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
+    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
+    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
+    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
+    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
+    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x08000205);                                     /* j 814 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
+    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
+    /* 0x83c YAMON print_count */
+    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
+    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
+    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
+    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
+    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
+    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
+    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
+    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
+    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
+    /* 0x870 */
+    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
+    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
+    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
+    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x03e00008);                                     /* jr ra */
+    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
+
+}
+
+static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
+                                        const char *string, ...)
+{
+    va_list ap;
+    int32_t table_addr;
+
+    if (index >= ENVP_NB_ENTRIES)
+        return;
+
+    if (string == NULL) {
+        prom_buf[index] = 0;
+        return;
+    }
+
+    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
+    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
+
+    va_start(ap, string);
+    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
+    va_end(ap);
+}
+
+/* Kernel */
+static int64_t load_kernel (void)
+{
+    int64_t kernel_entry, kernel_high;
+    long initrd_size;
+    ram_addr_t initrd_offset;
+    int big_endian;
+    uint32_t *prom_buf;
+    long prom_size;
+    int prom_index = 0;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    big_endian = 1;
+#else
+    big_endian = 0;
+#endif
+
+    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+                 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
+                 big_endian, ELF_MACHINE, 1) < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                loaderparams.kernel_filename);
+        exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (loaderparams.initrd_filename) {
+        initrd_size = get_image_size (loaderparams.initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        loaderparams.initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image_targphys(loaderparams.initrd_filename,
+                                              initrd_offset,
+                                              ram_size - initrd_offset);
+        }
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    loaderparams.initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* Setup prom parameters. */
+    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
+    prom_buf = g_malloc(prom_size);
+
+    prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename);
+    if (initrd_size > 0) {
+        prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
+                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
+                 loaderparams.kernel_cmdline);
+    } else {
+        prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_cmdline);
+    }
+
+    prom_set(prom_buf, prom_index++, "memsize");
+    prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
+    prom_set(prom_buf, prom_index++, "modetty0");
+    prom_set(prom_buf, prom_index++, "38400n8r");
+    prom_set(prom_buf, prom_index++, NULL);
+
+    rom_add_blob_fixed("prom", prom_buf, prom_size,
+                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
+
+    return kernel_entry;
+}
+
+static void malta_mips_config(MIPSCPU *cpu)
+{
+    CPUMIPSState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
+
+    env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
+                         ((smp_cpus * cs->nr_threads - 1) << CP0MVPC0_PTC);
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    MIPSCPU *cpu = opaque;
+    CPUMIPSState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+
+    /* The bootloader does not need to be rewritten as it is located in a
+       read only location. The kernel location and the arguments table
+       location does not change. */
+    if (loaderparams.kernel_filename) {
+        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
+    }
+
+    malta_mips_config(cpu);
+}
+
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+    CPUMIPSState *env = cpu_single_env;
+
+    if (env && level) {
+        cpu_exit(env);
+    }
+}
+
+static
+void mips_malta_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    pflash_t *fl;
+    MemoryRegion *system_memory = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
+    target_long bios_size = FLASH_SIZE;
+    int64_t kernel_entry;
+    PCIBus *pci_bus;
+    ISABus *isa_bus;
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+    qemu_irq *isa_irq;
+    qemu_irq *cpu_exit_irq;
+    int piix4_devfn;
+    i2c_bus *smbus;
+    int i;
+    DriveInfo *dinfo;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    DriveInfo *fd[MAX_FD];
+    int fl_idx = 0;
+    int fl_sectors = bios_size >> 16;
+    int be;
+
+    DeviceState *dev = qdev_create(NULL, "mips-malta");
+    MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev);
+
+    qdev_init_nofail(dev);
+
+    /* Make sure the first 3 serial ports are associated with a device. */
+    for(i = 0; i < 3; i++) {
+        if (!serial_hds[i]) {
+            char label[32];
+            snprintf(label, sizeof(label), "serial%d", i);
+            serial_hds[i] = qemu_chr_new(label, "null", NULL);
+        }
+    }
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "20Kc";
+#else
+        cpu_model = "24Kf";
+#endif
+    }
+
+    for (i = 0; i < smp_cpus; i++) {
+        cpu = cpu_mips_init(cpu_model);
+        if (cpu == NULL) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        env = &cpu->env;
+
+        /* Init internal devices */
+        cpu_mips_irq_init_cpu(env);
+        cpu_mips_clock_init(env);
+        qemu_register_reset(main_cpu_reset, cpu);
+    }
+    env = first_cpu;
+
+    /* allocate RAM */
+    if (ram_size > (256 << 20)) {
+        fprintf(stderr,
+                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
+                ((unsigned int)ram_size / (1 << 20)));
+        exit(1);
+    }
+    memory_region_init_ram(ram, "mips_malta.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(system_memory, 0, ram);
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    /* FPGA */
+    /* The CBUS UART is attached to the MIPS CPU INT2 pin, ie interrupt 4 */
+    malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[4], serial_hds[2]);
+
+    /* Load firmware in flash / BIOS. */
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+#ifdef DEBUG_BOARD_INIT
+    if (dinfo) {
+        printf("Register parallel flash %d size " TARGET_FMT_lx " at "
+               "addr %08llx '%s' %x\n",
+               fl_idx, bios_size, FLASH_ADDRESS,
+               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
+    }
+#endif
+    fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
+                               BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
+                               65536, fl_sectors,
+                               4, 0x0000, 0x0000, 0x0000, 0x0000, be);
+    bios = pflash_cfi01_get_memory(fl);
+    fl_idx++;
+    if (kernel_filename) {
+        /* Write a small bootloader to the flash location. */
+        loaderparams.ram_size = ram_size;
+        loaderparams.kernel_filename = kernel_filename;
+        loaderparams.kernel_cmdline = kernel_cmdline;
+        loaderparams.initrd_filename = initrd_filename;
+        kernel_entry = load_kernel();
+        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
+    } else {
+        /* Load firmware from flash. */
+        if (!dinfo) {
+            /* Load a BIOS image. */
+            if (bios_name == NULL) {
+                bios_name = BIOS_FILENAME;
+            }
+            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+            if (filename) {
+                bios_size = load_image_targphys(filename, FLASH_ADDRESS,
+                                                BIOS_SIZE);
+                g_free(filename);
+            } else {
+                bios_size = -1;
+            }
+            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
+                fprintf(stderr,
+                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
+                        bios_name);
+                exit(1);
+            }
+        }
+        /* In little endian mode the 32bit words in the bios are swapped,
+           a neat trick which allows bi-endian firmware. */
+#ifndef TARGET_WORDS_BIGENDIAN
+        {
+            uint32_t *addr = memory_region_get_ram_ptr(bios);
+            uint32_t *end = addr + bios_size;
+            while (addr < end) {
+                bswap32s(addr);
+                addr++;
+            }
+        }
+#endif
+    }
+
+    /* Map the BIOS at a 2nd physical location, as on the real board. */
+    memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
+    memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias);
+
+    /* Board ID = 0x420 (Malta Board with CoreLV)
+       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
+       map to the board ID. */
+    stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
+
+    /* Init internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+
+    /*
+     * We have a circular dependency problem: pci_bus depends on isa_irq,
+     * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
+     * on piix4, and piix4 depends on pci_bus.  To stop the cycle we have
+     * qemu_irq_proxy() adds an extra bit of indirection, allowing us
+     * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
+     */
+    isa_irq = qemu_irq_proxy(&s->i8259, 16);
+
+    /* Northbridge */
+    pci_bus = gt64120_register(isa_irq);
+
+    /* Southbridge */
+    ide_drive_get(hd, MAX_IDE_BUS);
+
+    piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
+
+    /* Interrupt controller */
+    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
+    s->i8259 = i8259_init(isa_bus, env->irq[2]);
+
+    isa_bus_irqs(isa_bus, s->i8259);
+    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
+    pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
+    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
+                          isa_get_irq(NULL, 9), NULL, 0, NULL);
+    /* TODO: Populate SPD eeprom data.  */
+    smbus_eeprom_init(smbus, 8, NULL, 0);
+    pit = pit_init(isa_bus, 0x40, 0, NULL);
+    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+    DMA_init(0, cpu_exit_irq);
+
+    /* Super I/O */
+    isa_create_simple(isa_bus, "i8042");
+
+    rtc_init(isa_bus, 2000, NULL);
+    serial_isa_init(isa_bus, 0, serial_hds[0]);
+    serial_isa_init(isa_bus, 1, serial_hds[1]);
+    if (parallel_hds[0])
+        parallel_init(isa_bus, 0, parallel_hds[0]);
+    for(i = 0; i < MAX_FD; i++) {
+        fd[i] = drive_get(IF_FLOPPY, 0, i);
+    }
+    fdctrl_init_isa(isa_bus, fd);
+
+    /* Sound card */
+    audio_init(isa_bus, pci_bus);
+
+    /* Network card */
+    network_init();
+
+    /* Optional PCI video card */
+    pci_vga_init(pci_bus);
+}
+
+static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
+{
+    return 0;
+}
+
+static void mips_malta_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mips_malta_sysbus_device_init;
+}
+
+static const TypeInfo mips_malta_device = {
+    .name          = "mips-malta",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(MaltaState),
+    .class_init    = mips_malta_class_init,
+};
+
+static QEMUMachine mips_malta_machine = {
+    .name = "malta",
+    .desc = "MIPS Malta Core LV",
+    .init = mips_malta_init,
+    .max_cpus = 16,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mips_malta_register_types(void)
+{
+    type_register_static(&mips_malta_device);
+}
+
+static void mips_malta_machine_init(void)
+{
+    qemu_register_machine(&mips_malta_machine);
+}
+
+type_init(mips_malta_register_types)
+machine_init(mips_malta_machine_init);
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c
new file mode 100644 (file)
index 0000000..4935c78
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * QEMU/mipssim emulation
+ *
+ * Emulates a very simple machine model similar to the one used by the
+ * proprietary MIPS emulator.
+ * 
+ * Copyright (c) 2007 Thiemo Seufer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/serial.h"
+#include "hw/isa.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/mips-bios.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+static struct _loaderparams {
+    int ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+} loaderparams;
+
+typedef struct ResetData {
+    MIPSCPU *cpu;
+    uint64_t vector;
+} ResetData;
+
+static int64_t load_kernel(void)
+{
+    int64_t entry, kernel_high;
+    long kernel_size;
+    long initrd_size;
+    ram_addr_t initrd_offset;
+    int big_endian;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    big_endian = 1;
+#else
+    big_endian = 0;
+#endif
+
+    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
+                           NULL, (uint64_t *)&entry, NULL,
+                           (uint64_t *)&kernel_high, big_endian,
+                           ELF_MACHINE, 1);
+    if (kernel_size >= 0) {
+        if ((entry & ~0x7fffffffULL) == 0x80000000)
+            entry = (int32_t)entry;
+    } else {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                loaderparams.kernel_filename);
+        exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (loaderparams.initrd_filename) {
+        initrd_size = get_image_size (loaderparams.initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > loaderparams.ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        loaderparams.initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image_targphys(loaderparams.initrd_filename,
+                initrd_offset, loaderparams.ram_size - initrd_offset);
+        }
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    loaderparams.initrd_filename);
+            exit(1);
+        }
+    }
+    return entry;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetData *s = (ResetData *)opaque;
+    CPUMIPSState *env = &s->cpu->env;
+
+    cpu_reset(CPU(s->cpu));
+    env->active_tc.PC = s->vector & ~(target_ulong)1;
+    if (s->vector & 1) {
+        env->hflags |= MIPS_HFLAG_M16;
+    }
+}
+
+static void mipsnet_init(int base, qemu_irq irq, NICInfo *nd)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "mipsnet");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, irq);
+    memory_region_add_subregion(get_system_io(),
+                                base,
+                                sysbus_mmio_get_region(s, 0));
+}
+
+static void
+mips_mipssim_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+    ResetData *reset_info;
+    int bios_size;
+
+    /* Init CPUs. */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "5Kf";
+#else
+        cpu_model = "24Kf";
+#endif
+    }
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    reset_info = g_malloc0(sizeof(ResetData));
+    reset_info->cpu = cpu;
+    reset_info->vector = env->active_tc.PC;
+    qemu_register_reset(main_cpu_reset, reset_info);
+
+    /* Allocate RAM. */
+    memory_region_init_ram(ram, "mips_mipssim.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_init_ram(bios, "mips_mipssim.bios", BIOS_SIZE);
+    vmstate_register_ram_global(bios);
+    memory_region_set_readonly(bios, true);
+
+    memory_region_add_subregion(address_space_mem, 0, ram);
+
+    /* Map the BIOS / boot exception handler. */
+    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
+    /* Load a BIOS / boot exception handler image. */
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (filename) {
+        bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE);
+        g_free(filename);
+    } else {
+        bios_size = -1;
+    }
+    if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
+        /* Bail out if we have neither a kernel image nor boot vector code. */
+        fprintf(stderr,
+                "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
+                filename);
+        exit(1);
+    } else {
+        /* We have a boot vector start address. */
+        env->active_tc.PC = (target_long)(int32_t)0xbfc00000;
+    }
+
+    if (kernel_filename) {
+        loaderparams.ram_size = ram_size;
+        loaderparams.kernel_filename = kernel_filename;
+        loaderparams.kernel_cmdline = kernel_cmdline;
+        loaderparams.initrd_filename = initrd_filename;
+        reset_info->vector = load_kernel();
+    }
+
+    /* Init CPU internal devices. */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+
+    /* Register 64 KB of ISA IO space at 0x1fd00000. */
+    isa_mmio_init(0x1fd00000, 0x00010000);
+
+    /* A single 16450 sits at offset 0x3f8. It is attached to
+       MIPS CPU INT2, which is interrupt 4. */
+    if (serial_hds[0])
+        serial_init(0x3f8, env->irq[4], 115200, serial_hds[0],
+                    get_system_io());
+
+    if (nd_table[0].used)
+        /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
+        mipsnet_init(0x4200, env->irq[2], &nd_table[0]);
+}
+
+static QEMUMachine mips_mipssim_machine = {
+    .name = "mipssim",
+    .desc = "MIPS MIPSsim platform",
+    .init = mips_mipssim_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mips_mipssim_machine_init(void)
+{
+    qemu_register_machine(&mips_mipssim_machine);
+}
+
+machine_init(mips_mipssim_machine_init);
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
new file mode 100644 (file)
index 0000000..539a562
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * QEMU/MIPS pseudo-board
+ *
+ * emulates a simple machine with ISA-like bus.
+ * ISA IO space mapped to the 0x14000000 (PHYS) and
+ * ISA memory at the 0x10000000 (PHYS, 16Mb in size).
+ * All peripherial devices are attached to this "bus" with
+ * the standard PC ISA addresses.
+*/
+#include "hw/hw.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/isa.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/flash.h"
+#include "qemu/log.h"
+#include "hw/mips-bios.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define MAX_IDE_BUS 2
+
+static const int ide_iobase[2] = { 0x1f0, 0x170 };
+static const int ide_iobase2[2] = { 0x3f6, 0x376 };
+static const int ide_irq[2] = { 14, 15 };
+
+static ISADevice *pit; /* PIT i8254 */
+
+/* i8254 PIT is attached to the IRQ0 at PIC i8259 */
+
+static struct _loaderparams {
+    int ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+} loaderparams;
+
+static void mips_qemu_write (void *opaque, hwaddr addr,
+                             uint64_t val, unsigned size)
+{
+    if ((addr & 0xffff) == 0 && val == 42)
+        qemu_system_reset_request ();
+    else if ((addr & 0xffff) == 4 && val == 42)
+        qemu_system_shutdown_request ();
+}
+
+static uint64_t mips_qemu_read (void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    return 0;
+}
+
+static const MemoryRegionOps mips_qemu_ops = {
+    .read = mips_qemu_read,
+    .write = mips_qemu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct ResetData {
+    MIPSCPU *cpu;
+    uint64_t vector;
+} ResetData;
+
+static int64_t load_kernel(void)
+{
+    int64_t entry, kernel_high;
+    long kernel_size, initrd_size, params_size;
+    ram_addr_t initrd_offset;
+    uint32_t *params_buf;
+    int big_endian;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    big_endian = 1;
+#else
+    big_endian = 0;
+#endif
+    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
+                           NULL, (uint64_t *)&entry, NULL,
+                           (uint64_t *)&kernel_high, big_endian,
+                           ELF_MACHINE, 1);
+    if (kernel_size >= 0) {
+        if ((entry & ~0x7fffffffULL) == 0x80000000)
+            entry = (int32_t)entry;
+    } else {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                loaderparams.kernel_filename);
+        exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (loaderparams.initrd_filename) {
+        initrd_size = get_image_size (loaderparams.initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        loaderparams.initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image_targphys(loaderparams.initrd_filename,
+                                              initrd_offset,
+                                              ram_size - initrd_offset);
+        }
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    loaderparams.initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* Store command line.  */
+    params_size = 264;
+    params_buf = g_malloc(params_size);
+
+    params_buf[0] = tswap32(ram_size);
+    params_buf[1] = tswap32(0x12345678);
+
+    if (initrd_size > 0) {
+        snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%li %s",
+                 cpu_mips_phys_to_kseg0(NULL, initrd_offset),
+                 initrd_size, loaderparams.kernel_cmdline);
+    } else {
+        snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline);
+    }
+
+    rom_add_blob_fixed("params", params_buf, params_size,
+                       (16 << 20) - 264);
+
+    return entry;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetData *s = (ResetData *)opaque;
+    CPUMIPSState *env = &s->cpu->env;
+
+    cpu_reset(CPU(s->cpu));
+    env->active_tc.PC = s->vector;
+}
+
+static const int sector_len = 32 * 1024;
+static
+void mips_r4k_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios;
+    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+    int bios_size;
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+    ResetData *reset_info;
+    int i;
+    qemu_irq *i8259;
+    ISABus *isa_bus;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    DriveInfo *dinfo;
+    int be;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "R4000";
+#else
+        cpu_model = "24Kf";
+#endif
+    }
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    reset_info = g_malloc0(sizeof(ResetData));
+    reset_info->cpu = cpu;
+    reset_info->vector = env->active_tc.PC;
+    qemu_register_reset(main_cpu_reset, reset_info);
+
+    /* allocate RAM */
+    if (ram_size > (256 << 20)) {
+        fprintf(stderr,
+                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
+                ((unsigned int)ram_size / (1 << 20)));
+        exit(1);
+    }
+    memory_region_init_ram(ram, "mips_r4k.ram", ram_size);
+    vmstate_register_ram_global(ram);
+
+    memory_region_add_subregion(address_space_mem, 0, ram);
+
+    memory_region_init_io(iomem, &mips_qemu_ops, NULL, "mips-qemu", 0x10000);
+    memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem);
+
+    /* Try to load a BIOS image. If this fails, we continue regardless,
+       but initialize the hardware ourselves. When a kernel gets
+       preloaded we also initialize the hardware, since the BIOS wasn't
+       run. */
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (filename) {
+        bios_size = get_image_size(filename);
+    } else {
+        bios_size = -1;
+    }
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
+        bios = g_new(MemoryRegion, 1);
+        memory_region_init_ram(bios, "mips_r4k.bios", BIOS_SIZE);
+        vmstate_register_ram_global(bios);
+        memory_region_set_readonly(bios, true);
+        memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
+
+        load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
+    } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
+        uint32_t mips_rom = 0x00400000;
+        if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
+                                   dinfo->bdrv, sector_len,
+                                   mips_rom / sector_len,
+                                   4, 0, 0, 0, 0, be)) {
+            fprintf(stderr, "qemu: Error registering flash memory.\n");
+       }
+    }
+    else {
+       /* not fatal */
+        fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
+               bios_name);
+    }
+    if (filename) {
+        g_free(filename);
+    }
+
+    if (kernel_filename) {
+        loaderparams.ram_size = ram_size;
+        loaderparams.kernel_filename = kernel_filename;
+        loaderparams.kernel_cmdline = kernel_cmdline;
+        loaderparams.initrd_filename = initrd_filename;
+        reset_info->vector = load_kernel();
+    }
+
+    /* Init CPU internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+
+    /* The PIC is attached to the MIPS CPU INT0 pin */
+    isa_bus = isa_bus_new(NULL, get_system_io());
+    i8259 = i8259_init(isa_bus, env->irq[2]);
+    isa_bus_irqs(isa_bus, i8259);
+
+    rtc_init(isa_bus, 2000, NULL);
+
+    /* Register 64 KB of ISA IO space at 0x14000000 */
+    isa_mmio_init(0x14000000, 0x00010000);
+    isa_mem_base = 0x10000000;
+
+    pit = pit_init(isa_bus, 0x40, 0, NULL);
+
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_isa_init(isa_bus, i, serial_hds[i]);
+        }
+    }
+
+    isa_vga_init(isa_bus);
+
+    if (nd_table[0].used)
+        isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]);
+
+    ide_drive_get(hd, MAX_IDE_BUS);
+    for(i = 0; i < MAX_IDE_BUS; i++)
+        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]);
+
+    isa_create_simple(isa_bus, "i8042");
+}
+
+static QEMUMachine mips_machine = {
+    .name = "mips",
+    .desc = "mips r4k platform",
+    .init = mips_r4k_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mips_machine_init(void)
+{
+    qemu_register_machine(&mips_machine);
+}
+
+machine_init(mips_machine_init);
diff --git a/hw/mips_addr.c b/hw/mips_addr.c
deleted file mode 100644 (file)
index aa1c7d8..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * QEMU MIPS address translation support
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw.h"
-#include "mips_cpudevs.h"
-
-uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
-{
-    return addr & 0x7fffffffll;
-}
-
-uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr)
-{
-    return addr | ~0x7fffffffll;
-}
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
deleted file mode 100644 (file)
index 8b532e1..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * QEMU fulong 2e mini pc support
- *
- * Copyright (c) 2008 yajin (yajin@vm-kernel.org)
- * Copyright (c) 2009 chenming (chenming@rdc.faw.com.cn)
- * Copyright (c) 2010 Huacai Chen (zltjiangshi@gmail.com)
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-/*
- * Fulong 2e mini pc is based on ICT/ST Loongson 2e CPU (MIPS III like, 800MHz)
- * http://www.linux-mips.org/wiki/Fulong
- *
- * Loongson 2e user manual:
- * http://www.loongsondeveloper.com/doc/Loongson2EUserGuide.pdf
- */
-
-#include "hw.h"
-#include "pc.h"
-#include "serial.h"
-#include "fdc.h"
-#include "net/net.h"
-#include "boards.h"
-#include "smbus.h"
-#include "block/block.h"
-#include "flash.h"
-#include "mips.h"
-#include "mips_cpudevs.h"
-#include "pci/pci.h"
-#include "char/char.h"
-#include "sysemu/sysemu.h"
-#include "audio/audio.h"
-#include "qemu/log.h"
-#include "loader.h"
-#include "mips-bios.h"
-#include "ide.h"
-#include "elf.h"
-#include "vt82c686.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define DEBUG_FULONG2E_INIT
-
-#define ENVP_ADDR       0x80002000l
-#define ENVP_NB_ENTRIES                16
-#define ENVP_ENTRY_SIZE                256
-
-#define MAX_IDE_BUS 2
-
-/*
- * PMON is not part of qemu and released with BSD license, anyone
- * who want to build a pmon binary please first git-clone the source
- * from the git repository at:
- * http://www.loongson.cn/support/git/pmon
- * Then follow the "Compile Guide" available at:
- * http://dev.lemote.com/code/pmon
- *
- * Notes:
- * 1, don't use the source at http://dev.lemote.com/http_git/pmon.git
- * 2, use "Bonito2edev" to replace "dir_corresponding_to_your_target_hardware"
- * in the "Compile Guide".
- */
-#define FULONG_BIOSNAME "pmon_fulong2e.bin"
-
-/* PCI SLOT in fulong 2e */
-#define FULONG2E_VIA_SLOT        5
-#define FULONG2E_ATI_SLOT        6
-#define FULONG2E_RTL8139_SLOT    7
-
-static ISADevice *pit;
-
-static struct _loaderparams {
-    int ram_size;
-    const char *kernel_filename;
-    const char *kernel_cmdline;
-    const char *initrd_filename;
-} loaderparams;
-
-static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
-                                        const char *string, ...)
-{
-    va_list ap;
-    int32_t table_addr;
-
-    if (index >= ENVP_NB_ENTRIES)
-        return;
-
-    if (string == NULL) {
-        prom_buf[index] = 0;
-        return;
-    }
-
-    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
-    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
-
-    va_start(ap, string);
-    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
-    va_end(ap);
-}
-
-static int64_t load_kernel (CPUMIPSState *env)
-{
-    int64_t kernel_entry, kernel_low, kernel_high;
-    int index = 0;
-    long initrd_size;
-    ram_addr_t initrd_offset;
-    uint32_t *prom_buf;
-    long prom_size;
-
-    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
-                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
-                 (uint64_t *)&kernel_high, 0, ELF_MACHINE, 1) < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                loaderparams.kernel_filename);
-        exit(1);
-    }
-
-    /* load initrd */
-    initrd_size = 0;
-    initrd_offset = 0;
-    if (loaderparams.initrd_filename) {
-        initrd_size = get_image_size (loaderparams.initrd_filename);
-        if (initrd_size > 0) {
-            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
-            if (initrd_offset + initrd_size > ram_size) {
-                fprintf(stderr,
-                        "qemu: memory too small for initial ram disk '%s'\n",
-                        loaderparams.initrd_filename);
-                exit(1);
-            }
-            initrd_size = load_image_targphys(loaderparams.initrd_filename,
-                                     initrd_offset, ram_size - initrd_offset);
-        }
-        if (initrd_size == (target_ulong) -1) {
-            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                    loaderparams.initrd_filename);
-            exit(1);
-        }
-    }
-
-    /* Setup prom parameters. */
-    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
-    prom_buf = g_malloc(prom_size);
-
-    prom_set(prom_buf, index++, "%s", loaderparams.kernel_filename);
-    if (initrd_size > 0) {
-        prom_set(prom_buf, index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
-                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
-                 loaderparams.kernel_cmdline);
-    } else {
-        prom_set(prom_buf, index++, "%s", loaderparams.kernel_cmdline);
-    }
-
-    /* Setup minimum environment variables */
-    prom_set(prom_buf, index++, "busclock=33000000");
-    prom_set(prom_buf, index++, "cpuclock=100000000");
-    prom_set(prom_buf, index++, "memsize=%i", loaderparams.ram_size/1024/1024);
-    prom_set(prom_buf, index++, "modetty0=38400n8r");
-    prom_set(prom_buf, index++, NULL);
-
-    rom_add_blob_fixed("prom", prom_buf, prom_size,
-                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
-
-    return kernel_entry;
-}
-
-static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_addr)
-{
-    uint32_t *p;
-
-    /* Small bootloader */
-    p = (uint32_t *) base;
-
-    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
-    stl_raw(p++, 0x00000000);                                      /* nop */
-
-    /* Second part of the bootloader */
-    p = (uint32_t *) (base + 0x040);
-
-    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
-    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
-    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
-    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
-    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));      /* lui a3, high(env->ram_size) */
-    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));   /* ori a3, a3, low(env->ram_size) */
-    stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
-    stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
-    stl_raw(p++, 0x03e00008);                                      /* jr ra */
-    stl_raw(p++, 0x00000000);                                      /* nop */
-}
-
-
-static void main_cpu_reset(void *opaque)
-{
-    MIPSCPU *cpu = opaque;
-    CPUMIPSState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-    /* TODO: 2E reset stuff */
-    if (loaderparams.kernel_filename) {
-        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
-    }
-}
-
-uint8_t eeprom_spd[0x80] = {
-    0x80,0x08,0x07,0x0d,0x09,0x02,0x40,0x00,0x04,0x70,
-    0x70,0x00,0x82,0x10,0x00,0x01,0x0e,0x04,0x0c,0x01,
-    0x02,0x20,0x80,0x75,0x70,0x00,0x00,0x50,0x3c,0x50,
-    0x2d,0x20,0xb0,0xb0,0x50,0x50,0x00,0x00,0x00,0x00,
-    0x00,0x41,0x48,0x3c,0x32,0x75,0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x9c,0x7b,0x07,0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x00,0x48,0x42,0x35,0x34,0x41,0x32,
-    0x35,0x36,0x38,0x4b,0x4e,0x2d,0x41,0x37,0x35,0x42,
-    0x20,0x30,0x20
-};
-
-/* Audio support */
-static void audio_init (PCIBus *pci_bus)
-{
-    vt82c686b_ac97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 5));
-    vt82c686b_mc97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 6));
-}
-
-/* Network support */
-static void network_init (void)
-{
-    int i;
-
-    for(i = 0; i < nb_nics; i++) {
-        NICInfo *nd = &nd_table[i];
-        const char *default_devaddr = NULL;
-
-        if (i == 0 && (!nd->model || strcmp(nd->model, "rtl8139") == 0)) {
-            /* The fulong board has a RTL8139 card using PCI SLOT 7 */
-            default_devaddr = "07";
-        }
-
-        pci_nic_init_nofail(nd, "rtl8139", default_devaddr);
-    }
-}
-
-static void cpu_request_exit(void *opaque, int irq, int level)
-{
-    CPUMIPSState *env = cpu_single_env;
-
-    if (env && level) {
-        cpu_exit(env);
-    }
-}
-
-static void mips_fulong2e_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *bios = g_new(MemoryRegion, 1);
-    long bios_size;
-    int64_t kernel_entry;
-    qemu_irq *i8259;
-    qemu_irq *cpu_exit_irq;
-    PCIBus *pci_bus;
-    ISABus *isa_bus;
-    i2c_bus *smbus;
-    int i;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    MIPSCPU *cpu;
-    CPUMIPSState *env;
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = "Loongson-2E";
-    }
-    cpu = cpu_mips_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    qemu_register_reset(main_cpu_reset, cpu);
-
-    /* fulong 2e has 256M ram. */
-    ram_size = 256 * 1024 * 1024;
-
-    /* fulong 2e has a 1M flash.Winbond W39L040AP70Z */
-    bios_size = 1024 * 1024;
-
-    /* allocate RAM */
-    memory_region_init_ram(ram, "fulong2e.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_init_ram(bios, "fulong2e.bios", bios_size);
-    vmstate_register_ram_global(bios);
-    memory_region_set_readonly(bios, true);
-
-    memory_region_add_subregion(address_space_mem, 0, ram);
-    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
-
-    /* We do not support flash operation, just loading pmon.bin as raw BIOS.
-     * Please use -L to set the BIOS path and -bios to set bios name. */
-
-    if (kernel_filename) {
-        loaderparams.ram_size = ram_size;
-        loaderparams.kernel_filename = kernel_filename;
-        loaderparams.kernel_cmdline = kernel_cmdline;
-        loaderparams.initrd_filename = initrd_filename;
-        kernel_entry = load_kernel (env);
-        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
-    } else {
-        if (bios_name == NULL) {
-                bios_name = FULONG_BIOSNAME;
-        }
-        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-        if (filename) {
-            bios_size = load_image_targphys(filename, 0x1fc00000LL,
-                                            BIOS_SIZE);
-            g_free(filename);
-        } else {
-            bios_size = -1;
-        }
-
-        if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
-            fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", bios_name);
-            exit(1);
-        }
-    }
-
-    /* Init internal devices */
-    cpu_mips_irq_init_cpu(env);
-    cpu_mips_clock_init(env);
-
-    /* North bridge, Bonito --> IP2 */
-    pci_bus = bonito_init((qemu_irq *)&(env->irq[2]));
-
-    /* South bridge */
-    ide_drive_get(hd, MAX_IDE_BUS);
-
-    isa_bus = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0));
-    if (!isa_bus) {
-        fprintf(stderr, "vt82c686b_init error\n");
-        exit(1);
-    }
-
-    /* Interrupt controller */
-    /* The 8259 -> IP5  */
-    i8259 = i8259_init(isa_bus, env->irq[5]);
-    isa_bus_irqs(isa_bus, i8259);
-
-    vt82c686b_ide_init(pci_bus, hd, PCI_DEVFN(FULONG2E_VIA_SLOT, 1));
-    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 2),
-                      "vt82c686b-usb-uhci");
-    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 3),
-                      "vt82c686b-usb-uhci");
-
-    smbus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 4),
-                              0xeee1, NULL);
-    /* TODO: Populate SPD eeprom data.  */
-    smbus_eeprom_init(smbus, 1, eeprom_spd, sizeof(eeprom_spd));
-
-    /* init other devices */
-    pit = pit_init(isa_bus, 0x40, 0, NULL);
-    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
-    DMA_init(0, cpu_exit_irq);
-
-    /* Super I/O */
-    isa_create_simple(isa_bus, "i8042");
-
-    rtc_init(isa_bus, 2000, NULL);
-
-    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_hds[i]) {
-            serial_isa_init(isa_bus, i, serial_hds[i]);
-        }
-    }
-
-    if (parallel_hds[0]) {
-        parallel_init(isa_bus, 0, parallel_hds[0]);
-    }
-
-    /* Sound card */
-    audio_init(pci_bus);
-    /* Network card */
-    network_init();
-}
-
-static QEMUMachine mips_fulong2e_machine = {
-    .name = "fulong2e",
-    .desc = "Fulong 2e mini pc",
-    .init = mips_fulong2e_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mips_fulong2e_machine_init(void)
-{
-    qemu_register_machine(&mips_fulong2e_machine);
-}
-
-machine_init(mips_fulong2e_machine_init);
diff --git a/hw/mips_int.c b/hw/mips_int.c
deleted file mode 100644 (file)
index 6423fd0..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * QEMU MIPS interrupt support
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw.h"
-#include "mips_cpudevs.h"
-#include "cpu.h"
-
-static void cpu_mips_irq_request(void *opaque, int irq, int level)
-{
-    CPUMIPSState *env = (CPUMIPSState *)opaque;
-
-    if (irq < 0 || irq > 7)
-        return;
-
-    if (level) {
-        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
-    } else {
-        env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
-    }
-
-    if (env->CP0_Cause & CP0Ca_IP_mask) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-void cpu_mips_irq_init_cpu(CPUMIPSState *env)
-{
-    qemu_irq *qi;
-    int i;
-
-    qi = qemu_allocate_irqs(cpu_mips_irq_request, env, 8);
-    for (i = 0; i < 8; i++) {
-        env->irq[i] = qi[i];
-    }
-}
-
-void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level)
-{
-    if (irq < 0 || irq > 2) {
-        return;
-    }
-
-    qemu_set_irq(env->irq[irq], level);
-}
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
deleted file mode 100644 (file)
index 17fbdde..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * QEMU MIPS Jazz support
- *
- * Copyright (c) 2007-2008 Hervé Poussineau
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw.h"
-#include "mips.h"
-#include "mips_cpudevs.h"
-#include "pc.h"
-#include "serial.h"
-#include "isa.h"
-#include "fdc.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/arch_init.h"
-#include "boards.h"
-#include "net/net.h"
-#include "esp.h"
-#include "mips-bios.h"
-#include "loader.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
-#include "pcspk.h"
-#include "sysemu/blockdev.h"
-#include "sysbus.h"
-#include "exec/address-spaces.h"
-
-enum jazz_model_e
-{
-    JAZZ_MAGNUM,
-    JAZZ_PICA61,
-};
-
-static void main_cpu_reset(void *opaque)
-{
-    MIPSCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size)
-{
-    return cpu_inw(0x71);
-}
-
-static void rtc_write(void *opaque, hwaddr addr,
-                      uint64_t val, unsigned size)
-{
-    cpu_outw(0x71, val & 0xff);
-}
-
-static const MemoryRegionOps rtc_ops = {
-    .read = rtc_read,
-    .write = rtc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static uint64_t dma_dummy_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    /* Nothing to do. That is only to ensure that
-     * the current DMA acknowledge cycle is completed. */
-    return 0xff;
-}
-
-static void dma_dummy_write(void *opaque, hwaddr addr,
-                            uint64_t val, unsigned size)
-{
-    /* Nothing to do. That is only to ensure that
-     * the current DMA acknowledge cycle is completed. */
-}
-
-static const MemoryRegionOps dma_dummy_ops = {
-    .read = dma_dummy_read,
-    .write = dma_dummy_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-#define MAGNUM_BIOS_SIZE_MAX 0x7e000
-#define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
-
-static void cpu_request_exit(void *opaque, int irq, int level)
-{
-    CPUMIPSState *env = cpu_single_env;
-
-    if (env && level) {
-        cpu_exit(env);
-    }
-}
-
-static void mips_jazz_init(MemoryRegion *address_space,
-                           MemoryRegion *address_space_io,
-                           ram_addr_t ram_size,
-                           const char *cpu_model,
-                           enum jazz_model_e jazz_model)
-{
-    char *filename;
-    int bios_size, n;
-    MIPSCPU *cpu;
-    CPUMIPSState *env;
-    qemu_irq *rc4030, *i8259;
-    rc4030_dma *dmas;
-    void* rc4030_opaque;
-    MemoryRegion *rtc = g_new(MemoryRegion, 1);
-    MemoryRegion *i8042 = g_new(MemoryRegion, 1);
-    MemoryRegion *dma_dummy = g_new(MemoryRegion, 1);
-    NICInfo *nd;
-    DeviceState *dev;
-    SysBusDevice *sysbus;
-    ISABus *isa_bus;
-    ISADevice *pit;
-    DriveInfo *fds[MAX_FD];
-    qemu_irq esp_reset, dma_enable;
-    qemu_irq *cpu_exit_irq;
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *bios = g_new(MemoryRegion, 1);
-    MemoryRegion *bios2 = g_new(MemoryRegion, 1);
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-#ifdef TARGET_MIPS64
-        cpu_model = "R4000";
-#else
-        /* FIXME: All wrong, this maybe should be R3000 for the older JAZZs. */
-        cpu_model = "24Kf";
-#endif
-    }
-    cpu = cpu_mips_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-    qemu_register_reset(main_cpu_reset, cpu);
-
-    /* allocate RAM */
-    memory_region_init_ram(ram, "mips_jazz.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space, 0, ram);
-
-    memory_region_init_ram(bios, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
-    vmstate_register_ram_global(bios);
-    memory_region_set_readonly(bios, true);
-    memory_region_init_alias(bios2, "mips_jazz.bios", bios,
-                             0, MAGNUM_BIOS_SIZE);
-    memory_region_add_subregion(address_space, 0x1fc00000LL, bios);
-    memory_region_add_subregion(address_space, 0xfff00000LL, bios2);
-
-    /* load the BIOS image. */
-    if (bios_name == NULL)
-        bios_name = BIOS_FILENAME;
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (filename) {
-        bios_size = load_image_targphys(filename, 0xfff00000LL,
-                                        MAGNUM_BIOS_SIZE);
-        g_free(filename);
-    } else {
-        bios_size = -1;
-    }
-    if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) {
-        fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n",
-                bios_name);
-        exit(1);
-    }
-
-    /* Init CPU internal devices */
-    cpu_mips_irq_init_cpu(env);
-    cpu_mips_clock_init(env);
-
-    /* Chipset */
-    rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas,
-                                address_space);
-    memory_region_init_io(dma_dummy, &dma_dummy_ops, NULL, "dummy_dma", 0x1000);
-    memory_region_add_subregion(address_space, 0x8000d000, dma_dummy);
-
-    /* ISA devices */
-    isa_bus = isa_bus_new(NULL, address_space_io);
-    i8259 = i8259_init(isa_bus, env->irq[4]);
-    isa_bus_irqs(isa_bus, i8259);
-    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
-    DMA_init(0, cpu_exit_irq);
-    pit = pit_init(isa_bus, 0x40, 0, NULL);
-    pcspk_init(isa_bus, pit);
-
-    /* ISA IO space at 0x90000000 */
-    isa_mmio_init(0x90000000, 0x01000000);
-    isa_mem_base = 0x11000000;
-
-    /* Video card */
-    switch (jazz_model) {
-    case JAZZ_MAGNUM:
-        dev = qdev_create(NULL, "sysbus-g364");
-        qdev_init_nofail(dev);
-        sysbus = SYS_BUS_DEVICE(dev);
-        sysbus_mmio_map(sysbus, 0, 0x60080000);
-        sysbus_mmio_map(sysbus, 1, 0x40000000);
-        sysbus_connect_irq(sysbus, 0, rc4030[3]);
-        {
-            /* Simple ROM, so user doesn't have to provide one */
-            MemoryRegion *rom_mr = g_new(MemoryRegion, 1);
-            memory_region_init_ram(rom_mr, "g364fb.rom", 0x80000);
-            vmstate_register_ram_global(rom_mr);
-            memory_region_set_readonly(rom_mr, true);
-            uint8_t *rom = memory_region_get_ram_ptr(rom_mr);
-            memory_region_add_subregion(address_space, 0x60000000, rom_mr);
-            rom[0] = 0x10; /* Mips G364 */
-        }
-        break;
-    case JAZZ_PICA61:
-        isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory());
-        break;
-    default:
-        break;
-    }
-
-    /* Network controller */
-    for (n = 0; n < nb_nics; n++) {
-        nd = &nd_table[n];
-        if (!nd->model)
-            nd->model = g_strdup("dp83932");
-        if (strcmp(nd->model, "dp83932") == 0) {
-            dp83932_init(nd, 0x80001000, 2, get_system_memory(), rc4030[4],
-                         rc4030_opaque, rc4030_dma_memory_rw);
-            break;
-        } else if (is_help_option(nd->model)) {
-            fprintf(stderr, "qemu: Supported NICs: dp83932\n");
-            exit(1);
-        } else {
-            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
-            exit(1);
-        }
-    }
-
-    /* SCSI adapter */
-    esp_init(0x80002000, 0,
-             rc4030_dma_read, rc4030_dma_write, dmas[0],
-             rc4030[5], &esp_reset, &dma_enable);
-
-    /* Floppy */
-    if (drive_get_max_bus(IF_FLOPPY) >= MAX_FD) {
-        fprintf(stderr, "qemu: too many floppy drives\n");
-        exit(1);
-    }
-    for (n = 0; n < MAX_FD; n++) {
-        fds[n] = drive_get(IF_FLOPPY, 0, n);
-    }
-    fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
-
-    /* Real time clock */
-    rtc_init(isa_bus, 1980, NULL);
-    memory_region_init_io(rtc, &rtc_ops, NULL, "rtc", 0x1000);
-    memory_region_add_subregion(address_space, 0x80004000, rtc);
-
-    /* Keyboard (i8042) */
-    i8042_mm_init(rc4030[6], rc4030[7], i8042, 0x1000, 0x1);
-    memory_region_add_subregion(address_space, 0x80005000, i8042);
-
-    /* Serial ports */
-    if (serial_hds[0]) {
-        serial_mm_init(address_space, 0x80006000, 0, rc4030[8], 8000000/16,
-                       serial_hds[0], DEVICE_NATIVE_ENDIAN);
-    }
-    if (serial_hds[1]) {
-        serial_mm_init(address_space, 0x80007000, 0, rc4030[9], 8000000/16,
-                       serial_hds[1], DEVICE_NATIVE_ENDIAN);
-    }
-
-    /* Parallel port */
-    if (parallel_hds[0])
-        parallel_mm_init(address_space, 0x80008000, 0, rc4030[0],
-                         parallel_hds[0]);
-
-    /* Sound card */
-    /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
-    audio_init(isa_bus, NULL);
-
-    /* NVRAM */
-    dev = qdev_create(NULL, "ds1225y");
-    qdev_init_nofail(dev);
-    sysbus = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(sysbus, 0, 0x80009000);
-
-    /* LED indicator */
-    sysbus_create_simple("jazz-led", 0x8000f000, NULL);
-}
-
-static
-void mips_magnum_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-        mips_jazz_init(get_system_memory(), get_system_io(),
-                       ram_size, cpu_model, JAZZ_MAGNUM);
-}
-
-static
-void mips_pica61_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    mips_jazz_init(get_system_memory(), get_system_io(),
-                   ram_size, cpu_model, JAZZ_PICA61);
-}
-
-static QEMUMachine mips_magnum_machine = {
-    .name = "magnum",
-    .desc = "MIPS Magnum",
-    .init = mips_magnum_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine mips_pica61_machine = {
-    .name = "pica61",
-    .desc = "Acer Pica 61",
-    .init = mips_pica61_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mips_jazz_machine_init(void)
-{
-    qemu_register_machine(&mips_magnum_machine);
-    qemu_register_machine(&mips_pica61_machine);
-}
-
-machine_init(mips_jazz_machine_init);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
deleted file mode 100644 (file)
index 2a150df..0000000
+++ /dev/null
@@ -1,1037 +0,0 @@
-/*
- * QEMU Malta board support
- *
- * Copyright (c) 2006 Aurelien Jarno
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw.h"
-#include "pc.h"
-#include "serial.h"
-#include "fdc.h"
-#include "net/net.h"
-#include "boards.h"
-#include "smbus.h"
-#include "block/block.h"
-#include "flash.h"
-#include "mips.h"
-#include "mips_cpudevs.h"
-#include "pci/pci.h"
-#include "char/char.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/arch_init.h"
-#include "boards.h"
-#include "qemu/log.h"
-#include "mips-bios.h"
-#include "ide.h"
-#include "loader.h"
-#include "elf.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-#include "sysbus.h"             /* SysBusDevice */
-
-//#define DEBUG_BOARD_INIT
-
-#define ENVP_ADDR              0x80002000l
-#define ENVP_NB_ENTRIES                16
-#define ENVP_ENTRY_SIZE                256
-
-/* Hardware addresses */
-#define FLASH_ADDRESS 0x1e000000ULL
-#define FPGA_ADDRESS  0x1f000000ULL
-#define RESET_ADDRESS 0x1fc00000ULL
-
-#define FLASH_SIZE    0x400000
-
-#define MAX_IDE_BUS 2
-
-typedef struct {
-    MemoryRegion iomem;
-    MemoryRegion iomem_lo; /* 0 - 0x900 */
-    MemoryRegion iomem_hi; /* 0xa00 - 0x100000 */
-    uint32_t leds;
-    uint32_t brk;
-    uint32_t gpout;
-    uint32_t i2cin;
-    uint32_t i2coe;
-    uint32_t i2cout;
-    uint32_t i2csel;
-    CharDriverState *display;
-    char display_text[9];
-    SerialState *uart;
-} MaltaFPGAState;
-
-typedef struct {
-    SysBusDevice busdev;
-    qemu_irq *i8259;
-} MaltaState;
-
-static ISADevice *pit;
-
-static struct _loaderparams {
-    int ram_size;
-    const char *kernel_filename;
-    const char *kernel_cmdline;
-    const char *initrd_filename;
-} loaderparams;
-
-/* Malta FPGA */
-static void malta_fpga_update_display(void *opaque)
-{
-    char leds_text[9];
-    int i;
-    MaltaFPGAState *s = opaque;
-
-    for (i = 7 ; i >= 0 ; i--) {
-        if (s->leds & (1 << i))
-            leds_text[i] = '#';
-        else
-            leds_text[i] = ' ';
-    }
-    leds_text[8] = '\0';
-
-    qemu_chr_fe_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
-    qemu_chr_fe_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
-}
-
-/*
- * EEPROM 24C01 / 24C02 emulation.
- *
- * Emulation for serial EEPROMs:
- * 24C01 - 1024 bit (128 x 8)
- * 24C02 - 2048 bit (256 x 8)
- *
- * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
- */
-
-//~ #define DEBUG
-
-#if defined(DEBUG)
-#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
-#else
-#  define logout(fmt, ...) ((void)0)
-#endif
-
-struct _eeprom24c0x_t {
-  uint8_t tick;
-  uint8_t address;
-  uint8_t command;
-  uint8_t ack;
-  uint8_t scl;
-  uint8_t sda;
-  uint8_t data;
-  //~ uint16_t size;
-  uint8_t contents[256];
-};
-
-typedef struct _eeprom24c0x_t eeprom24c0x_t;
-
-static eeprom24c0x_t eeprom = {
-    .contents = {
-        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
-        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
-        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
-        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
-        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
-        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
-        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
-    },
-};
-
-static uint8_t eeprom24c0x_read(void)
-{
-    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
-        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
-    return eeprom.sda;
-}
-
-static void eeprom24c0x_write(int scl, int sda)
-{
-    if (eeprom.scl && scl && (eeprom.sda != sda)) {
-        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
-                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
-        if (!sda) {
-            eeprom.tick = 1;
-            eeprom.command = 0;
-        }
-    } else if (eeprom.tick == 0 && !eeprom.ack) {
-        /* Waiting for start. */
-        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
-                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
-    } else if (!eeprom.scl && scl) {
-        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
-                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
-        if (eeprom.ack) {
-            logout("\ti2c ack bit = 0\n");
-            sda = 0;
-            eeprom.ack = 0;
-        } else if (eeprom.sda == sda) {
-            uint8_t bit = (sda != 0);
-            logout("\ti2c bit = %d\n", bit);
-            if (eeprom.tick < 9) {
-                eeprom.command <<= 1;
-                eeprom.command += bit;
-                eeprom.tick++;
-                if (eeprom.tick == 9) {
-                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
-                    eeprom.ack = 1;
-                }
-            } else if (eeprom.tick < 17) {
-                if (eeprom.command & 1) {
-                    sda = ((eeprom.data & 0x80) != 0);
-                }
-                eeprom.address <<= 1;
-                eeprom.address += bit;
-                eeprom.tick++;
-                eeprom.data <<= 1;
-                if (eeprom.tick == 17) {
-                    eeprom.data = eeprom.contents[eeprom.address];
-                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
-                    eeprom.ack = 1;
-                    eeprom.tick = 0;
-                }
-            } else if (eeprom.tick >= 17) {
-                sda = 0;
-            }
-        } else {
-            logout("\tsda changed with raising scl\n");
-        }
-    } else {
-        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
-    }
-    eeprom.scl = scl;
-    eeprom.sda = sda;
-}
-
-static uint64_t malta_fpga_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    MaltaFPGAState *s = opaque;
-    uint32_t val = 0;
-    uint32_t saddr;
-
-    saddr = (addr & 0xfffff);
-
-    switch (saddr) {
-
-    /* SWITCH Register */
-    case 0x00200:
-        val = 0x00000000;              /* All switches closed */
-        break;
-
-    /* STATUS Register */
-    case 0x00208:
-#ifdef TARGET_WORDS_BIGENDIAN
-        val = 0x00000012;
-#else
-        val = 0x00000010;
-#endif
-        break;
-
-    /* JMPRS Register */
-    case 0x00210:
-        val = 0x00;
-        break;
-
-    /* LEDBAR Register */
-    case 0x00408:
-        val = s->leds;
-        break;
-
-    /* BRKRES Register */
-    case 0x00508:
-        val = s->brk;
-        break;
-
-    /* UART Registers are handled directly by the serial device */
-
-    /* GPOUT Register */
-    case 0x00a00:
-        val = s->gpout;
-        break;
-
-    /* XXX: implement a real I2C controller */
-
-    /* GPINP Register */
-    case 0x00a08:
-        /* IN = OUT until a real I2C control is implemented */
-        if (s->i2csel)
-            val = s->i2cout;
-        else
-            val = 0x00;
-        break;
-
-    /* I2CINP Register */
-    case 0x00b00:
-        val = ((s->i2cin & ~1) | eeprom24c0x_read());
-        break;
-
-    /* I2COE Register */
-    case 0x00b08:
-        val = s->i2coe;
-        break;
-
-    /* I2COUT Register */
-    case 0x00b10:
-        val = s->i2cout;
-        break;
-
-    /* I2CSEL Register */
-    case 0x00b18:
-        val = s->i2csel;
-        break;
-
-    default:
-#if 0
-        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
-                addr);
-#endif
-        break;
-    }
-    return val;
-}
-
-static void malta_fpga_write(void *opaque, hwaddr addr,
-                             uint64_t val, unsigned size)
-{
-    MaltaFPGAState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr & 0xfffff);
-
-    switch (saddr) {
-
-    /* SWITCH Register */
-    case 0x00200:
-        break;
-
-    /* JMPRS Register */
-    case 0x00210:
-        break;
-
-    /* LEDBAR Register */
-    case 0x00408:
-        s->leds = val & 0xff;
-        malta_fpga_update_display(s);
-        break;
-
-    /* ASCIIWORD Register */
-    case 0x00410:
-        snprintf(s->display_text, 9, "%08X", (uint32_t)val);
-        malta_fpga_update_display(s);
-        break;
-
-    /* ASCIIPOS0 to ASCIIPOS7 Registers */
-    case 0x00418:
-    case 0x00420:
-    case 0x00428:
-    case 0x00430:
-    case 0x00438:
-    case 0x00440:
-    case 0x00448:
-    case 0x00450:
-        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
-        malta_fpga_update_display(s);
-        break;
-
-    /* SOFTRES Register */
-    case 0x00500:
-        if (val == 0x42)
-            qemu_system_reset_request ();
-        break;
-
-    /* BRKRES Register */
-    case 0x00508:
-        s->brk = val & 0xff;
-        break;
-
-    /* UART Registers are handled directly by the serial device */
-
-    /* GPOUT Register */
-    case 0x00a00:
-        s->gpout = val & 0xff;
-        break;
-
-    /* I2COE Register */
-    case 0x00b08:
-        s->i2coe = val & 0x03;
-        break;
-
-    /* I2COUT Register */
-    case 0x00b10:
-        eeprom24c0x_write(val & 0x02, val & 0x01);
-        s->i2cout = val;
-        break;
-
-    /* I2CSEL Register */
-    case 0x00b18:
-        s->i2csel = val & 0x01;
-        break;
-
-    default:
-#if 0
-        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
-                addr);
-#endif
-        break;
-    }
-}
-
-static const MemoryRegionOps malta_fpga_ops = {
-    .read = malta_fpga_read,
-    .write = malta_fpga_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void malta_fpga_reset(void *opaque)
-{
-    MaltaFPGAState *s = opaque;
-
-    s->leds   = 0x00;
-    s->brk    = 0x0a;
-    s->gpout  = 0x00;
-    s->i2cin  = 0x3;
-    s->i2coe  = 0x0;
-    s->i2cout = 0x3;
-    s->i2csel = 0x1;
-
-    s->display_text[8] = '\0';
-    snprintf(s->display_text, 9, "        ");
-}
-
-static void malta_fpga_led_init(CharDriverState *chr)
-{
-    qemu_chr_fe_printf(chr, "\e[HMalta LEDBAR\r\n");
-    qemu_chr_fe_printf(chr, "+--------+\r\n");
-    qemu_chr_fe_printf(chr, "+        +\r\n");
-    qemu_chr_fe_printf(chr, "+--------+\r\n");
-    qemu_chr_fe_printf(chr, "\n");
-    qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
-    qemu_chr_fe_printf(chr, "+--------+\r\n");
-    qemu_chr_fe_printf(chr, "+        +\r\n");
-    qemu_chr_fe_printf(chr, "+--------+\r\n");
-}
-
-static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
-         hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr)
-{
-    MaltaFPGAState *s;
-
-    s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
-
-    memory_region_init_io(&s->iomem, &malta_fpga_ops, s,
-                          "malta-fpga", 0x100000);
-    memory_region_init_alias(&s->iomem_lo, "malta-fpga",
-                             &s->iomem, 0, 0x900);
-    memory_region_init_alias(&s->iomem_hi, "malta-fpga",
-                             &s->iomem, 0xa00, 0x10000-0xa00);
-
-    memory_region_add_subregion(address_space, base, &s->iomem_lo);
-    memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
-
-    s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
-
-    s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
-                             230400, uart_chr, DEVICE_NATIVE_ENDIAN);
-
-    malta_fpga_reset(s);
-    qemu_register_reset(malta_fpga_reset, s);
-
-    return s;
-}
-
-/* Network support */
-static void network_init(void)
-{
-    int i;
-
-    for(i = 0; i < nb_nics; i++) {
-        NICInfo *nd = &nd_table[i];
-        const char *default_devaddr = NULL;
-
-        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
-            /* The malta board has a PCNet card using PCI SLOT 11 */
-            default_devaddr = "0b";
-
-        pci_nic_init_nofail(nd, "pcnet", default_devaddr);
-    }
-}
-
-/* ROM and pseudo bootloader
-
-   The following code implements a very very simple bootloader. It first
-   loads the registers a0 to a3 to the values expected by the OS, and
-   then jump at the kernel address.
-
-   The bootloader should pass the locations of the kernel arguments and
-   environment variables tables. Those tables contain the 32-bit address
-   of NULL terminated strings. The environment variables table should be
-   terminated by a NULL address.
-
-   For a simpler implementation, the number of kernel arguments is fixed
-   to two (the name of the kernel and the command line), and the two
-   tables are actually the same one.
-
-   The registers a0 to a3 should contain the following values:
-     a0 - number of kernel arguments
-     a1 - 32-bit address of the kernel arguments table
-     a2 - 32-bit address of the environment variables table
-     a3 - RAM size in bytes
-*/
-
-static void write_bootloader (CPUMIPSState *env, uint8_t *base,
-                              int64_t kernel_entry)
-{
-    uint32_t *p;
-
-    /* Small bootloader */
-    p = (uint32_t *)base;
-    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
-    stl_raw(p++, 0x00000000);                                      /* nop */
-
-    /* YAMON service vector */
-    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
-    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
-    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
-    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
-    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
-    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
-    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
-    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
-    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
-    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
-    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
-    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
-    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
-
-
-    /* Second part of the bootloader */
-    p = (uint32_t *) (base + 0x580);
-    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
-    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
-    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
-    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
-    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
-    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
-    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
-
-    /* Load BAR registers as done by YAMON */
-    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
-#else
-    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
-#endif
-    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
-
-    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
-#else
-    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
-#endif
-    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
-#else
-    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
-#endif
-    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
-#else
-    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
-#endif
-    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
-#else
-    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
-#endif
-    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
-#else
-    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
-#endif
-    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
-#else
-    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
-#endif
-    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
-
-    /* Jump to kernel code */
-    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
-    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
-    stl_raw(p++, 0x03e00008);                                      /* jr ra */
-    stl_raw(p++, 0x00000000);                                      /* nop */
-
-    /* YAMON subroutines */
-    p = (uint32_t *) (base + 0x800);
-    stl_raw(p++, 0x03e00008);                                     /* jr ra */
-    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
-   /* 808 YAMON print */
-    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
-    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
-    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
-    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
-    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
-    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x08000205);                                     /* j 814 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
-    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
-    /* 0x83c YAMON print_count */
-    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
-    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
-    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
-    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
-    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
-    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
-    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
-    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
-    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
-    /* 0x870 */
-    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
-    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
-    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
-    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x03e00008);                                     /* jr ra */
-    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
-
-}
-
-static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
-                                        const char *string, ...)
-{
-    va_list ap;
-    int32_t table_addr;
-
-    if (index >= ENVP_NB_ENTRIES)
-        return;
-
-    if (string == NULL) {
-        prom_buf[index] = 0;
-        return;
-    }
-
-    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
-    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
-
-    va_start(ap, string);
-    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
-    va_end(ap);
-}
-
-/* Kernel */
-static int64_t load_kernel (void)
-{
-    int64_t kernel_entry, kernel_high;
-    long initrd_size;
-    ram_addr_t initrd_offset;
-    int big_endian;
-    uint32_t *prom_buf;
-    long prom_size;
-    int prom_index = 0;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    big_endian = 1;
-#else
-    big_endian = 0;
-#endif
-
-    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
-                 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
-                 big_endian, ELF_MACHINE, 1) < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                loaderparams.kernel_filename);
-        exit(1);
-    }
-
-    /* load initrd */
-    initrd_size = 0;
-    initrd_offset = 0;
-    if (loaderparams.initrd_filename) {
-        initrd_size = get_image_size (loaderparams.initrd_filename);
-        if (initrd_size > 0) {
-            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
-            if (initrd_offset + initrd_size > ram_size) {
-                fprintf(stderr,
-                        "qemu: memory too small for initial ram disk '%s'\n",
-                        loaderparams.initrd_filename);
-                exit(1);
-            }
-            initrd_size = load_image_targphys(loaderparams.initrd_filename,
-                                              initrd_offset,
-                                              ram_size - initrd_offset);
-        }
-        if (initrd_size == (target_ulong) -1) {
-            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                    loaderparams.initrd_filename);
-            exit(1);
-        }
-    }
-
-    /* Setup prom parameters. */
-    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
-    prom_buf = g_malloc(prom_size);
-
-    prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename);
-    if (initrd_size > 0) {
-        prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
-                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
-                 loaderparams.kernel_cmdline);
-    } else {
-        prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_cmdline);
-    }
-
-    prom_set(prom_buf, prom_index++, "memsize");
-    prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
-    prom_set(prom_buf, prom_index++, "modetty0");
-    prom_set(prom_buf, prom_index++, "38400n8r");
-    prom_set(prom_buf, prom_index++, NULL);
-
-    rom_add_blob_fixed("prom", prom_buf, prom_size,
-                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
-
-    return kernel_entry;
-}
-
-static void malta_mips_config(MIPSCPU *cpu)
-{
-    CPUMIPSState *env = &cpu->env;
-    CPUState *cs = CPU(cpu);
-
-    env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
-                         ((smp_cpus * cs->nr_threads - 1) << CP0MVPC0_PTC);
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    MIPSCPU *cpu = opaque;
-    CPUMIPSState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-
-    /* The bootloader does not need to be rewritten as it is located in a
-       read only location. The kernel location and the arguments table
-       location does not change. */
-    if (loaderparams.kernel_filename) {
-        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
-    }
-
-    malta_mips_config(cpu);
-}
-
-static void cpu_request_exit(void *opaque, int irq, int level)
-{
-    CPUMIPSState *env = cpu_single_env;
-
-    if (env && level) {
-        cpu_exit(env);
-    }
-}
-
-static
-void mips_malta_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    pflash_t *fl;
-    MemoryRegion *system_memory = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
-    target_long bios_size = FLASH_SIZE;
-    int64_t kernel_entry;
-    PCIBus *pci_bus;
-    ISABus *isa_bus;
-    MIPSCPU *cpu;
-    CPUMIPSState *env;
-    qemu_irq *isa_irq;
-    qemu_irq *cpu_exit_irq;
-    int piix4_devfn;
-    i2c_bus *smbus;
-    int i;
-    DriveInfo *dinfo;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    DriveInfo *fd[MAX_FD];
-    int fl_idx = 0;
-    int fl_sectors = bios_size >> 16;
-    int be;
-
-    DeviceState *dev = qdev_create(NULL, "mips-malta");
-    MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev);
-
-    qdev_init_nofail(dev);
-
-    /* Make sure the first 3 serial ports are associated with a device. */
-    for(i = 0; i < 3; i++) {
-        if (!serial_hds[i]) {
-            char label[32];
-            snprintf(label, sizeof(label), "serial%d", i);
-            serial_hds[i] = qemu_chr_new(label, "null", NULL);
-        }
-    }
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-#ifdef TARGET_MIPS64
-        cpu_model = "20Kc";
-#else
-        cpu_model = "24Kf";
-#endif
-    }
-
-    for (i = 0; i < smp_cpus; i++) {
-        cpu = cpu_mips_init(cpu_model);
-        if (cpu == NULL) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        env = &cpu->env;
-
-        /* Init internal devices */
-        cpu_mips_irq_init_cpu(env);
-        cpu_mips_clock_init(env);
-        qemu_register_reset(main_cpu_reset, cpu);
-    }
-    env = first_cpu;
-
-    /* allocate RAM */
-    if (ram_size > (256 << 20)) {
-        fprintf(stderr,
-                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
-                ((unsigned int)ram_size / (1 << 20)));
-        exit(1);
-    }
-    memory_region_init_ram(ram, "mips_malta.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(system_memory, 0, ram);
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    /* FPGA */
-    /* The CBUS UART is attached to the MIPS CPU INT2 pin, ie interrupt 4 */
-    malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[4], serial_hds[2]);
-
-    /* Load firmware in flash / BIOS. */
-    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
-#ifdef DEBUG_BOARD_INIT
-    if (dinfo) {
-        printf("Register parallel flash %d size " TARGET_FMT_lx " at "
-               "addr %08llx '%s' %x\n",
-               fl_idx, bios_size, FLASH_ADDRESS,
-               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
-    }
-#endif
-    fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
-                               BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
-                               65536, fl_sectors,
-                               4, 0x0000, 0x0000, 0x0000, 0x0000, be);
-    bios = pflash_cfi01_get_memory(fl);
-    fl_idx++;
-    if (kernel_filename) {
-        /* Write a small bootloader to the flash location. */
-        loaderparams.ram_size = ram_size;
-        loaderparams.kernel_filename = kernel_filename;
-        loaderparams.kernel_cmdline = kernel_cmdline;
-        loaderparams.initrd_filename = initrd_filename;
-        kernel_entry = load_kernel();
-        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
-    } else {
-        /* Load firmware from flash. */
-        if (!dinfo) {
-            /* Load a BIOS image. */
-            if (bios_name == NULL) {
-                bios_name = BIOS_FILENAME;
-            }
-            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-            if (filename) {
-                bios_size = load_image_targphys(filename, FLASH_ADDRESS,
-                                                BIOS_SIZE);
-                g_free(filename);
-            } else {
-                bios_size = -1;
-            }
-            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
-                fprintf(stderr,
-                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
-                        bios_name);
-                exit(1);
-            }
-        }
-        /* In little endian mode the 32bit words in the bios are swapped,
-           a neat trick which allows bi-endian firmware. */
-#ifndef TARGET_WORDS_BIGENDIAN
-        {
-            uint32_t *addr = memory_region_get_ram_ptr(bios);
-            uint32_t *end = addr + bios_size;
-            while (addr < end) {
-                bswap32s(addr);
-                addr++;
-            }
-        }
-#endif
-    }
-
-    /* Map the BIOS at a 2nd physical location, as on the real board. */
-    memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
-    memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias);
-
-    /* Board ID = 0x420 (Malta Board with CoreLV)
-       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
-       map to the board ID. */
-    stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
-
-    /* Init internal devices */
-    cpu_mips_irq_init_cpu(env);
-    cpu_mips_clock_init(env);
-
-    /*
-     * We have a circular dependency problem: pci_bus depends on isa_irq,
-     * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
-     * on piix4, and piix4 depends on pci_bus.  To stop the cycle we have
-     * qemu_irq_proxy() adds an extra bit of indirection, allowing us
-     * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
-     */
-    isa_irq = qemu_irq_proxy(&s->i8259, 16);
-
-    /* Northbridge */
-    pci_bus = gt64120_register(isa_irq);
-
-    /* Southbridge */
-    ide_drive_get(hd, MAX_IDE_BUS);
-
-    piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
-
-    /* Interrupt controller */
-    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
-    s->i8259 = i8259_init(isa_bus, env->irq[2]);
-
-    isa_bus_irqs(isa_bus, s->i8259);
-    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
-    pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
-    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
-                          isa_get_irq(NULL, 9), NULL, 0, NULL);
-    /* TODO: Populate SPD eeprom data.  */
-    smbus_eeprom_init(smbus, 8, NULL, 0);
-    pit = pit_init(isa_bus, 0x40, 0, NULL);
-    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
-    DMA_init(0, cpu_exit_irq);
-
-    /* Super I/O */
-    isa_create_simple(isa_bus, "i8042");
-
-    rtc_init(isa_bus, 2000, NULL);
-    serial_isa_init(isa_bus, 0, serial_hds[0]);
-    serial_isa_init(isa_bus, 1, serial_hds[1]);
-    if (parallel_hds[0])
-        parallel_init(isa_bus, 0, parallel_hds[0]);
-    for(i = 0; i < MAX_FD; i++) {
-        fd[i] = drive_get(IF_FLOPPY, 0, i);
-    }
-    fdctrl_init_isa(isa_bus, fd);
-
-    /* Sound card */
-    audio_init(isa_bus, pci_bus);
-
-    /* Network card */
-    network_init();
-
-    /* Optional PCI video card */
-    pci_vga_init(pci_bus);
-}
-
-static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
-{
-    return 0;
-}
-
-static void mips_malta_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mips_malta_sysbus_device_init;
-}
-
-static const TypeInfo mips_malta_device = {
-    .name          = "mips-malta",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(MaltaState),
-    .class_init    = mips_malta_class_init,
-};
-
-static QEMUMachine mips_malta_machine = {
-    .name = "malta",
-    .desc = "MIPS Malta Core LV",
-    .init = mips_malta_init,
-    .max_cpus = 16,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mips_malta_register_types(void)
-{
-    type_register_static(&mips_malta_device);
-}
-
-static void mips_malta_machine_init(void)
-{
-    qemu_register_machine(&mips_malta_machine);
-}
-
-type_init(mips_malta_register_types)
-machine_init(mips_malta_machine_init);
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
deleted file mode 100644 (file)
index b0ab8f6..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * QEMU/mipssim emulation
- *
- * Emulates a very simple machine model similar to the one used by the
- * proprietary MIPS emulator.
- * 
- * Copyright (c) 2007 Thiemo Seufer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "mips.h"
-#include "mips_cpudevs.h"
-#include "serial.h"
-#include "isa.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "mips-bios.h"
-#include "loader.h"
-#include "elf.h"
-#include "sysbus.h"
-#include "exec/address-spaces.h"
-
-static struct _loaderparams {
-    int ram_size;
-    const char *kernel_filename;
-    const char *kernel_cmdline;
-    const char *initrd_filename;
-} loaderparams;
-
-typedef struct ResetData {
-    MIPSCPU *cpu;
-    uint64_t vector;
-} ResetData;
-
-static int64_t load_kernel(void)
-{
-    int64_t entry, kernel_high;
-    long kernel_size;
-    long initrd_size;
-    ram_addr_t initrd_offset;
-    int big_endian;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    big_endian = 1;
-#else
-    big_endian = 0;
-#endif
-
-    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
-                           NULL, (uint64_t *)&entry, NULL,
-                           (uint64_t *)&kernel_high, big_endian,
-                           ELF_MACHINE, 1);
-    if (kernel_size >= 0) {
-        if ((entry & ~0x7fffffffULL) == 0x80000000)
-            entry = (int32_t)entry;
-    } else {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                loaderparams.kernel_filename);
-        exit(1);
-    }
-
-    /* load initrd */
-    initrd_size = 0;
-    initrd_offset = 0;
-    if (loaderparams.initrd_filename) {
-        initrd_size = get_image_size (loaderparams.initrd_filename);
-        if (initrd_size > 0) {
-            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
-            if (initrd_offset + initrd_size > loaderparams.ram_size) {
-                fprintf(stderr,
-                        "qemu: memory too small for initial ram disk '%s'\n",
-                        loaderparams.initrd_filename);
-                exit(1);
-            }
-            initrd_size = load_image_targphys(loaderparams.initrd_filename,
-                initrd_offset, loaderparams.ram_size - initrd_offset);
-        }
-        if (initrd_size == (target_ulong) -1) {
-            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                    loaderparams.initrd_filename);
-            exit(1);
-        }
-    }
-    return entry;
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetData *s = (ResetData *)opaque;
-    CPUMIPSState *env = &s->cpu->env;
-
-    cpu_reset(CPU(s->cpu));
-    env->active_tc.PC = s->vector & ~(target_ulong)1;
-    if (s->vector & 1) {
-        env->hflags |= MIPS_HFLAG_M16;
-    }
-}
-
-static void mipsnet_init(int base, qemu_irq irq, NICInfo *nd)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "mipsnet");
-    qdev_set_nic_properties(dev, nd);
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, irq);
-    memory_region_add_subregion(get_system_io(),
-                                base,
-                                sysbus_mmio_get_region(s, 0));
-}
-
-static void
-mips_mipssim_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *bios = g_new(MemoryRegion, 1);
-    MIPSCPU *cpu;
-    CPUMIPSState *env;
-    ResetData *reset_info;
-    int bios_size;
-
-    /* Init CPUs. */
-    if (cpu_model == NULL) {
-#ifdef TARGET_MIPS64
-        cpu_model = "5Kf";
-#else
-        cpu_model = "24Kf";
-#endif
-    }
-    cpu = cpu_mips_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->cpu = cpu;
-    reset_info->vector = env->active_tc.PC;
-    qemu_register_reset(main_cpu_reset, reset_info);
-
-    /* Allocate RAM. */
-    memory_region_init_ram(ram, "mips_mipssim.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_init_ram(bios, "mips_mipssim.bios", BIOS_SIZE);
-    vmstate_register_ram_global(bios);
-    memory_region_set_readonly(bios, true);
-
-    memory_region_add_subregion(address_space_mem, 0, ram);
-
-    /* Map the BIOS / boot exception handler. */
-    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
-    /* Load a BIOS / boot exception handler image. */
-    if (bios_name == NULL)
-        bios_name = BIOS_FILENAME;
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (filename) {
-        bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE);
-        g_free(filename);
-    } else {
-        bios_size = -1;
-    }
-    if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
-        /* Bail out if we have neither a kernel image nor boot vector code. */
-        fprintf(stderr,
-                "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
-                filename);
-        exit(1);
-    } else {
-        /* We have a boot vector start address. */
-        env->active_tc.PC = (target_long)(int32_t)0xbfc00000;
-    }
-
-    if (kernel_filename) {
-        loaderparams.ram_size = ram_size;
-        loaderparams.kernel_filename = kernel_filename;
-        loaderparams.kernel_cmdline = kernel_cmdline;
-        loaderparams.initrd_filename = initrd_filename;
-        reset_info->vector = load_kernel();
-    }
-
-    /* Init CPU internal devices. */
-    cpu_mips_irq_init_cpu(env);
-    cpu_mips_clock_init(env);
-
-    /* Register 64 KB of ISA IO space at 0x1fd00000. */
-    isa_mmio_init(0x1fd00000, 0x00010000);
-
-    /* A single 16450 sits at offset 0x3f8. It is attached to
-       MIPS CPU INT2, which is interrupt 4. */
-    if (serial_hds[0])
-        serial_init(0x3f8, env->irq[4], 115200, serial_hds[0],
-                    get_system_io());
-
-    if (nd_table[0].used)
-        /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
-        mipsnet_init(0x4200, env->irq[2], &nd_table[0]);
-}
-
-static QEMUMachine mips_mipssim_machine = {
-    .name = "mipssim",
-    .desc = "MIPS MIPSsim platform",
-    .init = mips_mipssim_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mips_mipssim_machine_init(void)
-{
-    qemu_register_machine(&mips_mipssim_machine);
-}
-
-machine_init(mips_mipssim_machine_init);
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
deleted file mode 100644 (file)
index 5df7eb4..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * QEMU/MIPS pseudo-board
- *
- * emulates a simple machine with ISA-like bus.
- * ISA IO space mapped to the 0x14000000 (PHYS) and
- * ISA memory at the 0x10000000 (PHYS, 16Mb in size).
- * All peripherial devices are attached to this "bus" with
- * the standard PC ISA addresses.
-*/
-#include "hw.h"
-#include "mips.h"
-#include "mips_cpudevs.h"
-#include "pc.h"
-#include "serial.h"
-#include "isa.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "flash.h"
-#include "qemu/log.h"
-#include "mips-bios.h"
-#include "ide.h"
-#include "loader.h"
-#include "elf.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define MAX_IDE_BUS 2
-
-static const int ide_iobase[2] = { 0x1f0, 0x170 };
-static const int ide_iobase2[2] = { 0x3f6, 0x376 };
-static const int ide_irq[2] = { 14, 15 };
-
-static ISADevice *pit; /* PIT i8254 */
-
-/* i8254 PIT is attached to the IRQ0 at PIC i8259 */
-
-static struct _loaderparams {
-    int ram_size;
-    const char *kernel_filename;
-    const char *kernel_cmdline;
-    const char *initrd_filename;
-} loaderparams;
-
-static void mips_qemu_write (void *opaque, hwaddr addr,
-                             uint64_t val, unsigned size)
-{
-    if ((addr & 0xffff) == 0 && val == 42)
-        qemu_system_reset_request ();
-    else if ((addr & 0xffff) == 4 && val == 42)
-        qemu_system_shutdown_request ();
-}
-
-static uint64_t mips_qemu_read (void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    return 0;
-}
-
-static const MemoryRegionOps mips_qemu_ops = {
-    .read = mips_qemu_read,
-    .write = mips_qemu_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-typedef struct ResetData {
-    MIPSCPU *cpu;
-    uint64_t vector;
-} ResetData;
-
-static int64_t load_kernel(void)
-{
-    int64_t entry, kernel_high;
-    long kernel_size, initrd_size, params_size;
-    ram_addr_t initrd_offset;
-    uint32_t *params_buf;
-    int big_endian;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    big_endian = 1;
-#else
-    big_endian = 0;
-#endif
-    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
-                           NULL, (uint64_t *)&entry, NULL,
-                           (uint64_t *)&kernel_high, big_endian,
-                           ELF_MACHINE, 1);
-    if (kernel_size >= 0) {
-        if ((entry & ~0x7fffffffULL) == 0x80000000)
-            entry = (int32_t)entry;
-    } else {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                loaderparams.kernel_filename);
-        exit(1);
-    }
-
-    /* load initrd */
-    initrd_size = 0;
-    initrd_offset = 0;
-    if (loaderparams.initrd_filename) {
-        initrd_size = get_image_size (loaderparams.initrd_filename);
-        if (initrd_size > 0) {
-            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
-            if (initrd_offset + initrd_size > ram_size) {
-                fprintf(stderr,
-                        "qemu: memory too small for initial ram disk '%s'\n",
-                        loaderparams.initrd_filename);
-                exit(1);
-            }
-            initrd_size = load_image_targphys(loaderparams.initrd_filename,
-                                              initrd_offset,
-                                              ram_size - initrd_offset);
-        }
-        if (initrd_size == (target_ulong) -1) {
-            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                    loaderparams.initrd_filename);
-            exit(1);
-        }
-    }
-
-    /* Store command line.  */
-    params_size = 264;
-    params_buf = g_malloc(params_size);
-
-    params_buf[0] = tswap32(ram_size);
-    params_buf[1] = tswap32(0x12345678);
-
-    if (initrd_size > 0) {
-        snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%li %s",
-                 cpu_mips_phys_to_kseg0(NULL, initrd_offset),
-                 initrd_size, loaderparams.kernel_cmdline);
-    } else {
-        snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline);
-    }
-
-    rom_add_blob_fixed("params", params_buf, params_size,
-                       (16 << 20) - 264);
-
-    return entry;
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetData *s = (ResetData *)opaque;
-    CPUMIPSState *env = &s->cpu->env;
-
-    cpu_reset(CPU(s->cpu));
-    env->active_tc.PC = s->vector;
-}
-
-static const int sector_len = 32 * 1024;
-static
-void mips_r4k_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *bios;
-    MemoryRegion *iomem = g_new(MemoryRegion, 1);
-    int bios_size;
-    MIPSCPU *cpu;
-    CPUMIPSState *env;
-    ResetData *reset_info;
-    int i;
-    qemu_irq *i8259;
-    ISABus *isa_bus;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    DriveInfo *dinfo;
-    int be;
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-#ifdef TARGET_MIPS64
-        cpu_model = "R4000";
-#else
-        cpu_model = "24Kf";
-#endif
-    }
-    cpu = cpu_mips_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->cpu = cpu;
-    reset_info->vector = env->active_tc.PC;
-    qemu_register_reset(main_cpu_reset, reset_info);
-
-    /* allocate RAM */
-    if (ram_size > (256 << 20)) {
-        fprintf(stderr,
-                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
-                ((unsigned int)ram_size / (1 << 20)));
-        exit(1);
-    }
-    memory_region_init_ram(ram, "mips_r4k.ram", ram_size);
-    vmstate_register_ram_global(ram);
-
-    memory_region_add_subregion(address_space_mem, 0, ram);
-
-    memory_region_init_io(iomem, &mips_qemu_ops, NULL, "mips-qemu", 0x10000);
-    memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem);
-
-    /* Try to load a BIOS image. If this fails, we continue regardless,
-       but initialize the hardware ourselves. When a kernel gets
-       preloaded we also initialize the hardware, since the BIOS wasn't
-       run. */
-    if (bios_name == NULL)
-        bios_name = BIOS_FILENAME;
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (filename) {
-        bios_size = get_image_size(filename);
-    } else {
-        bios_size = -1;
-    }
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
-        bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, "mips_r4k.bios", BIOS_SIZE);
-        vmstate_register_ram_global(bios);
-        memory_region_set_readonly(bios, true);
-        memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
-
-        load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
-    } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
-        uint32_t mips_rom = 0x00400000;
-        if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
-                                   dinfo->bdrv, sector_len,
-                                   mips_rom / sector_len,
-                                   4, 0, 0, 0, 0, be)) {
-            fprintf(stderr, "qemu: Error registering flash memory.\n");
-       }
-    }
-    else {
-       /* not fatal */
-        fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
-               bios_name);
-    }
-    if (filename) {
-        g_free(filename);
-    }
-
-    if (kernel_filename) {
-        loaderparams.ram_size = ram_size;
-        loaderparams.kernel_filename = kernel_filename;
-        loaderparams.kernel_cmdline = kernel_cmdline;
-        loaderparams.initrd_filename = initrd_filename;
-        reset_info->vector = load_kernel();
-    }
-
-    /* Init CPU internal devices */
-    cpu_mips_irq_init_cpu(env);
-    cpu_mips_clock_init(env);
-
-    /* The PIC is attached to the MIPS CPU INT0 pin */
-    isa_bus = isa_bus_new(NULL, get_system_io());
-    i8259 = i8259_init(isa_bus, env->irq[2]);
-    isa_bus_irqs(isa_bus, i8259);
-
-    rtc_init(isa_bus, 2000, NULL);
-
-    /* Register 64 KB of ISA IO space at 0x14000000 */
-    isa_mmio_init(0x14000000, 0x00010000);
-    isa_mem_base = 0x10000000;
-
-    pit = pit_init(isa_bus, 0x40, 0, NULL);
-
-    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_hds[i]) {
-            serial_isa_init(isa_bus, i, serial_hds[i]);
-        }
-    }
-
-    isa_vga_init(isa_bus);
-
-    if (nd_table[0].used)
-        isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]);
-
-    ide_drive_get(hd, MAX_IDE_BUS);
-    for(i = 0; i < MAX_IDE_BUS; i++)
-        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]);
-
-    isa_create_simple(isa_bus, "i8042");
-}
-
-static QEMUMachine mips_machine = {
-    .name = "mips",
-    .desc = "mips r4k platform",
-    .init = mips_r4k_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mips_machine_init(void)
-{
-    qemu_register_machine(&mips_machine);
-}
-
-machine_init(mips_machine_init);
diff --git a/hw/mips_timer.c b/hw/mips_timer.c
deleted file mode 100644 (file)
index 83c400c..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * QEMU MIPS timer support
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw.h"
-#include "mips_cpudevs.h"
-#include "qemu/timer.h"
-
-#define TIMER_FREQ     100 * 1000 * 1000
-
-/* XXX: do not use a global */
-uint32_t cpu_mips_get_random (CPUMIPSState *env)
-{
-    static uint32_t lfsr = 1;
-    static uint32_t prev_idx = 0;
-    uint32_t idx;
-    /* Don't return same value twice, so get another value */
-    do {
-        lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u);
-        idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
-    } while (idx == prev_idx);
-    prev_idx = idx;
-    return idx;
-}
-
-/* MIPS R4K timer */
-static void cpu_mips_timer_update(CPUMIPSState *env)
-{
-    uint64_t now, next;
-    uint32_t wait;
-
-    now = qemu_get_clock_ns(vm_clock);
-    wait = env->CP0_Compare - env->CP0_Count -
-           (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
-    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
-    qemu_mod_timer(env->timer, next);
-}
-
-/* Expire the timer.  */
-static void cpu_mips_timer_expire(CPUMIPSState *env)
-{
-    cpu_mips_timer_update(env);
-    if (env->insn_flags & ISA_MIPS32R2) {
-        env->CP0_Cause |= 1 << CP0Ca_TI;
-    }
-    qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
-}
-
-uint32_t cpu_mips_get_count (CPUMIPSState *env)
-{
-    if (env->CP0_Cause & (1 << CP0Ca_DC)) {
-        return env->CP0_Count;
-    } else {
-        uint64_t now;
-
-        now = qemu_get_clock_ns(vm_clock);
-        if (qemu_timer_pending(env->timer)
-            && qemu_timer_expired(env->timer, now)) {
-            /* The timer has already expired.  */
-            cpu_mips_timer_expire(env);
-        }
-
-        return env->CP0_Count +
-            (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
-    }
-}
-
-void cpu_mips_store_count (CPUMIPSState *env, uint32_t count)
-{
-    if (env->CP0_Cause & (1 << CP0Ca_DC))
-        env->CP0_Count = count;
-    else {
-        /* Store new count register */
-        env->CP0_Count =
-            count - (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
-                                       TIMER_FREQ, get_ticks_per_sec());
-        /* Update timer timer */
-        cpu_mips_timer_update(env);
-    }
-}
-
-void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value)
-{
-    env->CP0_Compare = value;
-    if (!(env->CP0_Cause & (1 << CP0Ca_DC)))
-        cpu_mips_timer_update(env);
-    if (env->insn_flags & ISA_MIPS32R2)
-        env->CP0_Cause &= ~(1 << CP0Ca_TI);
-    qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
-}
-
-void cpu_mips_start_count(CPUMIPSState *env)
-{
-    cpu_mips_store_count(env, env->CP0_Count);
-}
-
-void cpu_mips_stop_count(CPUMIPSState *env)
-{
-    /* Store the current value */
-    env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
-                                         TIMER_FREQ, get_ticks_per_sec());
-}
-
-static void mips_timer_cb (void *opaque)
-{
-    CPUMIPSState *env;
-
-    env = opaque;
-#if 0
-    qemu_log("%s\n", __func__);
-#endif
-
-    if (env->CP0_Cause & (1 << CP0Ca_DC))
-        return;
-
-    /* ??? This callback should occur when the counter is exactly equal to
-       the comparator value.  Offset the count by one to avoid immediately
-       retriggering the callback before any virtual time has passed.  */
-    env->CP0_Count++;
-    cpu_mips_timer_expire(env);
-    env->CP0_Count--;
-}
-
-void cpu_mips_clock_init (CPUMIPSState *env)
-{
-    env->timer = qemu_new_timer_ns(vm_clock, &mips_timer_cb, env);
-    env->CP0_Compare = 0;
-    cpu_mips_store_count(env, 1);
-}
index ff6bf7fdcb83350b6ab75ce72c3ab6fa293292a2..ac6193a89ea2b3fd3bd72265675d4425b27bd555 100644 (file)
@@ -1,7 +1,7 @@
-#include "hw.h"
+#include "hw/hw.h"
 #include "net/net.h"
 #include "trace.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* MIPSnet register offsets */
 
diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
deleted file mode 100644 (file)
index 728723c..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * QEMU PowerPC MPC8544 global util pseudo-device
- *
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: Alexander Graf, <alex@csgraf.de>
- *
- * This 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.
- *
- * *****************************************************************
- *
- * The documentation for this device is noted in the MPC8544 documentation,
- * file name "MPC8544ERM.pdf". You can easily find it on the web.
- *
- */
-
-#include "hw.h"
-#include "sysemu/sysemu.h"
-#include "sysbus.h"
-
-#define MPC8544_GUTS_MMIO_SIZE        0x1000
-#define MPC8544_GUTS_RSTCR_RESET      0x02
-
-#define MPC8544_GUTS_ADDR_PORPLLSR    0x00
-#define MPC8544_GUTS_ADDR_PORBMSR     0x04
-#define MPC8544_GUTS_ADDR_PORIMPSCR   0x08
-#define MPC8544_GUTS_ADDR_PORDEVSR    0x0C
-#define MPC8544_GUTS_ADDR_PORDBGMSR   0x10
-#define MPC8544_GUTS_ADDR_PORDEVSR2   0x14
-#define MPC8544_GUTS_ADDR_GPPORCR     0x20
-#define MPC8544_GUTS_ADDR_GPIOCR      0x30
-#define MPC8544_GUTS_ADDR_GPOUTDR     0x40
-#define MPC8544_GUTS_ADDR_GPINDR      0x50
-#define MPC8544_GUTS_ADDR_PMUXCR      0x60
-#define MPC8544_GUTS_ADDR_DEVDISR     0x70
-#define MPC8544_GUTS_ADDR_POWMGTCSR   0x80
-#define MPC8544_GUTS_ADDR_MCPSUMR     0x90
-#define MPC8544_GUTS_ADDR_RSTRSCR     0x94
-#define MPC8544_GUTS_ADDR_PVR         0xA0
-#define MPC8544_GUTS_ADDR_SVR         0xA4
-#define MPC8544_GUTS_ADDR_RSTCR       0xB0
-#define MPC8544_GUTS_ADDR_IOVSELSR    0xC0
-#define MPC8544_GUTS_ADDR_DDRCSR      0xB20
-#define MPC8544_GUTS_ADDR_DDRCDR      0xB24
-#define MPC8544_GUTS_ADDR_DDRCLKDR    0xB28
-#define MPC8544_GUTS_ADDR_CLKOCR      0xE00
-#define MPC8544_GUTS_ADDR_SRDS1CR1    0xF04
-#define MPC8544_GUTS_ADDR_SRDS2CR1    0xF10
-#define MPC8544_GUTS_ADDR_SRDS2CR3    0xF18
-
-struct GutsState {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-};
-
-typedef struct GutsState GutsState;
-
-static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    uint32_t value = 0;
-    CPUPPCState *env = cpu_single_env;
-
-    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
-    switch (addr) {
-    case MPC8544_GUTS_ADDR_PVR:
-        value = env->spr[SPR_PVR];
-        break;
-    case MPC8544_GUTS_ADDR_SVR:
-        value = env->spr[SPR_E500_SVR];
-        break;
-    default:
-        fprintf(stderr, "guts: Unknown register read: %x\n", (int)addr);
-        break;
-    }
-
-    return value;
-}
-
-static void mpc8544_guts_write(void *opaque, hwaddr addr,
-                               uint64_t value, unsigned size)
-{
-    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
-
-    switch (addr) {
-    case MPC8544_GUTS_ADDR_RSTCR:
-        if (value & MPC8544_GUTS_RSTCR_RESET) {
-            qemu_system_reset_request();
-        }
-        break;
-    default:
-        fprintf(stderr, "guts: Unknown register write: %x = %x\n",
-                (int)addr, (unsigned)value);
-        break;
-    }
-}
-
-static const MemoryRegionOps mpc8544_guts_ops = {
-    .read = mpc8544_guts_read,
-    .write = mpc8544_guts_write,
-    .endianness = DEVICE_BIG_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-static int mpc8544_guts_initfn(SysBusDevice *dev)
-{
-    GutsState *s;
-
-    s = FROM_SYSBUS(GutsState, SYS_BUS_DEVICE(dev));
-
-    memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s,
-                          "mpc6544.guts", MPC8544_GUTS_MMIO_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    return 0;
-}
-
-static void mpc8544_guts_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mpc8544_guts_initfn;
-}
-
-static const TypeInfo mpc8544_guts_info = {
-    .name          = "mpc8544-guts",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(GutsState),
-    .class_init    = mpc8544_guts_class_init,
-};
-
-static void mpc8544_guts_register_types(void)
-{
-    type_register_static(&mpc8544_guts_info);
-}
-
-type_init(mpc8544_guts_register_types)
diff --git a/hw/msmouse.c b/hw/msmouse.c
deleted file mode 100644 (file)
index 407ec87..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * QEMU Microsoft serial mouse emulation
- *
- * Copyright (c) 2008 Lubomir Rintel
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include <stdlib.h>
-#include "qemu-common.h"
-#include "char/char.h"
-#include "ui/console.h"
-
-#define MSMOUSE_LO6(n) ((n) & 0x3f)
-#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
-
-static void msmouse_event(void *opaque,
-                          int dx, int dy, int dz, int buttons_state)
-{
-    CharDriverState *chr = (CharDriverState *)opaque;
-
-    unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 };
-
-    /* Movement deltas */
-    bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx);
-    bytes[1] |= MSMOUSE_LO6(dx);
-    bytes[2] |= MSMOUSE_LO6(dy);
-
-    /* Buttons */
-    bytes[0] |= (buttons_state & 0x01 ? 0x20 : 0x00);
-    bytes[0] |= (buttons_state & 0x02 ? 0x10 : 0x00);
-    bytes[3] |= (buttons_state & 0x04 ? 0x20 : 0x00);
-
-    /* We always send the packet of, so that we do not have to keep track
-       of previous state of the middle button. This can potentially confuse
-       some very old drivers for two button mice though. */
-    qemu_chr_be_write(chr, bytes, 4);
-}
-
-static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len)
-{
-    /* Ignore writes to mouse port */
-    return len;
-}
-
-static void msmouse_chr_close (struct CharDriverState *chr)
-{
-    g_free (chr);
-}
-
-static CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
-{
-    CharDriverState *chr;
-
-    chr = g_malloc0(sizeof(CharDriverState));
-    chr->chr_write = msmouse_chr_write;
-    chr->chr_close = msmouse_chr_close;
-
-    qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
-
-    return chr;
-}
-
-static void register_types(void)
-{
-    register_char_driver("msmouse", qemu_chr_open_msmouse);
-}
-
-type_init(register_types);
index 7ae05e389f8ab24bb9dcc87f09b9c933a5400831..1dd15054d0c52d55b557a4dfff8f369f2ff12a34 100644 (file)
@@ -10,8 +10,8 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 
 /* Mainstone FPGA for extern irqs */
 #define FPGA_GPIO_PIN  0
diff --git a/hw/multiboot.c b/hw/multiboot.c
deleted file mode 100644 (file)
index c4ec2e3..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * QEMU PC System Emulator
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw.h"
-#include "fw_cfg.h"
-#include "multiboot.h"
-#include "loader.h"
-#include "elf.h"
-#include "sysemu/sysemu.h"
-
-/* Show multiboot debug output */
-//#define DEBUG_MULTIBOOT
-
-#ifdef DEBUG_MULTIBOOT
-#define mb_debug(a...) fprintf(stderr, ## a)
-#else
-#define mb_debug(a...)
-#endif
-
-#define MULTIBOOT_STRUCT_ADDR 0x9000
-
-#if MULTIBOOT_STRUCT_ADDR > 0xf0000
-#error multiboot struct needs to fit in 16 bit real mode
-#endif
-
-enum {
-    /* Multiboot info */
-    MBI_FLAGS       = 0,
-    MBI_MEM_LOWER   = 4,
-    MBI_MEM_UPPER   = 8,
-    MBI_BOOT_DEVICE = 12,
-    MBI_CMDLINE     = 16,
-    MBI_MODS_COUNT  = 20,
-    MBI_MODS_ADDR   = 24,
-    MBI_MMAP_ADDR   = 48,
-
-    MBI_SIZE        = 88,
-
-    /* Multiboot modules */
-    MB_MOD_START    = 0,
-    MB_MOD_END      = 4,
-    MB_MOD_CMDLINE  = 8,
-
-    MB_MOD_SIZE     = 16,
-
-    /* Region offsets */
-    ADDR_E820_MAP = MULTIBOOT_STRUCT_ADDR + 0,
-    ADDR_MBI      = ADDR_E820_MAP + 0x500,
-
-    /* Multiboot flags */
-    MULTIBOOT_FLAGS_MEMORY      = 1 << 0,
-    MULTIBOOT_FLAGS_BOOT_DEVICE = 1 << 1,
-    MULTIBOOT_FLAGS_CMDLINE     = 1 << 2,
-    MULTIBOOT_FLAGS_MODULES     = 1 << 3,
-    MULTIBOOT_FLAGS_MMAP        = 1 << 6,
-};
-
-typedef struct {
-    /* buffer holding kernel, cmdlines and mb_infos */
-    void *mb_buf;
-    /* address in target */
-    hwaddr mb_buf_phys;
-    /* size of mb_buf in bytes */
-    unsigned mb_buf_size;
-    /* offset of mb-info's in bytes */
-    hwaddr offset_mbinfo;
-    /* offset in buffer for cmdlines in bytes */
-    hwaddr offset_cmdlines;
-    /* offset of modules in bytes */
-    hwaddr offset_mods;
-    /* available slots for mb modules infos */
-    int mb_mods_avail;
-    /* currently used slots of mb modules */
-    int mb_mods_count;
-} MultibootState;
-
-static uint32_t mb_add_cmdline(MultibootState *s, const char *cmdline)
-{
-    hwaddr p = s->offset_cmdlines;
-    char *b = (char *)s->mb_buf + p;
-
-    get_opt_value(b, strlen(cmdline) + 1, cmdline);
-    s->offset_cmdlines += strlen(b) + 1;
-    return s->mb_buf_phys + p;
-}
-
-static void mb_add_mod(MultibootState *s,
-                       hwaddr start, hwaddr end,
-                       hwaddr cmdline_phys)
-{
-    char *p;
-    assert(s->mb_mods_count < s->mb_mods_avail);
-
-    p = (char *)s->mb_buf + s->offset_mbinfo + MB_MOD_SIZE * s->mb_mods_count;
-
-    stl_p(p + MB_MOD_START,   start);
-    stl_p(p + MB_MOD_END,     end);
-    stl_p(p + MB_MOD_CMDLINE, cmdline_phys);
-
-    mb_debug("mod%02d: "TARGET_FMT_plx" - "TARGET_FMT_plx"\n",
-             s->mb_mods_count, start, end);
-
-    s->mb_mods_count++;
-}
-
-int load_multiboot(void *fw_cfg,
-                   FILE *f,
-                   const char *kernel_filename,
-                   const char *initrd_filename,
-                   const char *kernel_cmdline,
-                   int kernel_file_size,
-                   uint8_t *header)
-{
-    int i, is_multiboot = 0;
-    uint32_t flags = 0;
-    uint32_t mh_entry_addr;
-    uint32_t mh_load_addr;
-    uint32_t mb_kernel_size;
-    MultibootState mbs;
-    uint8_t bootinfo[MBI_SIZE];
-    uint8_t *mb_bootinfo_data;
-
-    /* Ok, let's see if it is a multiboot image.
-       The header is 12x32bit long, so the latest entry may be 8192 - 48. */
-    for (i = 0; i < (8192 - 48); i += 4) {
-        if (ldl_p(header+i) == 0x1BADB002) {
-            uint32_t checksum = ldl_p(header+i+8);
-            flags = ldl_p(header+i+4);
-            checksum += flags;
-            checksum += (uint32_t)0x1BADB002;
-            if (!checksum) {
-                is_multiboot = 1;
-                break;
-            }
-        }
-    }
-
-    if (!is_multiboot)
-        return 0; /* no multiboot */
-
-    mb_debug("qemu: I believe we found a multiboot image!\n");
-    memset(bootinfo, 0, sizeof(bootinfo));
-    memset(&mbs, 0, sizeof(mbs));
-
-    if (flags & 0x00000004) { /* MULTIBOOT_HEADER_HAS_VBE */
-        fprintf(stderr, "qemu: multiboot knows VBE. we don't.\n");
-    }
-    if (!(flags & 0x00010000)) { /* MULTIBOOT_HEADER_HAS_ADDR */
-        uint64_t elf_entry;
-        uint64_t elf_low, elf_high;
-        int kernel_size;
-        fclose(f);
-
-        if (((struct elf64_hdr*)header)->e_machine == EM_X86_64) {
-            fprintf(stderr, "Cannot load x86-64 image, give a 32bit one.\n");
-            exit(1);
-        }
-
-        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                               &elf_low, &elf_high, 0, ELF_MACHINE, 0);
-        if (kernel_size < 0) {
-            fprintf(stderr, "Error while loading elf kernel\n");
-            exit(1);
-        }
-        mh_load_addr = elf_low;
-        mb_kernel_size = elf_high - elf_low;
-        mh_entry_addr = elf_entry;
-
-        mbs.mb_buf = g_malloc(mb_kernel_size);
-        if (rom_copy(mbs.mb_buf, mh_load_addr, mb_kernel_size) != mb_kernel_size) {
-            fprintf(stderr, "Error while fetching elf kernel from rom\n");
-            exit(1);
-        }
-
-        mb_debug("qemu: loading multiboot-elf kernel (%#x bytes) with entry %#zx\n",
-                  mb_kernel_size, (size_t)mh_entry_addr);
-    } else {
-        /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_ADDR. */
-        uint32_t mh_header_addr = ldl_p(header+i+12);
-        uint32_t mh_load_end_addr = ldl_p(header+i+20);
-        uint32_t mh_bss_end_addr = ldl_p(header+i+24);
-        mh_load_addr = ldl_p(header+i+16);
-        uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
-        uint32_t mb_load_size = 0;
-        mh_entry_addr = ldl_p(header+i+28);
-
-        if (mh_load_end_addr) {
-            mb_kernel_size = mh_bss_end_addr - mh_load_addr;
-            mb_load_size = mh_load_end_addr - mh_load_addr;
-        } else {
-            mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
-            mb_load_size = mb_kernel_size;
-        }
-
-        /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE.
-        uint32_t mh_mode_type = ldl_p(header+i+32);
-        uint32_t mh_width = ldl_p(header+i+36);
-        uint32_t mh_height = ldl_p(header+i+40);
-        uint32_t mh_depth = ldl_p(header+i+44); */
-
-        mb_debug("multiboot: mh_header_addr = %#x\n", mh_header_addr);
-        mb_debug("multiboot: mh_load_addr = %#x\n", mh_load_addr);
-        mb_debug("multiboot: mh_load_end_addr = %#x\n", mh_load_end_addr);
-        mb_debug("multiboot: mh_bss_end_addr = %#x\n", mh_bss_end_addr);
-        mb_debug("qemu: loading multiboot kernel (%#x bytes) at %#x\n",
-                 mb_load_size, mh_load_addr);
-
-        mbs.mb_buf = g_malloc(mb_kernel_size);
-        fseek(f, mb_kernel_text_offset, SEEK_SET);
-        if (fread(mbs.mb_buf, 1, mb_load_size, f) != mb_load_size) {
-            fprintf(stderr, "fread() failed\n");
-            exit(1);
-        }
-        memset(mbs.mb_buf + mb_load_size, 0, mb_kernel_size - mb_load_size);
-        fclose(f);
-    }
-
-    mbs.mb_buf_phys = mh_load_addr;
-
-    mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_kernel_size);
-    mbs.offset_mbinfo = mbs.mb_buf_size;
-
-    /* Calculate space for cmdlines and mb_mods */
-    mbs.mb_buf_size += strlen(kernel_filename) + 1;
-    mbs.mb_buf_size += strlen(kernel_cmdline) + 1;
-    if (initrd_filename) {
-        const char *r = initrd_filename;
-        mbs.mb_buf_size += strlen(r) + 1;
-        mbs.mb_mods_avail = 1;
-        while (*(r = get_opt_value(NULL, 0, r))) {
-           mbs.mb_mods_avail++;
-           r++;
-        }
-        mbs.mb_buf_size += MB_MOD_SIZE * mbs.mb_mods_avail;
-    }
-
-    mbs.mb_buf_size = TARGET_PAGE_ALIGN(mbs.mb_buf_size);
-
-    /* enlarge mb_buf to hold cmdlines and mb-info structs */
-    mbs.mb_buf          = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
-    mbs.offset_cmdlines = mbs.offset_mbinfo + mbs.mb_mods_avail * MB_MOD_SIZE;
-
-    if (initrd_filename) {
-        char *next_initrd, not_last;
-
-        mbs.offset_mods = mbs.mb_buf_size;
-
-        do {
-            char *next_space;
-            int mb_mod_length;
-            uint32_t offs = mbs.mb_buf_size;
-
-            next_initrd = (char *)get_opt_value(NULL, 0, initrd_filename);
-            not_last = *next_initrd;
-            *next_initrd = '\0';
-            /* if a space comes after the module filename, treat everything
-               after that as parameters */
-            hwaddr c = mb_add_cmdline(&mbs, initrd_filename);
-            if ((next_space = strchr(initrd_filename, ' ')))
-                *next_space = '\0';
-            mb_debug("multiboot loading module: %s\n", initrd_filename);
-            mb_mod_length = get_image_size(initrd_filename);
-            if (mb_mod_length < 0) {
-                fprintf(stderr, "Failed to open file '%s'\n", initrd_filename);
-                exit(1);
-            }
-
-            mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_mod_length + mbs.mb_buf_size);
-            mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
-
-            load_image(initrd_filename, (unsigned char *)mbs.mb_buf + offs);
-            mb_add_mod(&mbs, mbs.mb_buf_phys + offs,
-                       mbs.mb_buf_phys + offs + mb_mod_length, c);
-
-            mb_debug("mod_start: %p\nmod_end:   %p\n  cmdline: "TARGET_FMT_plx"\n",
-                     (char *)mbs.mb_buf + offs,
-                     (char *)mbs.mb_buf + offs + mb_mod_length, c);
-            initrd_filename = next_initrd+1;
-        } while (not_last);
-    }
-
-    /* Commandline support */
-    char kcmdline[strlen(kernel_filename) + strlen(kernel_cmdline) + 2];
-    snprintf(kcmdline, sizeof(kcmdline), "%s %s",
-             kernel_filename, kernel_cmdline);
-    stl_p(bootinfo + MBI_CMDLINE, mb_add_cmdline(&mbs, kcmdline));
-
-    stl_p(bootinfo + MBI_MODS_ADDR,  mbs.mb_buf_phys + mbs.offset_mbinfo);
-    stl_p(bootinfo + MBI_MODS_COUNT, mbs.mb_mods_count); /* mods_count */
-
-    /* the kernel is where we want it to be now */
-    stl_p(bootinfo + MBI_FLAGS, MULTIBOOT_FLAGS_MEMORY
-                                | MULTIBOOT_FLAGS_BOOT_DEVICE
-                                | MULTIBOOT_FLAGS_CMDLINE
-                                | MULTIBOOT_FLAGS_MODULES
-                                | MULTIBOOT_FLAGS_MMAP);
-    stl_p(bootinfo + MBI_MEM_LOWER,   640);
-    stl_p(bootinfo + MBI_MEM_UPPER,   (ram_size / 1024) - 1024);
-    stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8000ffff); /* XXX: use the -boot switch? */
-    stl_p(bootinfo + MBI_MMAP_ADDR,   ADDR_E820_MAP);
-
-    mb_debug("multiboot: mh_entry_addr = %#x\n", mh_entry_addr);
-    mb_debug("           mb_buf_phys   = "TARGET_FMT_plx"\n", mbs.mb_buf_phys);
-    mb_debug("           mod_start     = "TARGET_FMT_plx"\n", mbs.mb_buf_phys + mbs.offset_mods);
-    mb_debug("           mb_mods_count = %d\n", mbs.mb_mods_count);
-
-    /* save bootinfo off the stack */
-    mb_bootinfo_data = g_malloc(sizeof(bootinfo));
-    memcpy(mb_bootinfo_data, bootinfo, sizeof(bootinfo));
-
-    /* Pass variables to option rom */
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ENTRY, mh_entry_addr);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, mh_load_addr);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, mbs.mb_buf_size);
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA,
-                     mbs.mb_buf, mbs.mb_buf_size);
-
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, ADDR_MBI);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, sizeof(bootinfo));
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, mb_bootinfo_data,
-                     sizeof(bootinfo));
-
-    option_rom[nb_option_roms].name = "multiboot.bin";
-    option_rom[nb_option_roms].bootindex = 0;
-    nb_option_roms++;
-
-    return 1; /* yes, we are multiboot */
-}
diff --git a/hw/musicpal.c b/hw/musicpal.c
deleted file mode 100644 (file)
index 272cb80..0000000
+++ /dev/null
@@ -1,1697 +0,0 @@
-/*
- * Marvell MV88W8618 / Freecom MusicPal emulation.
- *
- * Copyright (c) 2008 Jan Kiszka
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "serial.h"
-#include "qemu/timer.h"
-#include "ptimer.h"
-#include "block/block.h"
-#include "flash.h"
-#include "ui/console.h"
-#include "i2c.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-#include "ui/pixel_ops.h"
-
-#define MP_MISC_BASE            0x80002000
-#define MP_MISC_SIZE            0x00001000
-
-#define MP_ETH_BASE             0x80008000
-#define MP_ETH_SIZE             0x00001000
-
-#define MP_WLAN_BASE            0x8000C000
-#define MP_WLAN_SIZE            0x00000800
-
-#define MP_UART1_BASE           0x8000C840
-#define MP_UART2_BASE           0x8000C940
-
-#define MP_GPIO_BASE            0x8000D000
-#define MP_GPIO_SIZE            0x00001000
-
-#define MP_FLASHCFG_BASE        0x90006000
-#define MP_FLASHCFG_SIZE        0x00001000
-
-#define MP_AUDIO_BASE           0x90007000
-
-#define MP_PIC_BASE             0x90008000
-#define MP_PIC_SIZE             0x00001000
-
-#define MP_PIT_BASE             0x90009000
-#define MP_PIT_SIZE             0x00001000
-
-#define MP_LCD_BASE             0x9000c000
-#define MP_LCD_SIZE             0x00001000
-
-#define MP_SRAM_BASE            0xC0000000
-#define MP_SRAM_SIZE            0x00020000
-
-#define MP_RAM_DEFAULT_SIZE     32*1024*1024
-#define MP_FLASH_SIZE_MAX       32*1024*1024
-
-#define MP_TIMER1_IRQ           4
-#define MP_TIMER2_IRQ           5
-#define MP_TIMER3_IRQ           6
-#define MP_TIMER4_IRQ           7
-#define MP_EHCI_IRQ             8
-#define MP_ETH_IRQ              9
-#define MP_UART1_IRQ            11
-#define MP_UART2_IRQ            11
-#define MP_GPIO_IRQ             12
-#define MP_RTC_IRQ              28
-#define MP_AUDIO_IRQ            30
-
-/* Wolfson 8750 I2C address */
-#define MP_WM_ADDR              0x1A
-
-/* Ethernet register offsets */
-#define MP_ETH_SMIR             0x010
-#define MP_ETH_PCXR             0x408
-#define MP_ETH_SDCMR            0x448
-#define MP_ETH_ICR              0x450
-#define MP_ETH_IMR              0x458
-#define MP_ETH_FRDP0            0x480
-#define MP_ETH_FRDP1            0x484
-#define MP_ETH_FRDP2            0x488
-#define MP_ETH_FRDP3            0x48C
-#define MP_ETH_CRDP0            0x4A0
-#define MP_ETH_CRDP1            0x4A4
-#define MP_ETH_CRDP2            0x4A8
-#define MP_ETH_CRDP3            0x4AC
-#define MP_ETH_CTDP0            0x4E0
-#define MP_ETH_CTDP1            0x4E4
-#define MP_ETH_CTDP2            0x4E8
-#define MP_ETH_CTDP3            0x4EC
-
-/* MII PHY access */
-#define MP_ETH_SMIR_DATA        0x0000FFFF
-#define MP_ETH_SMIR_ADDR        0x03FF0000
-#define MP_ETH_SMIR_OPCODE      (1 << 26) /* Read value */
-#define MP_ETH_SMIR_RDVALID     (1 << 27)
-
-/* PHY registers */
-#define MP_ETH_PHY1_BMSR        0x00210000
-#define MP_ETH_PHY1_PHYSID1     0x00410000
-#define MP_ETH_PHY1_PHYSID2     0x00610000
-
-#define MP_PHY_BMSR_LINK        0x0004
-#define MP_PHY_BMSR_AUTONEG     0x0008
-
-#define MP_PHY_88E3015          0x01410E20
-
-/* TX descriptor status */
-#define MP_ETH_TX_OWN           (1 << 31)
-
-/* RX descriptor status */
-#define MP_ETH_RX_OWN           (1 << 31)
-
-/* Interrupt cause/mask bits */
-#define MP_ETH_IRQ_RX_BIT       0
-#define MP_ETH_IRQ_RX           (1 << MP_ETH_IRQ_RX_BIT)
-#define MP_ETH_IRQ_TXHI_BIT     2
-#define MP_ETH_IRQ_TXLO_BIT     3
-
-/* Port config bits */
-#define MP_ETH_PCXR_2BSM_BIT    28 /* 2-byte incoming suffix */
-
-/* SDMA command bits */
-#define MP_ETH_CMD_TXHI         (1 << 23)
-#define MP_ETH_CMD_TXLO         (1 << 22)
-
-typedef struct mv88w8618_tx_desc {
-    uint32_t cmdstat;
-    uint16_t res;
-    uint16_t bytes;
-    uint32_t buffer;
-    uint32_t next;
-} mv88w8618_tx_desc;
-
-typedef struct mv88w8618_rx_desc {
-    uint32_t cmdstat;
-    uint16_t bytes;
-    uint16_t buffer_size;
-    uint32_t buffer;
-    uint32_t next;
-} mv88w8618_rx_desc;
-
-typedef struct mv88w8618_eth_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    qemu_irq irq;
-    uint32_t smir;
-    uint32_t icr;
-    uint32_t imr;
-    int mmio_index;
-    uint32_t vlan_header;
-    uint32_t tx_queue[2];
-    uint32_t rx_queue[4];
-    uint32_t frx_queue[4];
-    uint32_t cur_rx[4];
-    NICState *nic;
-    NICConf conf;
-} mv88w8618_eth_state;
-
-static void eth_rx_desc_put(uint32_t addr, mv88w8618_rx_desc *desc)
-{
-    cpu_to_le32s(&desc->cmdstat);
-    cpu_to_le16s(&desc->bytes);
-    cpu_to_le16s(&desc->buffer_size);
-    cpu_to_le32s(&desc->buffer);
-    cpu_to_le32s(&desc->next);
-    cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
-}
-
-static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc)
-{
-    cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
-    le32_to_cpus(&desc->cmdstat);
-    le16_to_cpus(&desc->bytes);
-    le16_to_cpus(&desc->buffer_size);
-    le32_to_cpus(&desc->buffer);
-    le32_to_cpus(&desc->next);
-}
-
-static int eth_can_receive(NetClientState *nc)
-{
-    return 1;
-}
-
-static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
-{
-    mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
-    uint32_t desc_addr;
-    mv88w8618_rx_desc desc;
-    int i;
-
-    for (i = 0; i < 4; i++) {
-        desc_addr = s->cur_rx[i];
-        if (!desc_addr) {
-            continue;
-        }
-        do {
-            eth_rx_desc_get(desc_addr, &desc);
-            if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) {
-                cpu_physical_memory_write(desc.buffer + s->vlan_header,
-                                          buf, size);
-                desc.bytes = size + s->vlan_header;
-                desc.cmdstat &= ~MP_ETH_RX_OWN;
-                s->cur_rx[i] = desc.next;
-
-                s->icr |= MP_ETH_IRQ_RX;
-                if (s->icr & s->imr) {
-                    qemu_irq_raise(s->irq);
-                }
-                eth_rx_desc_put(desc_addr, &desc);
-                return size;
-            }
-            desc_addr = desc.next;
-        } while (desc_addr != s->rx_queue[i]);
-    }
-    return size;
-}
-
-static void eth_tx_desc_put(uint32_t addr, mv88w8618_tx_desc *desc)
-{
-    cpu_to_le32s(&desc->cmdstat);
-    cpu_to_le16s(&desc->res);
-    cpu_to_le16s(&desc->bytes);
-    cpu_to_le32s(&desc->buffer);
-    cpu_to_le32s(&desc->next);
-    cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
-}
-
-static void eth_tx_desc_get(uint32_t addr, mv88w8618_tx_desc *desc)
-{
-    cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
-    le32_to_cpus(&desc->cmdstat);
-    le16_to_cpus(&desc->res);
-    le16_to_cpus(&desc->bytes);
-    le32_to_cpus(&desc->buffer);
-    le32_to_cpus(&desc->next);
-}
-
-static void eth_send(mv88w8618_eth_state *s, int queue_index)
-{
-    uint32_t desc_addr = s->tx_queue[queue_index];
-    mv88w8618_tx_desc desc;
-    uint32_t next_desc;
-    uint8_t buf[2048];
-    int len;
-
-    do {
-        eth_tx_desc_get(desc_addr, &desc);
-        next_desc = desc.next;
-        if (desc.cmdstat & MP_ETH_TX_OWN) {
-            len = desc.bytes;
-            if (len < 2048) {
-                cpu_physical_memory_read(desc.buffer, buf, len);
-                qemu_send_packet(qemu_get_queue(s->nic), buf, len);
-            }
-            desc.cmdstat &= ~MP_ETH_TX_OWN;
-            s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);
-            eth_tx_desc_put(desc_addr, &desc);
-        }
-        desc_addr = next_desc;
-    } while (desc_addr != s->tx_queue[queue_index]);
-}
-
-static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    mv88w8618_eth_state *s = opaque;
-
-    switch (offset) {
-    case MP_ETH_SMIR:
-        if (s->smir & MP_ETH_SMIR_OPCODE) {
-            switch (s->smir & MP_ETH_SMIR_ADDR) {
-            case MP_ETH_PHY1_BMSR:
-                return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG |
-                       MP_ETH_SMIR_RDVALID;
-            case MP_ETH_PHY1_PHYSID1:
-                return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID;
-            case MP_ETH_PHY1_PHYSID2:
-                return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID;
-            default:
-                return MP_ETH_SMIR_RDVALID;
-            }
-        }
-        return 0;
-
-    case MP_ETH_ICR:
-        return s->icr;
-
-    case MP_ETH_IMR:
-        return s->imr;
-
-    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
-        return s->frx_queue[(offset - MP_ETH_FRDP0)/4];
-
-    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
-        return s->rx_queue[(offset - MP_ETH_CRDP0)/4];
-
-    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
-        return s->tx_queue[(offset - MP_ETH_CTDP0)/4];
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_eth_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    mv88w8618_eth_state *s = opaque;
-
-    switch (offset) {
-    case MP_ETH_SMIR:
-        s->smir = value;
-        break;
-
-    case MP_ETH_PCXR:
-        s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2;
-        break;
-
-    case MP_ETH_SDCMR:
-        if (value & MP_ETH_CMD_TXHI) {
-            eth_send(s, 1);
-        }
-        if (value & MP_ETH_CMD_TXLO) {
-            eth_send(s, 0);
-        }
-        if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr) {
-            qemu_irq_raise(s->irq);
-        }
-        break;
-
-    case MP_ETH_ICR:
-        s->icr &= value;
-        break;
-
-    case MP_ETH_IMR:
-        s->imr = value;
-        if (s->icr & s->imr) {
-            qemu_irq_raise(s->irq);
-        }
-        break;
-
-    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
-        s->frx_queue[(offset - MP_ETH_FRDP0)/4] = value;
-        break;
-
-    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
-        s->rx_queue[(offset - MP_ETH_CRDP0)/4] =
-            s->cur_rx[(offset - MP_ETH_CRDP0)/4] = value;
-        break;
-
-    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
-        s->tx_queue[(offset - MP_ETH_CTDP0)/4] = value;
-        break;
-    }
-}
-
-static const MemoryRegionOps mv88w8618_eth_ops = {
-    .read = mv88w8618_eth_read,
-    .write = mv88w8618_eth_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void eth_cleanup(NetClientState *nc)
-{
-    mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
-
-    s->nic = NULL;
-}
-
-static NetClientInfo net_mv88w8618_info = {
-    .type = NET_CLIENT_OPTIONS_KIND_NIC,
-    .size = sizeof(NICState),
-    .can_receive = eth_can_receive,
-    .receive = eth_receive,
-    .cleanup = eth_cleanup,
-};
-
-static int mv88w8618_eth_init(SysBusDevice *dev)
-{
-    mv88w8618_eth_state *s = FROM_SYSBUS(mv88w8618_eth_state, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf,
-                          object_get_typename(OBJECT(dev)), dev->qdev.id, s);
-    memory_region_init_io(&s->iomem, &mv88w8618_eth_ops, s, "mv88w8618-eth",
-                          MP_ETH_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-static const VMStateDescription mv88w8618_eth_vmsd = {
-    .name = "mv88w8618_eth",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(smir, mv88w8618_eth_state),
-        VMSTATE_UINT32(icr, mv88w8618_eth_state),
-        VMSTATE_UINT32(imr, mv88w8618_eth_state),
-        VMSTATE_UINT32(vlan_header, mv88w8618_eth_state),
-        VMSTATE_UINT32_ARRAY(tx_queue, mv88w8618_eth_state, 2),
-        VMSTATE_UINT32_ARRAY(rx_queue, mv88w8618_eth_state, 4),
-        VMSTATE_UINT32_ARRAY(frx_queue, mv88w8618_eth_state, 4),
-        VMSTATE_UINT32_ARRAY(cur_rx, mv88w8618_eth_state, 4),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static Property mv88w8618_eth_properties[] = {
-    DEFINE_NIC_PROPERTIES(mv88w8618_eth_state, conf),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void mv88w8618_eth_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mv88w8618_eth_init;
-    dc->vmsd = &mv88w8618_eth_vmsd;
-    dc->props = mv88w8618_eth_properties;
-}
-
-static const TypeInfo mv88w8618_eth_info = {
-    .name          = "mv88w8618_eth",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_eth_state),
-    .class_init    = mv88w8618_eth_class_init,
-};
-
-/* LCD register offsets */
-#define MP_LCD_IRQCTRL          0x180
-#define MP_LCD_IRQSTAT          0x184
-#define MP_LCD_SPICTRL          0x1ac
-#define MP_LCD_INST             0x1bc
-#define MP_LCD_DATA             0x1c0
-
-/* Mode magics */
-#define MP_LCD_SPI_DATA         0x00100011
-#define MP_LCD_SPI_CMD          0x00104011
-#define MP_LCD_SPI_INVALID      0x00000000
-
-/* Commmands */
-#define MP_LCD_INST_SETPAGE0    0xB0
-/* ... */
-#define MP_LCD_INST_SETPAGE7    0xB7
-
-#define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */
-
-typedef struct musicpal_lcd_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t brightness;
-    uint32_t mode;
-    uint32_t irqctrl;
-    uint32_t page;
-    uint32_t page_off;
-    DisplayState *ds;
-    uint8_t video_ram[128*64/8];
-} musicpal_lcd_state;
-
-static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
-{
-    switch (s->brightness) {
-    case 7:
-        return col;
-    case 0:
-        return 0;
-    default:
-        return (col * s->brightness) / 7;
-    }
-}
-
-#define SET_LCD_PIXEL(depth, type) \
-static inline void glue(set_lcd_pixel, depth) \
-        (musicpal_lcd_state *s, int x, int y, type col) \
-{ \
-    int dx, dy; \
-    type *pixel = &((type *) ds_get_data(s->ds))[(y * 128 * 3 + x) * 3]; \
-\
-    for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
-        for (dx = 0; dx < 3; dx++, pixel++) \
-            *pixel = col; \
-}
-SET_LCD_PIXEL(8, uint8_t)
-SET_LCD_PIXEL(16, uint16_t)
-SET_LCD_PIXEL(32, uint32_t)
-
-static void lcd_refresh(void *opaque)
-{
-    musicpal_lcd_state *s = opaque;
-    int x, y, col;
-
-    switch (ds_get_bits_per_pixel(s->ds)) {
-    case 0:
-        return;
-#define LCD_REFRESH(depth, func) \
-    case depth: \
-        col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
-                   scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
-                   scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
-        for (x = 0; x < 128; x++) { \
-            for (y = 0; y < 64; y++) { \
-                if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
-                    glue(set_lcd_pixel, depth)(s, x, y, col); \
-                } else { \
-                    glue(set_lcd_pixel, depth)(s, x, y, 0); \
-                } \
-            } \
-        } \
-        break;
-    LCD_REFRESH(8, rgb_to_pixel8)
-    LCD_REFRESH(16, rgb_to_pixel16)
-    LCD_REFRESH(32, (is_surface_bgr(s->ds->surface) ?
-                     rgb_to_pixel32bgr : rgb_to_pixel32))
-    default:
-        hw_error("unsupported colour depth %i\n",
-                  ds_get_bits_per_pixel(s->ds));
-    }
-
-    dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3);
-}
-
-static void lcd_invalidate(void *opaque)
-{
-}
-
-static void musicpal_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
-{
-    musicpal_lcd_state *s = opaque;
-    s->brightness &= ~(1 << irq);
-    s->brightness |= level << irq;
-}
-
-static uint64_t musicpal_lcd_read(void *opaque, hwaddr offset,
-                                  unsigned size)
-{
-    musicpal_lcd_state *s = opaque;
-
-    switch (offset) {
-    case MP_LCD_IRQCTRL:
-        return s->irqctrl;
-
-    default:
-        return 0;
-    }
-}
-
-static void musicpal_lcd_write(void *opaque, hwaddr offset,
-                               uint64_t value, unsigned size)
-{
-    musicpal_lcd_state *s = opaque;
-
-    switch (offset) {
-    case MP_LCD_IRQCTRL:
-        s->irqctrl = value;
-        break;
-
-    case MP_LCD_SPICTRL:
-        if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
-            s->mode = value;
-        } else {
-            s->mode = MP_LCD_SPI_INVALID;
-        }
-        break;
-
-    case MP_LCD_INST:
-        if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
-            s->page = value - MP_LCD_INST_SETPAGE0;
-            s->page_off = 0;
-        }
-        break;
-
-    case MP_LCD_DATA:
-        if (s->mode == MP_LCD_SPI_CMD) {
-            if (value >= MP_LCD_INST_SETPAGE0 &&
-                value <= MP_LCD_INST_SETPAGE7) {
-                s->page = value - MP_LCD_INST_SETPAGE0;
-                s->page_off = 0;
-            }
-        } else if (s->mode == MP_LCD_SPI_DATA) {
-            s->video_ram[s->page*128 + s->page_off] = value;
-            s->page_off = (s->page_off + 1) & 127;
-        }
-        break;
-    }
-}
-
-static const MemoryRegionOps musicpal_lcd_ops = {
-    .read = musicpal_lcd_read,
-    .write = musicpal_lcd_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int musicpal_lcd_init(SysBusDevice *dev)
-{
-    musicpal_lcd_state *s = FROM_SYSBUS(musicpal_lcd_state, dev);
-
-    s->brightness = 7;
-
-    memory_region_init_io(&s->iomem, &musicpal_lcd_ops, s,
-                          "musicpal-lcd", MP_LCD_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    s->ds = graphic_console_init(lcd_refresh, lcd_invalidate,
-                                 NULL, NULL, s);
-    qemu_console_resize(s->ds, 128*3, 64*3);
-
-    qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3);
-
-    return 0;
-}
-
-static const VMStateDescription musicpal_lcd_vmsd = {
-    .name = "musicpal_lcd",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(brightness, musicpal_lcd_state),
-        VMSTATE_UINT32(mode, musicpal_lcd_state),
-        VMSTATE_UINT32(irqctrl, musicpal_lcd_state),
-        VMSTATE_UINT32(page, musicpal_lcd_state),
-        VMSTATE_UINT32(page_off, musicpal_lcd_state),
-        VMSTATE_BUFFER(video_ram, musicpal_lcd_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void musicpal_lcd_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = musicpal_lcd_init;
-    dc->vmsd = &musicpal_lcd_vmsd;
-}
-
-static const TypeInfo musicpal_lcd_info = {
-    .name          = "musicpal_lcd",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(musicpal_lcd_state),
-    .class_init    = musicpal_lcd_class_init,
-};
-
-/* PIC register offsets */
-#define MP_PIC_STATUS           0x00
-#define MP_PIC_ENABLE_SET       0x08
-#define MP_PIC_ENABLE_CLR       0x0C
-
-typedef struct mv88w8618_pic_state
-{
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t level;
-    uint32_t enabled;
-    qemu_irq parent_irq;
-} mv88w8618_pic_state;
-
-static void mv88w8618_pic_update(mv88w8618_pic_state *s)
-{
-    qemu_set_irq(s->parent_irq, (s->level & s->enabled));
-}
-
-static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
-{
-    mv88w8618_pic_state *s = opaque;
-
-    if (level) {
-        s->level |= 1 << irq;
-    } else {
-        s->level &= ~(1 << irq);
-    }
-    mv88w8618_pic_update(s);
-}
-
-static uint64_t mv88w8618_pic_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    mv88w8618_pic_state *s = opaque;
-
-    switch (offset) {
-    case MP_PIC_STATUS:
-        return s->level & s->enabled;
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_pic_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    mv88w8618_pic_state *s = opaque;
-
-    switch (offset) {
-    case MP_PIC_ENABLE_SET:
-        s->enabled |= value;
-        break;
-
-    case MP_PIC_ENABLE_CLR:
-        s->enabled &= ~value;
-        s->level &= ~value;
-        break;
-    }
-    mv88w8618_pic_update(s);
-}
-
-static void mv88w8618_pic_reset(DeviceState *d)
-{
-    mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state,
-                                         SYS_BUS_DEVICE(d));
-
-    s->level = 0;
-    s->enabled = 0;
-}
-
-static const MemoryRegionOps mv88w8618_pic_ops = {
-    .read = mv88w8618_pic_read,
-    .write = mv88w8618_pic_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int mv88w8618_pic_init(SysBusDevice *dev)
-{
-    mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state, dev);
-
-    qdev_init_gpio_in(&dev->qdev, mv88w8618_pic_set_irq, 32);
-    sysbus_init_irq(dev, &s->parent_irq);
-    memory_region_init_io(&s->iomem, &mv88w8618_pic_ops, s,
-                          "musicpal-pic", MP_PIC_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-static const VMStateDescription mv88w8618_pic_vmsd = {
-    .name = "mv88w8618_pic",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(level, mv88w8618_pic_state),
-        VMSTATE_UINT32(enabled, mv88w8618_pic_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void mv88w8618_pic_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mv88w8618_pic_init;
-    dc->reset = mv88w8618_pic_reset;
-    dc->vmsd = &mv88w8618_pic_vmsd;
-}
-
-static const TypeInfo mv88w8618_pic_info = {
-    .name          = "mv88w8618_pic",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_pic_state),
-    .class_init    = mv88w8618_pic_class_init,
-};
-
-/* PIT register offsets */
-#define MP_PIT_TIMER1_LENGTH    0x00
-/* ... */
-#define MP_PIT_TIMER4_LENGTH    0x0C
-#define MP_PIT_CONTROL          0x10
-#define MP_PIT_TIMER1_VALUE     0x14
-/* ... */
-#define MP_PIT_TIMER4_VALUE     0x20
-#define MP_BOARD_RESET          0x34
-
-/* Magic board reset value (probably some watchdog behind it) */
-#define MP_BOARD_RESET_MAGIC    0x10000
-
-typedef struct mv88w8618_timer_state {
-    ptimer_state *ptimer;
-    uint32_t limit;
-    int freq;
-    qemu_irq irq;
-} mv88w8618_timer_state;
-
-typedef struct mv88w8618_pit_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    mv88w8618_timer_state timer[4];
-} mv88w8618_pit_state;
-
-static void mv88w8618_timer_tick(void *opaque)
-{
-    mv88w8618_timer_state *s = opaque;
-
-    qemu_irq_raise(s->irq);
-}
-
-static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
-                                 uint32_t freq)
-{
-    QEMUBH *bh;
-
-    sysbus_init_irq(dev, &s->irq);
-    s->freq = freq;
-
-    bh = qemu_bh_new(mv88w8618_timer_tick, s);
-    s->ptimer = ptimer_init(bh);
-}
-
-static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    mv88w8618_pit_state *s = opaque;
-    mv88w8618_timer_state *t;
-
-    switch (offset) {
-    case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
-        t = &s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
-        return ptimer_get_count(t->ptimer);
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_pit_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    mv88w8618_pit_state *s = opaque;
-    mv88w8618_timer_state *t;
-    int i;
-
-    switch (offset) {
-    case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
-        t = &s->timer[offset >> 2];
-        t->limit = value;
-        if (t->limit > 0) {
-            ptimer_set_limit(t->ptimer, t->limit, 1);
-        } else {
-            ptimer_stop(t->ptimer);
-        }
-        break;
-
-    case MP_PIT_CONTROL:
-        for (i = 0; i < 4; i++) {
-            t = &s->timer[i];
-            if (value & 0xf && t->limit > 0) {
-                ptimer_set_limit(t->ptimer, t->limit, 0);
-                ptimer_set_freq(t->ptimer, t->freq);
-                ptimer_run(t->ptimer, 0);
-            } else {
-                ptimer_stop(t->ptimer);
-            }
-            value >>= 4;
-        }
-        break;
-
-    case MP_BOARD_RESET:
-        if (value == MP_BOARD_RESET_MAGIC) {
-            qemu_system_reset_request();
-        }
-        break;
-    }
-}
-
-static void mv88w8618_pit_reset(DeviceState *d)
-{
-    mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state,
-                                         SYS_BUS_DEVICE(d));
-    int i;
-
-    for (i = 0; i < 4; i++) {
-        ptimer_stop(s->timer[i].ptimer);
-        s->timer[i].limit = 0;
-    }
-}
-
-static const MemoryRegionOps mv88w8618_pit_ops = {
-    .read = mv88w8618_pit_read,
-    .write = mv88w8618_pit_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int mv88w8618_pit_init(SysBusDevice *dev)
-{
-    mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state, dev);
-    int i;
-
-    /* Letting them all run at 1 MHz is likely just a pragmatic
-     * simplification. */
-    for (i = 0; i < 4; i++) {
-        mv88w8618_timer_init(dev, &s->timer[i], 1000000);
-    }
-
-    memory_region_init_io(&s->iomem, &mv88w8618_pit_ops, s,
-                          "musicpal-pit", MP_PIT_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-static const VMStateDescription mv88w8618_timer_vmsd = {
-    .name = "timer",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
-        VMSTATE_UINT32(limit, mv88w8618_timer_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription mv88w8618_pit_vmsd = {
-    .name = "mv88w8618_pit",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
-                             mv88w8618_timer_vmsd, mv88w8618_timer_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void mv88w8618_pit_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mv88w8618_pit_init;
-    dc->reset = mv88w8618_pit_reset;
-    dc->vmsd = &mv88w8618_pit_vmsd;
-}
-
-static const TypeInfo mv88w8618_pit_info = {
-    .name          = "mv88w8618_pit",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_pit_state),
-    .class_init    = mv88w8618_pit_class_init,
-};
-
-/* Flash config register offsets */
-#define MP_FLASHCFG_CFGR0    0x04
-
-typedef struct mv88w8618_flashcfg_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t cfgr0;
-} mv88w8618_flashcfg_state;
-
-static uint64_t mv88w8618_flashcfg_read(void *opaque,
-                                        hwaddr offset,
-                                        unsigned size)
-{
-    mv88w8618_flashcfg_state *s = opaque;
-
-    switch (offset) {
-    case MP_FLASHCFG_CFGR0:
-        return s->cfgr0;
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_flashcfg_write(void *opaque, hwaddr offset,
-                                     uint64_t value, unsigned size)
-{
-    mv88w8618_flashcfg_state *s = opaque;
-
-    switch (offset) {
-    case MP_FLASHCFG_CFGR0:
-        s->cfgr0 = value;
-        break;
-    }
-}
-
-static const MemoryRegionOps mv88w8618_flashcfg_ops = {
-    .read = mv88w8618_flashcfg_read,
-    .write = mv88w8618_flashcfg_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int mv88w8618_flashcfg_init(SysBusDevice *dev)
-{
-    mv88w8618_flashcfg_state *s = FROM_SYSBUS(mv88w8618_flashcfg_state, dev);
-
-    s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
-    memory_region_init_io(&s->iomem, &mv88w8618_flashcfg_ops, s,
-                          "musicpal-flashcfg", MP_FLASHCFG_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-static const VMStateDescription mv88w8618_flashcfg_vmsd = {
-    .name = "mv88w8618_flashcfg",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void mv88w8618_flashcfg_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mv88w8618_flashcfg_init;
-    dc->vmsd = &mv88w8618_flashcfg_vmsd;
-}
-
-static const TypeInfo mv88w8618_flashcfg_info = {
-    .name          = "mv88w8618_flashcfg",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_flashcfg_state),
-    .class_init    = mv88w8618_flashcfg_class_init,
-};
-
-/* Misc register offsets */
-#define MP_MISC_BOARD_REVISION  0x18
-
-#define MP_BOARD_REVISION       0x31
-
-static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    switch (offset) {
-    case MP_MISC_BOARD_REVISION:
-        return MP_BOARD_REVISION;
-
-    default:
-        return 0;
-    }
-}
-
-static void musicpal_misc_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-}
-
-static const MemoryRegionOps musicpal_misc_ops = {
-    .read = musicpal_misc_read,
-    .write = musicpal_misc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void musicpal_misc_init(SysBusDevice *dev)
-{
-    MemoryRegion *iomem = g_new(MemoryRegion, 1);
-
-    memory_region_init_io(iomem, &musicpal_misc_ops, NULL,
-                          "musicpal-misc", MP_MISC_SIZE);
-    sysbus_add_memory(dev, MP_MISC_BASE, iomem);
-}
-
-/* WLAN register offsets */
-#define MP_WLAN_MAGIC1          0x11c
-#define MP_WLAN_MAGIC2          0x124
-
-static uint64_t mv88w8618_wlan_read(void *opaque, hwaddr offset,
-                                    unsigned size)
-{
-    switch (offset) {
-    /* Workaround to allow loading the binary-only wlandrv.ko crap
-     * from the original Freecom firmware. */
-    case MP_WLAN_MAGIC1:
-        return ~3;
-    case MP_WLAN_MAGIC2:
-        return -1;
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_wlan_write(void *opaque, hwaddr offset,
-                                 uint64_t value, unsigned size)
-{
-}
-
-static const MemoryRegionOps mv88w8618_wlan_ops = {
-    .read = mv88w8618_wlan_read,
-    .write =mv88w8618_wlan_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int mv88w8618_wlan_init(SysBusDevice *dev)
-{
-    MemoryRegion *iomem = g_new(MemoryRegion, 1);
-
-    memory_region_init_io(iomem, &mv88w8618_wlan_ops, NULL,
-                          "musicpal-wlan", MP_WLAN_SIZE);
-    sysbus_init_mmio(dev, iomem);
-    return 0;
-}
-
-/* GPIO register offsets */
-#define MP_GPIO_OE_LO           0x008
-#define MP_GPIO_OUT_LO          0x00c
-#define MP_GPIO_IN_LO           0x010
-#define MP_GPIO_IER_LO          0x014
-#define MP_GPIO_IMR_LO          0x018
-#define MP_GPIO_ISR_LO          0x020
-#define MP_GPIO_OE_HI           0x508
-#define MP_GPIO_OUT_HI          0x50c
-#define MP_GPIO_IN_HI           0x510
-#define MP_GPIO_IER_HI          0x514
-#define MP_GPIO_IMR_HI          0x518
-#define MP_GPIO_ISR_HI          0x520
-
-/* GPIO bits & masks */
-#define MP_GPIO_LCD_BRIGHTNESS  0x00070000
-#define MP_GPIO_I2C_DATA_BIT    29
-#define MP_GPIO_I2C_CLOCK_BIT   30
-
-/* LCD brightness bits in GPIO_OE_HI */
-#define MP_OE_LCD_BRIGHTNESS    0x0007
-
-typedef struct musicpal_gpio_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t lcd_brightness;
-    uint32_t out_state;
-    uint32_t in_state;
-    uint32_t ier;
-    uint32_t imr;
-    uint32_t isr;
-    qemu_irq irq;
-    qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
-} musicpal_gpio_state;
-
-static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
-    int i;
-    uint32_t brightness;
-
-    /* compute brightness ratio */
-    switch (s->lcd_brightness) {
-    case 0x00000007:
-        brightness = 0;
-        break;
-
-    case 0x00020000:
-        brightness = 1;
-        break;
-
-    case 0x00020001:
-        brightness = 2;
-        break;
-
-    case 0x00040000:
-        brightness = 3;
-        break;
-
-    case 0x00010006:
-        brightness = 4;
-        break;
-
-    case 0x00020005:
-        brightness = 5;
-        break;
-
-    case 0x00040003:
-        brightness = 6;
-        break;
-
-    case 0x00030004:
-    default:
-        brightness = 7;
-    }
-
-    /* set lcd brightness GPIOs  */
-    for (i = 0; i <= 2; i++) {
-        qemu_set_irq(s->out[i], (brightness >> i) & 1);
-    }
-}
-
-static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
-{
-    musicpal_gpio_state *s = opaque;
-    uint32_t mask = 1 << pin;
-    uint32_t delta = level << pin;
-    uint32_t old = s->in_state & mask;
-
-    s->in_state &= ~mask;
-    s->in_state |= delta;
-
-    if ((old ^ delta) &&
-        ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
-        s->isr = mask;
-        qemu_irq_raise(s->irq);
-    }
-}
-
-static uint64_t musicpal_gpio_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    musicpal_gpio_state *s = opaque;
-
-    switch (offset) {
-    case MP_GPIO_OE_HI: /* used for LCD brightness control */
-        return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
-
-    case MP_GPIO_OUT_LO:
-        return s->out_state & 0xFFFF;
-    case MP_GPIO_OUT_HI:
-        return s->out_state >> 16;
-
-    case MP_GPIO_IN_LO:
-        return s->in_state & 0xFFFF;
-    case MP_GPIO_IN_HI:
-        return s->in_state >> 16;
-
-    case MP_GPIO_IER_LO:
-        return s->ier & 0xFFFF;
-    case MP_GPIO_IER_HI:
-        return s->ier >> 16;
-
-    case MP_GPIO_IMR_LO:
-        return s->imr & 0xFFFF;
-    case MP_GPIO_IMR_HI:
-        return s->imr >> 16;
-
-    case MP_GPIO_ISR_LO:
-        return s->isr & 0xFFFF;
-    case MP_GPIO_ISR_HI:
-        return s->isr >> 16;
-
-    default:
-        return 0;
-    }
-}
-
-static void musicpal_gpio_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    musicpal_gpio_state *s = opaque;
-    switch (offset) {
-    case MP_GPIO_OE_HI: /* used for LCD brightness control */
-        s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
-                         (value & MP_OE_LCD_BRIGHTNESS);
-        musicpal_gpio_brightness_update(s);
-        break;
-
-    case MP_GPIO_OUT_LO:
-        s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
-        break;
-    case MP_GPIO_OUT_HI:
-        s->out_state = (s->out_state & 0xFFFF) | (value << 16);
-        s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
-                            (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
-        musicpal_gpio_brightness_update(s);
-        qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
-        qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
-        break;
-
-    case MP_GPIO_IER_LO:
-        s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
-        break;
-    case MP_GPIO_IER_HI:
-        s->ier = (s->ier & 0xFFFF) | (value << 16);
-        break;
-
-    case MP_GPIO_IMR_LO:
-        s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
-        break;
-    case MP_GPIO_IMR_HI:
-        s->imr = (s->imr & 0xFFFF) | (value << 16);
-        break;
-    }
-}
-
-static const MemoryRegionOps musicpal_gpio_ops = {
-    .read = musicpal_gpio_read,
-    .write = musicpal_gpio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void musicpal_gpio_reset(DeviceState *d)
-{
-    musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state,
-                                         SYS_BUS_DEVICE(d));
-
-    s->lcd_brightness = 0;
-    s->out_state = 0;
-    s->in_state = 0xffffffff;
-    s->ier = 0;
-    s->imr = 0;
-    s->isr = 0;
-}
-
-static int musicpal_gpio_init(SysBusDevice *dev)
-{
-    musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-
-    memory_region_init_io(&s->iomem, &musicpal_gpio_ops, s,
-                          "musicpal-gpio", MP_GPIO_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
-
-    qdev_init_gpio_in(&dev->qdev, musicpal_gpio_pin_event, 32);
-
-    return 0;
-}
-
-static const VMStateDescription musicpal_gpio_vmsd = {
-    .name = "musicpal_gpio",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
-        VMSTATE_UINT32(out_state, musicpal_gpio_state),
-        VMSTATE_UINT32(in_state, musicpal_gpio_state),
-        VMSTATE_UINT32(ier, musicpal_gpio_state),
-        VMSTATE_UINT32(imr, musicpal_gpio_state),
-        VMSTATE_UINT32(isr, musicpal_gpio_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void musicpal_gpio_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = musicpal_gpio_init;
-    dc->reset = musicpal_gpio_reset;
-    dc->vmsd = &musicpal_gpio_vmsd;
-}
-
-static const TypeInfo musicpal_gpio_info = {
-    .name          = "musicpal_gpio",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(musicpal_gpio_state),
-    .class_init    = musicpal_gpio_class_init,
-};
-
-/* Keyboard codes & masks */
-#define KEY_RELEASED            0x80
-#define KEY_CODE                0x7f
-
-#define KEYCODE_TAB             0x0f
-#define KEYCODE_ENTER           0x1c
-#define KEYCODE_F               0x21
-#define KEYCODE_M               0x32
-
-#define KEYCODE_EXTENDED        0xe0
-#define KEYCODE_UP              0x48
-#define KEYCODE_DOWN            0x50
-#define KEYCODE_LEFT            0x4b
-#define KEYCODE_RIGHT           0x4d
-
-#define MP_KEY_WHEEL_VOL       (1 << 0)
-#define MP_KEY_WHEEL_VOL_INV   (1 << 1)
-#define MP_KEY_WHEEL_NAV       (1 << 2)
-#define MP_KEY_WHEEL_NAV_INV   (1 << 3)
-#define MP_KEY_BTN_FAVORITS    (1 << 4)
-#define MP_KEY_BTN_MENU        (1 << 5)
-#define MP_KEY_BTN_VOLUME      (1 << 6)
-#define MP_KEY_BTN_NAVIGATION  (1 << 7)
-
-typedef struct musicpal_key_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t kbd_extended;
-    uint32_t pressed_keys;
-    qemu_irq out[8];
-} musicpal_key_state;
-
-static void musicpal_key_event(void *opaque, int keycode)
-{
-    musicpal_key_state *s = opaque;
-    uint32_t event = 0;
-    int i;
-
-    if (keycode == KEYCODE_EXTENDED) {
-        s->kbd_extended = 1;
-        return;
-    }
-
-    if (s->kbd_extended) {
-        switch (keycode & KEY_CODE) {
-        case KEYCODE_UP:
-            event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
-            break;
-
-        case KEYCODE_DOWN:
-            event = MP_KEY_WHEEL_NAV;
-            break;
-
-        case KEYCODE_LEFT:
-            event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
-            break;
-
-        case KEYCODE_RIGHT:
-            event = MP_KEY_WHEEL_VOL;
-            break;
-        }
-    } else {
-        switch (keycode & KEY_CODE) {
-        case KEYCODE_F:
-            event = MP_KEY_BTN_FAVORITS;
-            break;
-
-        case KEYCODE_TAB:
-            event = MP_KEY_BTN_VOLUME;
-            break;
-
-        case KEYCODE_ENTER:
-            event = MP_KEY_BTN_NAVIGATION;
-            break;
-
-        case KEYCODE_M:
-            event = MP_KEY_BTN_MENU;
-            break;
-        }
-        /* Do not repeat already pressed buttons */
-        if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
-            event = 0;
-        }
-    }
-
-    if (event) {
-        /* Raise GPIO pin first if repeating a key */
-        if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
-            for (i = 0; i <= 7; i++) {
-                if (event & (1 << i)) {
-                    qemu_set_irq(s->out[i], 1);
-                }
-            }
-        }
-        for (i = 0; i <= 7; i++) {
-            if (event & (1 << i)) {
-                qemu_set_irq(s->out[i], !!(keycode & KEY_RELEASED));
-            }
-        }
-        if (keycode & KEY_RELEASED) {
-            s->pressed_keys &= ~event;
-        } else {
-            s->pressed_keys |= event;
-        }
-    }
-
-    s->kbd_extended = 0;
-}
-
-static int musicpal_key_init(SysBusDevice *dev)
-{
-    musicpal_key_state *s = FROM_SYSBUS(musicpal_key_state, dev);
-
-    memory_region_init(&s->iomem, "dummy", 0);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    s->kbd_extended = 0;
-    s->pressed_keys = 0;
-
-    qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
-
-    qemu_add_kbd_event_handler(musicpal_key_event, s);
-
-    return 0;
-}
-
-static const VMStateDescription musicpal_key_vmsd = {
-    .name = "musicpal_key",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(kbd_extended, musicpal_key_state),
-        VMSTATE_UINT32(pressed_keys, musicpal_key_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void musicpal_key_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = musicpal_key_init;
-    dc->vmsd = &musicpal_key_vmsd;
-}
-
-static const TypeInfo musicpal_key_info = {
-    .name          = "musicpal_key",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(musicpal_key_state),
-    .class_init    = musicpal_key_class_init,
-};
-
-static struct arm_boot_info musicpal_binfo = {
-    .loader_start = 0x0,
-    .board_id = 0x20e,
-};
-
-static void musicpal_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    ARMCPU *cpu;
-    qemu_irq *cpu_pic;
-    qemu_irq pic[32];
-    DeviceState *dev;
-    DeviceState *i2c_dev;
-    DeviceState *lcd_dev;
-    DeviceState *key_dev;
-    DeviceState *wm8750_dev;
-    SysBusDevice *s;
-    i2c_bus *i2c;
-    int i;
-    unsigned long flash_size;
-    DriveInfo *dinfo;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-
-    if (!cpu_model) {
-        cpu_model = "arm926";
-    }
-    cpu = cpu_arm_init(cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    cpu_pic = arm_pic_init_cpu(cpu);
-
-    /* For now we use a fixed - the original - RAM size */
-    memory_region_init_ram(ram, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, 0, ram);
-
-    memory_region_init_ram(sram, "musicpal.sram", MP_SRAM_SIZE);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
-
-    dev = sysbus_create_simple("mv88w8618_pic", MP_PIC_BASE,
-                               cpu_pic[ARM_PIC_CPU_IRQ]);
-    for (i = 0; i < 32; i++) {
-        pic[i] = qdev_get_gpio_in(dev, i);
-    }
-    sysbus_create_varargs("mv88w8618_pit", MP_PIT_BASE, pic[MP_TIMER1_IRQ],
-                          pic[MP_TIMER2_IRQ], pic[MP_TIMER3_IRQ],
-                          pic[MP_TIMER4_IRQ], NULL);
-
-    if (serial_hds[0]) {
-        serial_mm_init(address_space_mem, MP_UART1_BASE, 2, pic[MP_UART1_IRQ],
-                       1825000, serial_hds[0], DEVICE_NATIVE_ENDIAN);
-    }
-    if (serial_hds[1]) {
-        serial_mm_init(address_space_mem, MP_UART2_BASE, 2, pic[MP_UART2_IRQ],
-                       1825000, serial_hds[1], DEVICE_NATIVE_ENDIAN);
-    }
-
-    /* Register flash */
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (dinfo) {
-        flash_size = bdrv_getlength(dinfo->bdrv);
-        if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
-            flash_size != 32*1024*1024) {
-            fprintf(stderr, "Invalid flash image size\n");
-            exit(1);
-        }
-
-        /*
-         * The original U-Boot accesses the flash at 0xFE000000 instead of
-         * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
-         * image is smaller than 32 MB.
-         */
-#ifdef TARGET_WORDS_BIGENDIAN
-        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
-                              "musicpal.flash", flash_size,
-                              dinfo->bdrv, 0x10000,
-                              (flash_size + 0xffff) >> 16,
-                              MP_FLASH_SIZE_MAX / flash_size,
-                              2, 0x00BF, 0x236D, 0x0000, 0x0000,
-                              0x5555, 0x2AAA, 1);
-#else
-        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
-                              "musicpal.flash", flash_size,
-                              dinfo->bdrv, 0x10000,
-                              (flash_size + 0xffff) >> 16,
-                              MP_FLASH_SIZE_MAX / flash_size,
-                              2, 0x00BF, 0x236D, 0x0000, 0x0000,
-                              0x5555, 0x2AAA, 0);
-#endif
-
-    }
-    sysbus_create_simple("mv88w8618_flashcfg", MP_FLASHCFG_BASE, NULL);
-
-    qemu_check_nic_model(&nd_table[0], "mv88w8618");
-    dev = qdev_create(NULL, "mv88w8618_eth");
-    qdev_set_nic_properties(dev, &nd_table[0]);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[MP_ETH_IRQ]);
-
-    sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
-
-    musicpal_misc_init(SYS_BUS_DEVICE(dev));
-
-    dev = sysbus_create_simple("musicpal_gpio", MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
-    i2c_dev = sysbus_create_simple("gpio_i2c", -1, NULL);
-    i2c = (i2c_bus *)qdev_get_child_bus(i2c_dev, "i2c");
-
-    lcd_dev = sysbus_create_simple("musicpal_lcd", MP_LCD_BASE, NULL);
-    key_dev = sysbus_create_simple("musicpal_key", -1, NULL);
-
-    /* I2C read data */
-    qdev_connect_gpio_out(i2c_dev, 0,
-                          qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
-    /* I2C data */
-    qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
-    /* I2C clock */
-    qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
-
-    for (i = 0; i < 3; i++) {
-        qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
-    }
-    for (i = 0; i < 4; i++) {
-        qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
-    }
-    for (i = 4; i < 8; i++) {
-        qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
-    }
-
-    wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
-    dev = qdev_create(NULL, "mv88w8618_audio");
-    s = SYS_BUS_DEVICE(dev);
-    qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
-    sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
-
-    musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
-    musicpal_binfo.kernel_filename = kernel_filename;
-    musicpal_binfo.kernel_cmdline = kernel_cmdline;
-    musicpal_binfo.initrd_filename = initrd_filename;
-    arm_load_kernel(cpu, &musicpal_binfo);
-}
-
-static QEMUMachine musicpal_machine = {
-    .name = "musicpal",
-    .desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)",
-    .init = musicpal_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void musicpal_machine_init(void)
-{
-    qemu_register_machine(&musicpal_machine);
-}
-
-machine_init(musicpal_machine_init);
-
-static void mv88w8618_wlan_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = mv88w8618_wlan_init;
-}
-
-static const TypeInfo mv88w8618_wlan_info = {
-    .name          = "mv88w8618_wlan",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SysBusDevice),
-    .class_init    = mv88w8618_wlan_class_init,
-};
-
-static void musicpal_register_types(void)
-{
-    type_register_static(&mv88w8618_pic_info);
-    type_register_static(&mv88w8618_pit_info);
-    type_register_static(&mv88w8618_flashcfg_info);
-    type_register_static(&mv88w8618_eth_info);
-    type_register_static(&mv88w8618_wlan_info);
-    type_register_static(&musicpal_lcd_info);
-    type_register_static(&musicpal_gpio_info);
-    type_register_static(&musicpal_key_info);
-}
-
-type_init(musicpal_register_types)
index 61e918fa834ef2e997399e9ee264c6d371454d4a..de3e502596f080de222bc055d6a042a3bea1cdeb 100644 (file)
--- a/hw/nand.c
+++ b/hw/nand.c
 
 #ifndef NAND_IO
 
-# include "hw.h"
-# include "flash.h"
+# include "hw/hw.h"
+# include "hw/flash.h"
 # include "sysemu/blockdev.h"
-# include "sysbus.h"
+# include "hw/sysbus.h"
 #include "qemu/error-report.h"
 
 # define NAND_CMD_READ0                0x00
index 342c6bdad1634ffbe3a275873dd8980779047ac2..47c00c3a7652e7792c46496945940ca01e1aa6c6 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
-#include "qdev.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
+#include "hw/qdev.h"
 #include "net/net.h"
-#include "ne2000.h"
+#include "hw/ne2000.h"
 #include "exec/address-spaces.h"
 
 typedef struct ISANE2000State {
index 3dd1c844e835816ddac2618bae7e60beb4206f2e..7dadc1cea7ab60f593f0a3bd4c6f18f79674cd42 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "net/net.h"
-#include "ne2000.h"
-#include "loader.h"
+#include "hw/ne2000.h"
+#include "hw/loader.h"
 #include "sysemu/sysemu.h"
 
 /* debug NE2000 card */
diff --git a/hw/nseries.c b/hw/nseries.c
deleted file mode 100644 (file)
index 99d353a..0000000
+++ /dev/null
@@ -1,1430 +0,0 @@
-/*
- * Nokia N-series internet tablets.
- *
- * Copyright (C) 2007 Nokia Corporation
- * Written by Andrzej Zaborowski <andrew@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
- *
- * 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 "qemu-common.h"
-#include "sysemu/sysemu.h"
-#include "omap.h"
-#include "arm-misc.h"
-#include "irq.h"
-#include "ui/console.h"
-#include "boards.h"
-#include "i2c.h"
-#include "devices.h"
-#include "flash.h"
-#include "hw.h"
-#include "bt.h"
-#include "loader.h"
-#include "sysemu/blockdev.h"
-#include "sysbus.h"
-#include "exec/address-spaces.h"
-
-/* Nokia N8x0 support */
-struct n800_s {
-    struct omap_mpu_state_s *mpu;
-
-    struct rfbi_chip_s blizzard;
-    struct {
-        void *opaque;
-        uint32_t (*txrx)(void *opaque, uint32_t value, int len);
-        uWireSlave *chip;
-    } ts;
-
-    int keymap[0x80];
-    DeviceState *kbd;
-
-    DeviceState *usb;
-    void *retu;
-    void *tahvo;
-    DeviceState *nand;
-};
-
-/* GPIO pins */
-#define N8X0_TUSB_ENABLE_GPIO          0
-#define N800_MMC2_WP_GPIO              8
-#define N800_UNKNOWN_GPIO0             9       /* out */
-#define N810_MMC2_VIOSD_GPIO           9
-#define N810_HEADSET_AMP_GPIO          10
-#define N800_CAM_TURN_GPIO             12
-#define N810_GPS_RESET_GPIO            12
-#define N800_BLIZZARD_POWERDOWN_GPIO   15
-#define N800_MMC1_WP_GPIO              23
-#define N810_MMC2_VSD_GPIO             23
-#define N8X0_ONENAND_GPIO              26
-#define N810_BLIZZARD_RESET_GPIO       30
-#define N800_UNKNOWN_GPIO2             53      /* out */
-#define N8X0_TUSB_INT_GPIO             58
-#define N8X0_BT_WKUP_GPIO              61
-#define N8X0_STI_GPIO                  62
-#define N8X0_CBUS_SEL_GPIO             64
-#define N8X0_CBUS_DAT_GPIO             65
-#define N8X0_CBUS_CLK_GPIO             66
-#define N8X0_WLAN_IRQ_GPIO             87
-#define N8X0_BT_RESET_GPIO             92
-#define N8X0_TEA5761_CS_GPIO           93
-#define N800_UNKNOWN_GPIO              94
-#define N810_TSC_RESET_GPIO            94
-#define N800_CAM_ACT_GPIO              95
-#define N810_GPS_WAKEUP_GPIO           95
-#define N8X0_MMC_CS_GPIO               96
-#define N8X0_WLAN_PWR_GPIO             97
-#define N8X0_BT_HOST_WKUP_GPIO         98
-#define N810_SPEAKER_AMP_GPIO          101
-#define N810_KB_LOCK_GPIO              102
-#define N800_TSC_TS_GPIO               103
-#define N810_TSC_TS_GPIO               106
-#define N8X0_HEADPHONE_GPIO            107
-#define N8X0_RETU_GPIO                 108
-#define N800_TSC_KP_IRQ_GPIO           109
-#define N810_KEYBOARD_GPIO             109
-#define N800_BAT_COVER_GPIO            110
-#define N810_SLIDE_GPIO                        110
-#define N8X0_TAHVO_GPIO                        111
-#define N800_UNKNOWN_GPIO4             112     /* out */
-#define N810_SLEEPX_LED_GPIO           112
-#define N800_TSC_RESET_GPIO            118     /* ? */
-#define N810_AIC33_RESET_GPIO          118
-#define N800_TSC_UNKNOWN_GPIO          119     /* out */
-#define N8X0_TMP105_GPIO               125
-
-/* Config */
-#define BT_UART                                0
-#define XLDR_LL_UART                   1
-
-/* Addresses on the I2C bus 0 */
-#define N810_TLV320AIC33_ADDR          0x18    /* Audio CODEC */
-#define N8X0_TCM825x_ADDR              0x29    /* Camera */
-#define N810_LP5521_ADDR               0x32    /* LEDs */
-#define N810_TSL2563_ADDR              0x3d    /* Light sensor */
-#define N810_LM8323_ADDR               0x45    /* Keyboard */
-/* Addresses on the I2C bus 1 */
-#define N8X0_TMP105_ADDR               0x48    /* Temperature sensor */
-#define N8X0_MENELAUS_ADDR             0x72    /* Power management */
-
-/* Chipselects on GPMC NOR interface */
-#define N8X0_ONENAND_CS                        0
-#define N8X0_USB_ASYNC_CS              1
-#define N8X0_USB_SYNC_CS               4
-
-#define N8X0_BD_ADDR                   0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81
-
-static void n800_mmc_cs_cb(void *opaque, int line, int level)
-{
-    /* TODO: this seems to actually be connected to the menelaus, to
-     * which also both MMC slots connect.  */
-    omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
-
-    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
-}
-
-static void n8x0_gpio_setup(struct n800_s *s)
-{
-    qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->mpu->mmc, 1);
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
-
-    qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO));
-}
-
-#define MAEMO_CAL_HEADER(...)                          \
-    'C',  'o',  'n',  'F',  0x02, 0x00, 0x04, 0x00,    \
-    __VA_ARGS__,                                       \
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-static const uint8_t n8x0_cal_wlan_mac[] = {
-    MAEMO_CAL_HEADER('w', 'l', 'a', 'n', '-', 'm', 'a', 'c')
-    0x1c, 0x00, 0x00, 0x00, 0x47, 0xd6, 0x69, 0xb3,
-    0x30, 0x08, 0xa0, 0x83, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
-    0x89, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
-    0x5d, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
-};
-
-static const uint8_t n8x0_cal_bt_id[] = {
-    MAEMO_CAL_HEADER('b', 't', '-', 'i', 'd', 0, 0, 0)
-    0x0a, 0x00, 0x00, 0x00, 0xa3, 0x4b, 0xf6, 0x96,
-    0xa8, 0xeb, 0xb2, 0x41, 0x00, 0x00, 0x00, 0x00,
-    N8X0_BD_ADDR,
-};
-
-static void n8x0_nand_setup(struct n800_s *s)
-{
-    char *otp_region;
-    DriveInfo *dinfo;
-
-    s->nand = qdev_create(NULL, "onenand");
-    qdev_prop_set_uint16(s->nand, "manufacturer_id", NAND_MFR_SAMSUNG);
-    /* Either 0x40 or 0x48 are OK for the device ID */
-    qdev_prop_set_uint16(s->nand, "device_id", 0x48);
-    qdev_prop_set_uint16(s->nand, "version_id", 0);
-    qdev_prop_set_int32(s->nand, "shift", 1);
-    dinfo = drive_get(IF_MTD, 0, 0);
-    if (dinfo && dinfo->bdrv) {
-        qdev_prop_set_drive_nofail(s->nand, "drive", dinfo->bdrv);
-    }
-    qdev_init_nofail(s->nand);
-    sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
-                       qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO));
-    omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS,
-                     sysbus_mmio_get_region(SYS_BUS_DEVICE(s->nand), 0));
-    otp_region = onenand_raw_otp(s->nand);
-
-    memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
-    memcpy(otp_region + 0x800, n8x0_cal_bt_id, sizeof(n8x0_cal_bt_id));
-    /* XXX: in theory should also update the OOB for both pages */
-}
-
-static qemu_irq n8x0_system_powerdown;
-
-static void n8x0_powerdown_req(Notifier *n, void *opaque)
-{
-    qemu_irq_raise(n8x0_system_powerdown);
-}
-
-static Notifier n8x0_system_powerdown_notifier = {
-    .notify = n8x0_powerdown_req
-};
-
-static void n8x0_i2c_setup(struct n800_s *s)
-{
-    DeviceState *dev;
-    qemu_irq tmp_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TMP105_GPIO);
-    i2c_bus *i2c = omap_i2c_bus(s->mpu->i2c[0]);
-
-    /* Attach a menelaus PM chip */
-    dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR);
-    qdev_connect_gpio_out(dev, 3,
-                          qdev_get_gpio_in(s->mpu->ih[0],
-                                           OMAP_INT_24XX_SYS_NIRQ));
-
-    n8x0_system_powerdown = qdev_get_gpio_in(dev, 3);
-    qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier);
-
-    /* Attach a TMP105 PM chip (A0 wired to ground) */
-    dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
-    qdev_connect_gpio_out(dev, 0, tmp_irq);
-}
-
-/* Touchscreen and keypad controller */
-static MouseTransformInfo n800_pointercal = {
-    .x = 800,
-    .y = 480,
-    .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 },
-};
-
-static MouseTransformInfo n810_pointercal = {
-    .x = 800,
-    .y = 480,
-    .a = { 15041, 148, -4731056, 171, -10238, 35933380, 65536 },
-};
-
-#define RETU_KEYCODE   61      /* F3 */
-
-static void n800_key_event(void *opaque, int keycode)
-{
-    struct n800_s *s = (struct n800_s *) opaque;
-    int code = s->keymap[keycode & 0x7f];
-
-    if (code == -1) {
-        if ((keycode & 0x7f) == RETU_KEYCODE)
-            retu_key_event(s->retu, !(keycode & 0x80));
-        return;
-    }
-
-    tsc210x_key_event(s->ts.chip, code, !(keycode & 0x80));
-}
-
-static const int n800_keys[16] = {
-    -1,
-    72,        /* Up */
-    63,        /* Home (F5) */
-    -1,
-    75,        /* Left */
-    28,        /* Enter */
-    77,        /* Right */
-    -1,
-     1,        /* Cycle (ESC) */
-    80,        /* Down */
-    62,        /* Menu (F4) */
-    -1,
-    66,        /* Zoom- (F8) */
-    64,        /* FullScreen (F6) */
-    65,        /* Zoom+ (F7) */
-    -1,
-};
-
-static void n800_tsc_kbd_setup(struct n800_s *s)
-{
-    int i;
-
-    /* XXX: are the three pins inverted inside the chip between the
-     * tsc and the cpu (N4111)?  */
-    qemu_irq penirq = NULL;    /* NC */
-    qemu_irq kbirq = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_KP_IRQ_GPIO);
-    qemu_irq dav = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_TS_GPIO);
-
-    s->ts.chip = tsc2301_init(penirq, kbirq, dav);
-    s->ts.opaque = s->ts.chip->opaque;
-    s->ts.txrx = tsc210x_txrx;
-
-    for (i = 0; i < 0x80; i ++)
-        s->keymap[i] = -1;
-    for (i = 0; i < 0x10; i ++)
-        if (n800_keys[i] >= 0)
-            s->keymap[n800_keys[i]] = i;
-
-    qemu_add_kbd_event_handler(n800_key_event, s);
-
-    tsc210x_set_transform(s->ts.chip, &n800_pointercal);
-}
-
-static void n810_tsc_setup(struct n800_s *s)
-{
-    qemu_irq pintdav = qdev_get_gpio_in(s->mpu->gpio, N810_TSC_TS_GPIO);
-
-    s->ts.opaque = tsc2005_init(pintdav);
-    s->ts.txrx = tsc2005_txrx;
-
-    tsc2005_set_transform(s->ts.opaque, &n810_pointercal);
-}
-
-/* N810 Keyboard controller */
-static void n810_key_event(void *opaque, int keycode)
-{
-    struct n800_s *s = (struct n800_s *) opaque;
-    int code = s->keymap[keycode & 0x7f];
-
-    if (code == -1) {
-        if ((keycode & 0x7f) == RETU_KEYCODE)
-            retu_key_event(s->retu, !(keycode & 0x80));
-        return;
-    }
-
-    lm832x_key_event(s->kbd, code, !(keycode & 0x80));
-}
-
-#define M      0
-
-static int n810_keys[0x80] = {
-    [0x01] = 16,       /* Q */
-    [0x02] = 37,       /* K */
-    [0x03] = 24,       /* O */
-    [0x04] = 25,       /* P */
-    [0x05] = 14,       /* Backspace */
-    [0x06] = 30,       /* A */
-    [0x07] = 31,       /* S */
-    [0x08] = 32,       /* D */
-    [0x09] = 33,       /* F */
-    [0x0a] = 34,       /* G */
-    [0x0b] = 35,       /* H */
-    [0x0c] = 36,       /* J */
-
-    [0x11] = 17,       /* W */
-    [0x12] = 62,       /* Menu (F4) */
-    [0x13] = 38,       /* L */
-    [0x14] = 40,       /* ' (Apostrophe) */
-    [0x16] = 44,       /* Z */
-    [0x17] = 45,       /* X */
-    [0x18] = 46,       /* C */
-    [0x19] = 47,       /* V */
-    [0x1a] = 48,       /* B */
-    [0x1b] = 49,       /* N */
-    [0x1c] = 42,       /* Shift (Left shift) */
-    [0x1f] = 65,       /* Zoom+ (F7) */
-
-    [0x21] = 18,       /* E */
-    [0x22] = 39,       /* ; (Semicolon) */
-    [0x23] = 12,       /* - (Minus) */
-    [0x24] = 13,       /* = (Equal) */
-    [0x2b] = 56,       /* Fn (Left Alt) */
-    [0x2c] = 50,       /* M */
-    [0x2f] = 66,       /* Zoom- (F8) */
-
-    [0x31] = 19,       /* R */
-    [0x32] = 29 | M,   /* Right Ctrl */
-    [0x34] = 57,       /* Space */
-    [0x35] = 51,       /* , (Comma) */
-    [0x37] = 72 | M,   /* Up */
-    [0x3c] = 82 | M,   /* Compose (Insert) */
-    [0x3f] = 64,       /* FullScreen (F6) */
-
-    [0x41] = 20,       /* T */
-    [0x44] = 52,       /* . (Dot) */
-    [0x46] = 77 | M,   /* Right */
-    [0x4f] = 63,       /* Home (F5) */
-    [0x51] = 21,       /* Y */
-    [0x53] = 80 | M,   /* Down */
-    [0x55] = 28,       /* Enter */
-    [0x5f] =  1,       /* Cycle (ESC) */
-
-    [0x61] = 22,       /* U */
-    [0x64] = 75 | M,   /* Left */
-
-    [0x71] = 23,       /* I */
-#if 0
-    [0x75] = 28 | M,   /* KP Enter (KP Enter) */
-#else
-    [0x75] = 15,       /* KP Enter (Tab) */
-#endif
-};
-
-#undef M
-
-static void n810_kbd_setup(struct n800_s *s)
-{
-    qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
-    int i;
-
-    for (i = 0; i < 0x80; i ++)
-        s->keymap[i] = -1;
-    for (i = 0; i < 0x80; i ++)
-        if (n810_keys[i] > 0)
-            s->keymap[n810_keys[i]] = i;
-
-    qemu_add_kbd_event_handler(n810_key_event, s);
-
-    /* Attach the LM8322 keyboard to the I2C bus,
-     * should happen in n8x0_i2c_setup and s->kbd be initialised here.  */
-    s->kbd = i2c_create_slave(omap_i2c_bus(s->mpu->i2c[0]),
-                           "lm8323", N810_LM8323_ADDR);
-    qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
-}
-
-/* LCD MIPI DBI-C controller (URAL) */
-struct mipid_s {
-    int resp[4];
-    int param[4];
-    int p;
-    int pm;
-    int cmd;
-
-    int sleep;
-    int booster;
-    int te;
-    int selfcheck;
-    int partial;
-    int normal;
-    int vscr;
-    int invert;
-    int onoff;
-    int gamma;
-    uint32_t id;
-};
-
-static void mipid_reset(struct mipid_s *s)
-{
-    if (!s->sleep)
-        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
-
-    s->pm = 0;
-    s->cmd = 0;
-
-    s->sleep = 1;
-    s->booster = 0;
-    s->selfcheck =
-            (1 << 7) | /* Register loading OK.  */
-            (1 << 5) | /* The chip is attached.  */
-            (1 << 4);  /* Display glass still in one piece.  */
-    s->te = 0;
-    s->partial = 0;
-    s->normal = 1;
-    s->vscr = 0;
-    s->invert = 0;
-    s->onoff = 1;
-    s->gamma = 0;
-}
-
-static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
-{
-    struct mipid_s *s = (struct mipid_s *) opaque;
-    uint8_t ret;
-
-    if (len > 9)
-        hw_error("%s: FIXME: bad SPI word width %i\n", __FUNCTION__, len);
-
-    if (s->p >= ARRAY_SIZE(s->resp))
-        ret = 0;
-    else
-        ret = s->resp[s->p ++];
-    if (s->pm --> 0)
-        s->param[s->pm] = cmd;
-    else
-        s->cmd = cmd;
-
-    switch (s->cmd) {
-    case 0x00: /* NOP */
-        break;
-
-    case 0x01: /* SWRESET */
-        mipid_reset(s);
-        break;
-
-    case 0x02: /* BSTROFF */
-        s->booster = 0;
-        break;
-    case 0x03: /* BSTRON */
-        s->booster = 1;
-        break;
-
-    case 0x04: /* RDDID */
-        s->p = 0;
-        s->resp[0] = (s->id >> 16) & 0xff;
-        s->resp[1] = (s->id >>  8) & 0xff;
-        s->resp[2] = (s->id >>  0) & 0xff;
-        break;
-
-    case 0x06: /* RD_RED */
-    case 0x07: /* RD_GREEN */
-        /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so
-         * for the bootloader one needs to change this.  */
-    case 0x08: /* RD_BLUE */
-        s->p = 0;
-        /* TODO: return first pixel components */
-        s->resp[0] = 0x01;
-        break;
-
-    case 0x09: /* RDDST */
-        s->p = 0;
-        s->resp[0] = s->booster << 7;
-        s->resp[1] = (5 << 4) | (s->partial << 2) |
-                (s->sleep << 1) | s->normal;
-        s->resp[2] = (s->vscr << 7) | (s->invert << 5) |
-                (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2);
-        s->resp[3] = s->gamma << 6;
-        break;
-
-    case 0x0a: /* RDDPM */
-        s->p = 0;
-        s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) |
-                (s->partial << 5) | (s->sleep << 6) | (s->booster << 7);
-        break;
-    case 0x0b: /* RDDMADCTR */
-        s->p = 0;
-        s->resp[0] = 0;
-        break;
-    case 0x0c: /* RDDCOLMOD */
-        s->p = 0;
-        s->resp[0] = 5;        /* 65K colours */
-        break;
-    case 0x0d: /* RDDIM */
-        s->p = 0;
-        s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma;
-        break;
-    case 0x0e: /* RDDSM */
-        s->p = 0;
-        s->resp[0] = s->te << 7;
-        break;
-    case 0x0f: /* RDDSDR */
-        s->p = 0;
-        s->resp[0] = s->selfcheck;
-        break;
-
-    case 0x10: /* SLPIN */
-        s->sleep = 1;
-        break;
-    case 0x11: /* SLPOUT */
-        s->sleep = 0;
-        s->selfcheck ^= 1 << 6;        /* POFF self-diagnosis Ok */
-        break;
-
-    case 0x12: /* PTLON */
-        s->partial = 1;
-        s->normal = 0;
-        s->vscr = 0;
-        break;
-    case 0x13: /* NORON */
-        s->partial = 0;
-        s->normal = 1;
-        s->vscr = 0;
-        break;
-
-    case 0x20: /* INVOFF */
-        s->invert = 0;
-        break;
-    case 0x21: /* INVON */
-        s->invert = 1;
-        break;
-
-    case 0x22: /* APOFF */
-    case 0x23: /* APON */
-        goto bad_cmd;
-
-    case 0x25: /* WRCNTR */
-        if (s->pm < 0)
-            s->pm = 1;
-        goto bad_cmd;
-
-    case 0x26: /* GAMSET */
-        if (!s->pm)
-            s->gamma = ffs(s->param[0] & 0xf) - 1;
-        else if (s->pm < 0)
-            s->pm = 1;
-        break;
-
-    case 0x28: /* DISPOFF */
-        s->onoff = 0;
-        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
-        break;
-    case 0x29: /* DISPON */
-        s->onoff = 1;
-        fprintf(stderr, "%s: Display on\n", __FUNCTION__);
-        break;
-
-    case 0x2a: /* CASET */
-    case 0x2b: /* RASET */
-    case 0x2c: /* RAMWR */
-    case 0x2d: /* RGBSET */
-    case 0x2e: /* RAMRD */
-    case 0x30: /* PTLAR */
-    case 0x33: /* SCRLAR */
-        goto bad_cmd;
-
-    case 0x34: /* TEOFF */
-        s->te = 0;
-        break;
-    case 0x35: /* TEON */
-        if (!s->pm)
-            s->te = 1;
-        else if (s->pm < 0)
-            s->pm = 1;
-        break;
-
-    case 0x36: /* MADCTR */
-        goto bad_cmd;
-
-    case 0x37: /* VSCSAD */
-        s->partial = 0;
-        s->normal = 0;
-        s->vscr = 1;
-        break;
-
-    case 0x38: /* IDMOFF */
-    case 0x39: /* IDMON */
-    case 0x3a: /* COLMOD */
-        goto bad_cmd;
-
-    case 0xb0: /* CLKINT / DISCTL */
-    case 0xb1: /* CLKEXT */
-        if (s->pm < 0)
-            s->pm = 2;
-        break;
-
-    case 0xb4: /* FRMSEL */
-        break;
-
-    case 0xb5: /* FRM8SEL */
-    case 0xb6: /* TMPRNG / INIESC */
-    case 0xb7: /* TMPHIS / NOP2 */
-    case 0xb8: /* TMPREAD / MADCTL */
-    case 0xba: /* DISTCTR */
-    case 0xbb: /* EPVOL */
-        goto bad_cmd;
-
-    case 0xbd: /* Unknown */
-        s->p = 0;
-        s->resp[0] = 0;
-        s->resp[1] = 1;
-        break;
-
-    case 0xc2: /* IFMOD */
-        if (s->pm < 0)
-            s->pm = 2;
-        break;
-
-    case 0xc6: /* PWRCTL */
-    case 0xc7: /* PPWRCTL */
-    case 0xd0: /* EPWROUT */
-    case 0xd1: /* EPWRIN */
-    case 0xd4: /* RDEV */
-    case 0xd5: /* RDRR */
-        goto bad_cmd;
-
-    case 0xda: /* RDID1 */
-        s->p = 0;
-        s->resp[0] = (s->id >> 16) & 0xff;
-        break;
-    case 0xdb: /* RDID2 */
-        s->p = 0;
-        s->resp[0] = (s->id >>  8) & 0xff;
-        break;
-    case 0xdc: /* RDID3 */
-        s->p = 0;
-        s->resp[0] = (s->id >>  0) & 0xff;
-        break;
-
-    default:
-    bad_cmd:
-        fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd);
-        break;
-    }
-
-    return ret;
-}
-
-static void *mipid_init(void)
-{
-    struct mipid_s *s = (struct mipid_s *) g_malloc0(sizeof(*s));
-
-    s->id = 0x838f03;
-    mipid_reset(s);
-
-    return s;
-}
-
-static void n8x0_spi_setup(struct n800_s *s)
-{
-    void *tsc = s->ts.opaque;
-    void *mipid = mipid_init();
-
-    omap_mcspi_attach(s->mpu->mcspi[0], s->ts.txrx, tsc, 0);
-    omap_mcspi_attach(s->mpu->mcspi[0], mipid_txrx, mipid, 1);
-}
-
-/* This task is normally performed by the bootloader.  If we're loading
- * a kernel directly, we need to enable the Blizzard ourselves.  */
-static void n800_dss_init(struct rfbi_chip_s *chip)
-{
-    uint8_t *fb_blank;
-
-    chip->write(chip->opaque, 0, 0x2a);                /* LCD Width register */
-    chip->write(chip->opaque, 1, 0x64);
-    chip->write(chip->opaque, 0, 0x2c);                /* LCD HNDP register */
-    chip->write(chip->opaque, 1, 0x1e);
-    chip->write(chip->opaque, 0, 0x2e);                /* LCD Height 0 register */
-    chip->write(chip->opaque, 1, 0xe0);
-    chip->write(chip->opaque, 0, 0x30);                /* LCD Height 1 register */
-    chip->write(chip->opaque, 1, 0x01);
-    chip->write(chip->opaque, 0, 0x32);                /* LCD VNDP register */
-    chip->write(chip->opaque, 1, 0x06);
-    chip->write(chip->opaque, 0, 0x68);                /* Display Mode register */
-    chip->write(chip->opaque, 1, 1);           /* Enable bit */
-
-    chip->write(chip->opaque, 0, 0x6c);        
-    chip->write(chip->opaque, 1, 0x00);                /* Input X Start Position */
-    chip->write(chip->opaque, 1, 0x00);                /* Input X Start Position */
-    chip->write(chip->opaque, 1, 0x00);                /* Input Y Start Position */
-    chip->write(chip->opaque, 1, 0x00);                /* Input Y Start Position */
-    chip->write(chip->opaque, 1, 0x1f);                /* Input X End Position */
-    chip->write(chip->opaque, 1, 0x03);                /* Input X End Position */
-    chip->write(chip->opaque, 1, 0xdf);                /* Input Y End Position */
-    chip->write(chip->opaque, 1, 0x01);                /* Input Y End Position */
-    chip->write(chip->opaque, 1, 0x00);                /* Output X Start Position */
-    chip->write(chip->opaque, 1, 0x00);                /* Output X Start Position */
-    chip->write(chip->opaque, 1, 0x00);                /* Output Y Start Position */
-    chip->write(chip->opaque, 1, 0x00);                /* Output Y Start Position */
-    chip->write(chip->opaque, 1, 0x1f);                /* Output X End Position */
-    chip->write(chip->opaque, 1, 0x03);                /* Output X End Position */
-    chip->write(chip->opaque, 1, 0xdf);                /* Output Y End Position */
-    chip->write(chip->opaque, 1, 0x01);                /* Output Y End Position */
-    chip->write(chip->opaque, 1, 0x01);                /* Input Data Format */
-    chip->write(chip->opaque, 1, 0x01);                /* Data Source Select */
-
-    fb_blank = memset(g_malloc(800 * 480 * 2), 0xff, 800 * 480 * 2);
-    /* Display Memory Data Port */
-    chip->block(chip->opaque, 1, fb_blank, 800 * 480 * 2, 800);
-    g_free(fb_blank);
-}
-
-static void n8x0_dss_setup(struct n800_s *s)
-{
-    s->blizzard.opaque = s1d13745_init(NULL);
-    s->blizzard.block = s1d13745_write_block;
-    s->blizzard.write = s1d13745_write;
-    s->blizzard.read = s1d13745_read;
-
-    omap_rfbi_attach(s->mpu->dss, 0, &s->blizzard);
-}
-
-static void n8x0_cbus_setup(struct n800_s *s)
-{
-    qemu_irq dat_out = qdev_get_gpio_in(s->mpu->gpio, N8X0_CBUS_DAT_GPIO);
-    qemu_irq retu_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_RETU_GPIO);
-    qemu_irq tahvo_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TAHVO_GPIO);
-
-    CBus *cbus = cbus_init(dat_out);
-
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
-
-    cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
-    cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
-}
-
-static void n8x0_uart_setup(struct n800_s *s)
-{
-    CharDriverState *radio = uart_hci_init(
-                    qdev_get_gpio_in(s->mpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
-
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO,
-                    csrhci_pins_get(radio)[csrhci_pin_reset]);
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_WKUP_GPIO,
-                    csrhci_pins_get(radio)[csrhci_pin_wakeup]);
-
-    omap_uart_attach(s->mpu->uart[BT_UART], radio);
-}
-
-static void n8x0_usb_setup(struct n800_s *s)
-{
-    SysBusDevice *dev;
-    s->usb = qdev_create(NULL, "tusb6010");
-    dev = SYS_BUS_DEVICE(s->usb);
-    qdev_init_nofail(s->usb);
-    sysbus_connect_irq(dev, 0,
-                       qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO));
-    /* Using the NOR interface */
-    omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_ASYNC_CS,
-                     sysbus_mmio_get_region(dev, 0));
-    omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_SYNC_CS,
-                     sysbus_mmio_get_region(dev, 1));
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_TUSB_ENABLE_GPIO,
-                          qdev_get_gpio_in(s->usb, 0)); /* tusb_pwr */
-}
-
-/* Setup done before the main bootloader starts by some early setup code
- * - used when we want to run the main bootloader in emulation.  This
- * isn't documented.  */
-static uint32_t n800_pinout[104] = {
-    0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0,
-    0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808,
-    0x08080808, 0x180800c4, 0x00b80000, 0x08080808,
-    0x080800bc, 0x00cc0808, 0x08081818, 0x18180128,
-    0x01241800, 0x18181818, 0x000000f0, 0x01300000,
-    0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b,
-    0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080,
-    0x007c0000, 0x00000000, 0x00000088, 0x00840000,
-    0x00000000, 0x00000094, 0x00980300, 0x0f180003,
-    0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c,
-    0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008,
-    0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f,
-    0x181800f4, 0x00f81818, 0x00000018, 0x000000fc,
-    0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008,
-    0x00000000, 0x00000038, 0x00340000, 0x00000000,
-    0x1a080070, 0x00641a1a, 0x08080808, 0x08080060,
-    0x005c0808, 0x08080808, 0x08080058, 0x00540808,
-    0x08080808, 0x0808006c, 0x00680808, 0x08080808,
-    0x000000a8, 0x00b00000, 0x08080808, 0x000000a0,
-    0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808,
-    0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff,
-    0x000000ac, 0x01040800, 0x08080b0f, 0x18180100,
-    0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a,
-    0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00,
-    0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118,
-    0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b,
-};
-
-static void n800_setup_nolo_tags(void *sram_base)
-{
-    int i;
-    uint32_t *p = sram_base + 0x8000;
-    uint32_t *v = sram_base + 0xa000;
-
-    memset(p, 0, 0x3000);
-
-    strcpy((void *) (p + 0), "QEMU N800");
-
-    strcpy((void *) (p + 8), "F5");
-
-    stl_raw(p + 10, 0x04f70000);
-    strcpy((void *) (p + 9), "RX-34");
-
-    /* RAM size in MB? */
-    stl_raw(p + 12, 0x80);
-
-    /* Pointer to the list of tags */
-    stl_raw(p + 13, OMAP2_SRAM_BASE + 0x9000);
-
-    /* The NOLO tags start here */
-    p = sram_base + 0x9000;
-#define ADD_TAG(tag, len)                              \
-    stw_raw((uint16_t *) p + 0, tag);                  \
-    stw_raw((uint16_t *) p + 1, len); p ++;            \
-    stl_raw(p ++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
-
-    /* OMAP STI console? Pin out settings? */
-    ADD_TAG(0x6e01, 414);
-    for (i = 0; i < ARRAY_SIZE(n800_pinout); i ++)
-        stl_raw(v ++, n800_pinout[i]);
-
-    /* Kernel memsize? */
-    ADD_TAG(0x6e05, 1);
-    stl_raw(v ++, 2);
-
-    /* NOLO serial console */
-    ADD_TAG(0x6e02, 4);
-    stl_raw(v ++, XLDR_LL_UART);       /* UART number (1 - 3) */
-
-#if 0
-    /* CBUS settings (Retu/AVilma) */
-    ADD_TAG(0x6e03, 6);
-    stw_raw((uint16_t *) v + 0, 65);   /* CBUS GPIO0 */
-    stw_raw((uint16_t *) v + 1, 66);   /* CBUS GPIO1 */
-    stw_raw((uint16_t *) v + 2, 64);   /* CBUS GPIO2 */
-    v += 2;
-#endif
-
-    /* Nokia ASIC BB5 (Retu/Tahvo) */
-    ADD_TAG(0x6e0a, 4);
-    stw_raw((uint16_t *) v + 0, 111);  /* "Retu" interrupt GPIO */
-    stw_raw((uint16_t *) v + 1, 108);  /* "Tahvo" interrupt GPIO */
-    v ++;
-
-    /* LCD console? */
-    ADD_TAG(0x6e04, 4);
-    stw_raw((uint16_t *) v + 0, 30);   /* ??? */
-    stw_raw((uint16_t *) v + 1, 24);   /* ??? */
-    v ++;
-
-#if 0
-    /* LCD settings */
-    ADD_TAG(0x6e06, 2);
-    stw_raw((uint16_t *) (v ++), 15);  /* ??? */
-#endif
-
-    /* I^2C (Menelaus) */
-    ADD_TAG(0x6e07, 4);
-    stl_raw(v ++, 0x00720000);         /* ??? */
-
-    /* Unknown */
-    ADD_TAG(0x6e0b, 6);
-    stw_raw((uint16_t *) v + 0, 94);   /* ??? */
-    stw_raw((uint16_t *) v + 1, 23);   /* ??? */
-    stw_raw((uint16_t *) v + 2, 0);    /* ??? */
-    v += 2;
-
-    /* OMAP gpio switch info */
-    ADD_TAG(0x6e0c, 80);
-    strcpy((void *) v, "bat_cover");   v += 3;
-    stw_raw((uint16_t *) v + 0, 110);  /* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 1);    /* GPIO num ??? */
-    v += 2;
-    strcpy((void *) v, "cam_act");     v += 3;
-    stw_raw((uint16_t *) v + 0, 95);   /* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 32);   /* GPIO num ??? */
-    v += 2;
-    strcpy((void *) v, "cam_turn");    v += 3;
-    stw_raw((uint16_t *) v + 0, 12);   /* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 33);   /* GPIO num ??? */
-    v += 2;
-    strcpy((void *) v, "headphone");   v += 3;
-    stw_raw((uint16_t *) v + 0, 107);  /* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 17);   /* GPIO num ??? */
-    v += 2;
-
-    /* Bluetooth */
-    ADD_TAG(0x6e0e, 12);
-    stl_raw(v ++, 0x5c623d01);         /* ??? */
-    stl_raw(v ++, 0x00000201);         /* ??? */
-    stl_raw(v ++, 0x00000000);         /* ??? */
-
-    /* CX3110x WLAN settings */
-    ADD_TAG(0x6e0f, 8);
-    stl_raw(v ++, 0x00610025);         /* ??? */
-    stl_raw(v ++, 0xffff0057);         /* ??? */
-
-    /* MMC host settings */
-    ADD_TAG(0x6e10, 12);
-    stl_raw(v ++, 0xffff000f);         /* ??? */
-    stl_raw(v ++, 0xffffffff);         /* ??? */
-    stl_raw(v ++, 0x00000060);         /* ??? */
-
-    /* OneNAND chip select */
-    ADD_TAG(0x6e11, 10);
-    stl_raw(v ++, 0x00000401);         /* ??? */
-    stl_raw(v ++, 0x0002003a);         /* ??? */
-    stl_raw(v ++, 0x00000002);         /* ??? */
-
-    /* TEA5761 sensor settings */
-    ADD_TAG(0x6e12, 2);
-    stl_raw(v ++, 93);                 /* GPIO num ??? */
-
-#if 0
-    /* Unknown tag */
-    ADD_TAG(6e09, 0);
-
-    /* Kernel UART / console */
-    ADD_TAG(6e12, 0);
-#endif
-
-    /* End of the list */
-    stl_raw(p ++, 0x00000000);
-    stl_raw(p ++, 0x00000000);
-}
-
-/* This task is normally performed by the bootloader.  If we're loading
- * a kernel directly, we need to set up GPMC mappings ourselves.  */
-static void n800_gpmc_init(struct n800_s *s)
-{
-    uint32_t config7 =
-            (0xf << 8) |       /* MASKADDRESS */
-            (1 << 6) |         /* CSVALID */
-            (4 << 0);          /* BASEADDRESS */
-
-    cpu_physical_memory_write(0x6800a078,              /* GPMC_CONFIG7_0 */
-                    (void *) &config7, sizeof(config7));
-}
-
-/* Setup sequence done by the bootloader */
-static void n8x0_boot_init(void *opaque)
-{
-    struct n800_s *s = (struct n800_s *) opaque;
-    uint32_t buf;
-
-    /* PRCM setup */
-#define omap_writel(addr, val) \
-    buf = (val);                       \
-    cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf))
-
-    omap_writel(0x48008060, 0x41);             /* PRCM_CLKSRC_CTRL */
-    omap_writel(0x48008070, 1);                        /* PRCM_CLKOUT_CTRL */
-    omap_writel(0x48008078, 0);                        /* PRCM_CLKEMUL_CTRL */
-    omap_writel(0x48008090, 0);                        /* PRCM_VOLTSETUP */
-    omap_writel(0x48008094, 0);                        /* PRCM_CLKSSETUP */
-    omap_writel(0x48008098, 0);                        /* PRCM_POLCTRL */
-    omap_writel(0x48008140, 2);                        /* CM_CLKSEL_MPU */
-    omap_writel(0x48008148, 0);                        /* CM_CLKSTCTRL_MPU */
-    omap_writel(0x48008158, 1);                        /* RM_RSTST_MPU */
-    omap_writel(0x480081c8, 0x15);             /* PM_WKDEP_MPU */
-    omap_writel(0x480081d4, 0x1d4);            /* PM_EVGENCTRL_MPU */
-    omap_writel(0x480081d8, 0);                        /* PM_EVEGENONTIM_MPU */
-    omap_writel(0x480081dc, 0);                        /* PM_EVEGENOFFTIM_MPU */
-    omap_writel(0x480081e0, 0xc);              /* PM_PWSTCTRL_MPU */
-    omap_writel(0x48008200, 0x047e7ff7);       /* CM_FCLKEN1_CORE */
-    omap_writel(0x48008204, 0x00000004);       /* CM_FCLKEN2_CORE */
-    omap_writel(0x48008210, 0x047e7ff1);       /* CM_ICLKEN1_CORE */
-    omap_writel(0x48008214, 0x00000004);       /* CM_ICLKEN2_CORE */
-    omap_writel(0x4800821c, 0x00000000);       /* CM_ICLKEN4_CORE */
-    omap_writel(0x48008230, 0);                        /* CM_AUTOIDLE1_CORE */
-    omap_writel(0x48008234, 0);                        /* CM_AUTOIDLE2_CORE */
-    omap_writel(0x48008238, 7);                        /* CM_AUTOIDLE3_CORE */
-    omap_writel(0x4800823c, 0);                        /* CM_AUTOIDLE4_CORE */
-    omap_writel(0x48008240, 0x04360626);       /* CM_CLKSEL1_CORE */
-    omap_writel(0x48008244, 0x00000014);       /* CM_CLKSEL2_CORE */
-    omap_writel(0x48008248, 0);                        /* CM_CLKSTCTRL_CORE */
-    omap_writel(0x48008300, 0x00000000);       /* CM_FCLKEN_GFX */
-    omap_writel(0x48008310, 0x00000000);       /* CM_ICLKEN_GFX */
-    omap_writel(0x48008340, 0x00000001);       /* CM_CLKSEL_GFX */
-    omap_writel(0x48008400, 0x00000004);       /* CM_FCLKEN_WKUP */
-    omap_writel(0x48008410, 0x00000004);       /* CM_ICLKEN_WKUP */
-    omap_writel(0x48008440, 0x00000000);       /* CM_CLKSEL_WKUP */
-    omap_writel(0x48008500, 0x000000cf);       /* CM_CLKEN_PLL */
-    omap_writel(0x48008530, 0x0000000c);       /* CM_AUTOIDLE_PLL */
-    omap_writel(0x48008540,                    /* CM_CLKSEL1_PLL */
-                    (0x78 << 12) | (6 << 8));
-    omap_writel(0x48008544, 2);                        /* CM_CLKSEL2_PLL */
-
-    /* GPMC setup */
-    n800_gpmc_init(s);
-
-    /* Video setup */
-    n800_dss_init(&s->blizzard);
-
-    /* CPU setup */
-    s->mpu->cpu->env.GE = 0x5;
-
-    /* If the machine has a slided keyboard, open it */
-    if (s->kbd)
-        qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
-}
-
-#define OMAP_TAG_NOKIA_BT      0x4e01
-#define OMAP_TAG_WLAN_CX3110X  0x4e02
-#define OMAP_TAG_CBUS          0x4e03
-#define OMAP_TAG_EM_ASIC_BB5   0x4e04
-
-static struct omap_gpiosw_info_s {
-    const char *name;
-    int line;
-    int type;
-} n800_gpiosw_info[] = {
-    {
-        "bat_cover", N800_BAT_COVER_GPIO,
-        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
-    }, {
-        "cam_act", N800_CAM_ACT_GPIO,
-        OMAP_GPIOSW_TYPE_ACTIVITY,
-    }, {
-        "cam_turn", N800_CAM_TURN_GPIO,
-        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED,
-    }, {
-        "headphone", N8X0_HEADPHONE_GPIO,
-        OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
-    },
-    { NULL }
-}, n810_gpiosw_info[] = {
-    {
-        "gps_reset", N810_GPS_RESET_GPIO,
-        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
-    }, {
-        "gps_wakeup", N810_GPS_WAKEUP_GPIO,
-        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
-    }, {
-        "headphone", N8X0_HEADPHONE_GPIO,
-        OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
-    }, {
-        "kb_lock", N810_KB_LOCK_GPIO,
-        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
-    }, {
-        "sleepx_led", N810_SLEEPX_LED_GPIO,
-        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED | OMAP_GPIOSW_OUTPUT,
-    }, {
-        "slide", N810_SLIDE_GPIO,
-        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
-    },
-    { NULL }
-};
-
-static struct omap_partition_info_s {
-    uint32_t offset;
-    uint32_t size;
-    int mask;
-    const char *name;
-} n800_part_info[] = {
-    { 0x00000000, 0x00020000, 0x3, "bootloader" },
-    { 0x00020000, 0x00060000, 0x0, "config" },
-    { 0x00080000, 0x00200000, 0x0, "kernel" },
-    { 0x00280000, 0x00200000, 0x3, "initfs" },
-    { 0x00480000, 0x0fb80000, 0x3, "rootfs" },
-
-    { 0, 0, 0, NULL }
-}, n810_part_info[] = {
-    { 0x00000000, 0x00020000, 0x3, "bootloader" },
-    { 0x00020000, 0x00060000, 0x0, "config" },
-    { 0x00080000, 0x00220000, 0x0, "kernel" },
-    { 0x002a0000, 0x00400000, 0x0, "initfs" },
-    { 0x006a0000, 0x0f960000, 0x0, "rootfs" },
-
-    { 0, 0, 0, NULL }
-};
-
-static bdaddr_t n8x0_bd_addr = {{ N8X0_BD_ADDR }};
-
-static int n8x0_atag_setup(void *p, int model)
-{
-    uint8_t *b;
-    uint16_t *w;
-    uint32_t *l;
-    struct omap_gpiosw_info_s *gpiosw;
-    struct omap_partition_info_s *partition;
-    const char *tag;
-
-    w = p;
-
-    stw_raw(w ++, OMAP_TAG_UART);              /* u16 tag */
-    stw_raw(w ++, 4);                          /* u16 len */
-    stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
-    w ++;
-
-#if 0
-    stw_raw(w ++, OMAP_TAG_SERIAL_CONSOLE);    /* u16 tag */
-    stw_raw(w ++, 4);                          /* u16 len */
-    stw_raw(w ++, XLDR_LL_UART + 1);           /* u8 console_uart */
-    stw_raw(w ++, 115200);                     /* u32 console_speed */
-#endif
-
-    stw_raw(w ++, OMAP_TAG_LCD);               /* u16 tag */
-    stw_raw(w ++, 36);                         /* u16 len */
-    strcpy((void *) w, "QEMU LCD panel");      /* char panel_name[16] */
-    w += 8;
-    strcpy((void *) w, "blizzard");            /* char ctrl_name[16] */
-    w += 8;
-    stw_raw(w ++, N810_BLIZZARD_RESET_GPIO);   /* TODO: n800 s16 nreset_gpio */
-    stw_raw(w ++, 24);                         /* u8 data_lines */
-
-    stw_raw(w ++, OMAP_TAG_CBUS);              /* u16 tag */
-    stw_raw(w ++, 8);                          /* u16 len */
-    stw_raw(w ++, N8X0_CBUS_CLK_GPIO);         /* s16 clk_gpio */
-    stw_raw(w ++, N8X0_CBUS_DAT_GPIO);         /* s16 dat_gpio */
-    stw_raw(w ++, N8X0_CBUS_SEL_GPIO);         /* s16 sel_gpio */
-    w ++;
-
-    stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5);       /* u16 tag */
-    stw_raw(w ++, 4);                          /* u16 len */
-    stw_raw(w ++, N8X0_RETU_GPIO);             /* s16 retu_irq_gpio */
-    stw_raw(w ++, N8X0_TAHVO_GPIO);            /* s16 tahvo_irq_gpio */
-
-    gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
-    for (; gpiosw->name; gpiosw ++) {
-        stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);   /* u16 tag */
-        stw_raw(w ++, 20);                     /* u16 len */
-        strcpy((void *) w, gpiosw->name);      /* char name[12] */
-        w += 6;
-        stw_raw(w ++, gpiosw->line);           /* u16 gpio */
-        stw_raw(w ++, gpiosw->type);
-        stw_raw(w ++, 0);
-        stw_raw(w ++, 0);
-    }
-
-    stw_raw(w ++, OMAP_TAG_NOKIA_BT);          /* u16 tag */
-    stw_raw(w ++, 12);                         /* u16 len */
-    b = (void *) w;
-    stb_raw(b ++, 0x01);                       /* u8 chip_type (CSR) */
-    stb_raw(b ++, N8X0_BT_WKUP_GPIO);          /* u8 bt_wakeup_gpio */
-    stb_raw(b ++, N8X0_BT_HOST_WKUP_GPIO);     /* u8 host_wakeup_gpio */
-    stb_raw(b ++, N8X0_BT_RESET_GPIO);         /* u8 reset_gpio */
-    stb_raw(b ++, BT_UART + 1);                        /* u8 bt_uart */
-    memcpy(b, &n8x0_bd_addr, 6);               /* u8 bd_addr[6] */
-    b += 6;
-    stb_raw(b ++, 0x02);                       /* u8 bt_sysclk (38.4) */
-    w = (void *) b;
-
-    stw_raw(w ++, OMAP_TAG_WLAN_CX3110X);      /* u16 tag */
-    stw_raw(w ++, 8);                          /* u16 len */
-    stw_raw(w ++, 0x25);                       /* u8 chip_type */
-    stw_raw(w ++, N8X0_WLAN_PWR_GPIO);         /* s16 power_gpio */
-    stw_raw(w ++, N8X0_WLAN_IRQ_GPIO);         /* s16 irq_gpio */
-    stw_raw(w ++, -1);                         /* s16 spi_cs_gpio */
-
-    stw_raw(w ++, OMAP_TAG_MMC);               /* u16 tag */
-    stw_raw(w ++, 16);                         /* u16 len */
-    if (model == 810) {
-        stw_raw(w ++, 0x23f);                  /* unsigned flags */
-        stw_raw(w ++, -1);                     /* s16 power_pin */
-        stw_raw(w ++, -1);                     /* s16 switch_pin */
-        stw_raw(w ++, -1);                     /* s16 wp_pin */
-        stw_raw(w ++, 0x240);                  /* unsigned flags */
-        stw_raw(w ++, 0xc000);                 /* s16 power_pin */
-        stw_raw(w ++, 0x0248);                 /* s16 switch_pin */
-        stw_raw(w ++, 0xc000);                 /* s16 wp_pin */
-    } else {
-        stw_raw(w ++, 0xf);                    /* unsigned flags */
-        stw_raw(w ++, -1);                     /* s16 power_pin */
-        stw_raw(w ++, -1);                     /* s16 switch_pin */
-        stw_raw(w ++, -1);                     /* s16 wp_pin */
-        stw_raw(w ++, 0);                      /* unsigned flags */
-        stw_raw(w ++, 0);                      /* s16 power_pin */
-        stw_raw(w ++, 0);                      /* s16 switch_pin */
-        stw_raw(w ++, 0);                      /* s16 wp_pin */
-    }
-
-    stw_raw(w ++, OMAP_TAG_TEA5761);           /* u16 tag */
-    stw_raw(w ++, 4);                          /* u16 len */
-    stw_raw(w ++, N8X0_TEA5761_CS_GPIO);       /* u16 enable_gpio */
-    w ++;
-
-    partition = (model == 810) ? n810_part_info : n800_part_info;
-    for (; partition->name; partition ++) {
-        stw_raw(w ++, OMAP_TAG_PARTITION);     /* u16 tag */
-        stw_raw(w ++, 28);                     /* u16 len */
-        strcpy((void *) w, partition->name);   /* char name[16] */
-        l = (void *) (w + 8);
-        stl_raw(l ++, partition->size);                /* unsigned int size */
-        stl_raw(l ++, partition->offset);      /* unsigned int offset */
-        stl_raw(l ++, partition->mask);                /* unsigned int mask_flags */
-        w = (void *) l;
-    }
-
-    stw_raw(w ++, OMAP_TAG_BOOT_REASON);       /* u16 tag */
-    stw_raw(w ++, 12);                         /* u16 len */
-#if 0
-    strcpy((void *) w, "por");                 /* char reason_str[12] */
-    strcpy((void *) w, "charger");             /* char reason_str[12] */
-    strcpy((void *) w, "32wd_to");             /* char reason_str[12] */
-    strcpy((void *) w, "sw_rst");              /* char reason_str[12] */
-    strcpy((void *) w, "mbus");                        /* char reason_str[12] */
-    strcpy((void *) w, "unknown");             /* char reason_str[12] */
-    strcpy((void *) w, "swdg_to");             /* char reason_str[12] */
-    strcpy((void *) w, "sec_vio");             /* char reason_str[12] */
-    strcpy((void *) w, "pwr_key");             /* char reason_str[12] */
-    strcpy((void *) w, "rtc_alarm");           /* char reason_str[12] */
-#else
-    strcpy((void *) w, "pwr_key");             /* char reason_str[12] */
-#endif
-    w += 6;
-
-    tag = (model == 810) ? "RX-44" : "RX-34";
-    stw_raw(w ++, OMAP_TAG_VERSION_STR);       /* u16 tag */
-    stw_raw(w ++, 24);                         /* u16 len */
-    strcpy((void *) w, "product");             /* char component[12] */
-    w += 6;
-    strcpy((void *) w, tag);                   /* char version[12] */
-    w += 6;
-
-    stw_raw(w ++, OMAP_TAG_VERSION_STR);       /* u16 tag */
-    stw_raw(w ++, 24);                         /* u16 len */
-    strcpy((void *) w, "hw-build");            /* char component[12] */
-    w += 6;
-    strcpy((void *) w, "QEMU ");
-    pstrcat((void *) w, 12, qemu_get_version()); /* char version[12] */
-    w += 6;
-
-    tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
-    stw_raw(w ++, OMAP_TAG_VERSION_STR);       /* u16 tag */
-    stw_raw(w ++, 24);                         /* u16 len */
-    strcpy((void *) w, "nolo");                        /* char component[12] */
-    w += 6;
-    strcpy((void *) w, tag);                   /* char version[12] */
-    w += 6;
-
-    return (void *) w - p;
-}
-
-static int n800_atag_setup(const struct arm_boot_info *info, void *p)
-{
-    return n8x0_atag_setup(p, 800);
-}
-
-static int n810_atag_setup(const struct arm_boot_info *info, void *p)
-{
-    return n8x0_atag_setup(p, 810);
-}
-
-static void n8x0_init(QEMUMachineInitArgs *args,
-                      struct arm_boot_info *binfo, int model)
-{
-    MemoryRegion *sysmem = get_system_memory();
-    struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
-    int sdram_size = binfo->ram_size;
-    DisplayState *ds;
-
-    s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model);
-
-    /* Setup peripherals
-     *
-     * Believed external peripherals layout in the N810:
-     * (spi bus 1)
-     *   tsc2005
-     *   lcd_mipid
-     * (spi bus 2)
-     *   Conexant cx3110x (WLAN)
-     *   optional: pc2400m (WiMAX)
-     * (i2c bus 0)
-     *   TLV320AIC33 (audio codec)
-     *   TCM825x (camera by Toshiba)
-     *   lp5521 (clever LEDs)
-     *   tsl2563 (light sensor, hwmon, model 7, rev. 0)
-     *   lm8323 (keypad, manf 00, rev 04)
-     * (i2c bus 1)
-     *   tmp105 (temperature sensor, hwmon)
-     *   menelaus (pm)
-     * (somewhere on i2c - maybe N800-only)
-     *   tea5761 (FM tuner)
-     * (serial 0)
-     *   GPS
-     * (some serial port)
-     *   csr41814 (Bluetooth)
-     */
-    n8x0_gpio_setup(s);
-    n8x0_nand_setup(s);
-    n8x0_i2c_setup(s);
-    if (model == 800)
-        n800_tsc_kbd_setup(s);
-    else if (model == 810) {
-        n810_tsc_setup(s);
-        n810_kbd_setup(s);
-    }
-    n8x0_spi_setup(s);
-    n8x0_dss_setup(s);
-    n8x0_cbus_setup(s);
-    n8x0_uart_setup(s);
-    if (usb_enabled(false)) {
-        n8x0_usb_setup(s);
-    }
-
-    if (args->kernel_filename) {
-        /* Or at the linux loader.  */
-        binfo->kernel_filename = args->kernel_filename;
-        binfo->kernel_cmdline = args->kernel_cmdline;
-        binfo->initrd_filename = args->initrd_filename;
-        arm_load_kernel(s->mpu->cpu, binfo);
-
-        qemu_register_reset(n8x0_boot_init, s);
-    }
-
-    if (option_rom[0].name &&
-        (args->boot_device[0] == 'n' || !args->kernel_filename)) {
-        int rom_size;
-        uint8_t nolo_tags[0x10000];
-        /* No, wait, better start at the ROM.  */
-        s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
-
-        /* This is intended for loading the `secondary.bin' program from
-         * Nokia images (the NOLO bootloader).  The entry point seems
-         * to be at OMAP2_Q2_BASE + 0x400000.
-         *
-         * The `2nd.bin' files contain some kind of earlier boot code and
-         * for them the entry point needs to be set to OMAP2_SRAM_BASE.
-         *
-         * The code above is for loading the `zImage' file from Nokia
-         * images.  */
-        rom_size = load_image_targphys(option_rom[0].name,
-                                       OMAP2_Q2_BASE + 0x400000,
-                                       sdram_size - 0x400000);
-        printf("%i bytes of image loaded\n", rom_size);
-
-        n800_setup_nolo_tags(nolo_tags);
-        cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
-    }
-    /* FIXME: We shouldn't really be doing this here.  The LCD controller
-       will set the size once configured, so this just sets an initial
-       size until the guest activates the display.  */
-    ds = get_displaystate();
-    ds->surface = qemu_resize_displaysurface(ds, 800, 480);
-    dpy_gfx_resize(ds);
-}
-
-static struct arm_boot_info n800_binfo = {
-    .loader_start = OMAP2_Q2_BASE,
-    /* Actually two chips of 0x4000000 bytes each */
-    .ram_size = 0x08000000,
-    .board_id = 0x4f7,
-    .atag_board = n800_atag_setup,
-};
-
-static struct arm_boot_info n810_binfo = {
-    .loader_start = OMAP2_Q2_BASE,
-    /* Actually two chips of 0x4000000 bytes each */
-    .ram_size = 0x08000000,
-    /* 0x60c and 0x6bf (WiMAX Edition) have been assigned but are not
-     * used by some older versions of the bootloader and 5555 is used
-     * instead (including versions that shipped with many devices).  */
-    .board_id = 0x60c,
-    .atag_board = n810_atag_setup,
-};
-
-static void n800_init(QEMUMachineInitArgs *args)
-{
-    return n8x0_init(args, &n800_binfo, 800);
-}
-
-static void n810_init(QEMUMachineInitArgs *args)
-{
-    return n8x0_init(args, &n810_binfo, 810);
-}
-
-static QEMUMachine n800_machine = {
-    .name = "n800",
-    .desc = "Nokia N800 tablet aka. RX-34 (OMAP2420)",
-    .init = n800_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine n810_machine = {
-    .name = "n810",
-    .desc = "Nokia N810 tablet aka. RX-44 (OMAP2420)",
-    .init = n810_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void nseries_machine_init(void)
-{
-    qemu_register_machine(&n800_machine);
-    qemu_register_machine(&n810_machine);
-}
-
-machine_init(nseries_machine_init);
diff --git a/hw/omap1.c b/hw/omap1.c
deleted file mode 100644 (file)
index 623b101..0000000
+++ /dev/null
@@ -1,4056 +0,0 @@
-/*
- * TI OMAP processors emulation.
- *
- * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
- *
- * 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 or
- * (at your option) version 3 of the License.
- *
- * 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 "hw.h"
-#include "arm-misc.h"
-#include "omap.h"
-#include "sysemu/sysemu.h"
-#include "soc_dma.h"
-#include "sysemu/blockdev.h"
-#include "qemu/range.h"
-#include "sysbus.h"
-
-/* Should signal the TCMI/GPMC */
-uint32_t omap_badwidth_read8(void *opaque, hwaddr addr)
-{
-    uint8_t ret;
-
-    OMAP_8B_REG(addr);
-    cpu_physical_memory_read(addr, (void *) &ret, 1);
-    return ret;
-}
-
-void omap_badwidth_write8(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    uint8_t val8 = value;
-
-    OMAP_8B_REG(addr);
-    cpu_physical_memory_write(addr, (void *) &val8, 1);
-}
-
-uint32_t omap_badwidth_read16(void *opaque, hwaddr addr)
-{
-    uint16_t ret;
-
-    OMAP_16B_REG(addr);
-    cpu_physical_memory_read(addr, (void *) &ret, 2);
-    return ret;
-}
-
-void omap_badwidth_write16(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    uint16_t val16 = value;
-
-    OMAP_16B_REG(addr);
-    cpu_physical_memory_write(addr, (void *) &val16, 2);
-}
-
-uint32_t omap_badwidth_read32(void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-    OMAP_32B_REG(addr);
-    cpu_physical_memory_read(addr, (void *) &ret, 4);
-    return ret;
-}
-
-void omap_badwidth_write32(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    OMAP_32B_REG(addr);
-    cpu_physical_memory_write(addr, (void *) &value, 4);
-}
-
-/* MPU OS timers */
-struct omap_mpu_timer_s {
-    MemoryRegion iomem;
-    qemu_irq irq;
-    omap_clk clk;
-    uint32_t val;
-    int64_t time;
-    QEMUTimer *timer;
-    QEMUBH *tick;
-    int64_t rate;
-    int it_ena;
-
-    int enable;
-    int ptv;
-    int ar;
-    int st;
-    uint32_t reset_val;
-};
-
-static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer)
-{
-    uint64_t distance = qemu_get_clock_ns(vm_clock) - timer->time;
-
-    if (timer->st && timer->enable && timer->rate)
-        return timer->val - muldiv64(distance >> (timer->ptv + 1),
-                                     timer->rate, get_ticks_per_sec());
-    else
-        return timer->val;
-}
-
-static inline void omap_timer_sync(struct omap_mpu_timer_s *timer)
-{
-    timer->val = omap_timer_read(timer);
-    timer->time = qemu_get_clock_ns(vm_clock);
-}
-
-static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
-{
-    int64_t expires;
-
-    if (timer->enable && timer->st && timer->rate) {
-        timer->val = timer->reset_val; /* Should skip this on clk enable */
-        expires = muldiv64((uint64_t) timer->val << (timer->ptv + 1),
-                           get_ticks_per_sec(), timer->rate);
-
-        /* If timer expiry would be sooner than in about 1 ms and
-         * auto-reload isn't set, then fire immediately.  This is a hack
-         * to make systems like PalmOS run in acceptable time.  PalmOS
-         * sets the interval to a very low value and polls the status bit
-         * in a busy loop when it wants to sleep just a couple of CPU
-         * ticks.  */
-        if (expires > (get_ticks_per_sec() >> 10) || timer->ar)
-            qemu_mod_timer(timer->timer, timer->time + expires);
-        else
-            qemu_bh_schedule(timer->tick);
-    } else
-        qemu_del_timer(timer->timer);
-}
-
-static void omap_timer_fire(void *opaque)
-{
-    struct omap_mpu_timer_s *timer = opaque;
-
-    if (!timer->ar) {
-        timer->val = 0;
-        timer->st = 0;
-    }
-
-    if (timer->it_ena)
-        /* Edge-triggered irq */
-        qemu_irq_pulse(timer->irq);
-}
-
-static void omap_timer_tick(void *opaque)
-{
-    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
-
-    omap_timer_sync(timer);
-    omap_timer_fire(timer);
-    omap_timer_update(timer);
-}
-
-static void omap_timer_clk_update(void *opaque, int line, int on)
-{
-    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
-
-    omap_timer_sync(timer);
-    timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
-    omap_timer_update(timer);
-}
-
-static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
-{
-    omap_clk_adduser(timer->clk,
-                    qemu_allocate_irqs(omap_timer_clk_update, timer, 1)[0]);
-    timer->rate = omap_clk_getrate(timer->clk);
-}
-
-static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr,
-                                    unsigned size)
-{
-    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00: /* CNTL_TIMER */
-        return (s->enable << 5) | (s->ptv << 2) | (s->ar << 1) | s->st;
-
-    case 0x04: /* LOAD_TIM */
-        break;
-
-    case 0x08: /* READ_TIM */
-        return omap_timer_read(s);
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mpu_timer_write(void *opaque, hwaddr addr,
-                                 uint64_t value, unsigned size)
-{
-    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00: /* CNTL_TIMER */
-        omap_timer_sync(s);
-        s->enable = (value >> 5) & 1;
-        s->ptv = (value >> 2) & 7;
-        s->ar = (value >> 1) & 1;
-        s->st = value & 1;
-        omap_timer_update(s);
-        return;
-
-    case 0x04: /* LOAD_TIM */
-        s->reset_val = value;
-        return;
-
-    case 0x08: /* READ_TIM */
-        OMAP_RO_REG(addr);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_mpu_timer_ops = {
-    .read = omap_mpu_timer_read,
-    .write = omap_mpu_timer_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s)
-{
-    qemu_del_timer(s->timer);
-    s->enable = 0;
-    s->reset_val = 31337;
-    s->val = 0;
-    s->ptv = 0;
-    s->ar = 0;
-    s->st = 0;
-    s->it_ena = 1;
-}
-
-static struct omap_mpu_timer_s *omap_mpu_timer_init(MemoryRegion *system_memory,
-                hwaddr base,
-                qemu_irq irq, omap_clk clk)
-{
-    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *)
-            g_malloc0(sizeof(struct omap_mpu_timer_s));
-
-    s->irq = irq;
-    s->clk = clk;
-    s->timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, s);
-    s->tick = qemu_bh_new(omap_timer_fire, s);
-    omap_mpu_timer_reset(s);
-    omap_timer_clk_setup(s);
-
-    memory_region_init_io(&s->iomem, &omap_mpu_timer_ops, s,
-                          "omap-mpu-timer", 0x100);
-
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    return s;
-}
-
-/* Watchdog timer */
-struct omap_watchdog_timer_s {
-    struct omap_mpu_timer_s timer;
-    MemoryRegion iomem;
-    uint8_t last_wr;
-    int mode;
-    int free;
-    int reset;
-};
-
-static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr,
-                                   unsigned size)
-{
-    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00: /* CNTL_TIMER */
-        return (s->timer.ptv << 9) | (s->timer.ar << 8) |
-                (s->timer.st << 7) | (s->free << 1);
-
-    case 0x04: /* READ_TIMER */
-        return omap_timer_read(&s->timer);
-
-    case 0x08: /* TIMER_MODE */
-        return s->mode << 15;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_wd_timer_write(void *opaque, hwaddr addr,
-                                uint64_t value, unsigned size)
-{
-    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00: /* CNTL_TIMER */
-        omap_timer_sync(&s->timer);
-        s->timer.ptv = (value >> 9) & 7;
-        s->timer.ar = (value >> 8) & 1;
-        s->timer.st = (value >> 7) & 1;
-        s->free = (value >> 1) & 1;
-        omap_timer_update(&s->timer);
-        break;
-
-    case 0x04: /* LOAD_TIMER */
-        s->timer.reset_val = value & 0xffff;
-        break;
-
-    case 0x08: /* TIMER_MODE */
-        if (!s->mode && ((value >> 15) & 1))
-            omap_clk_get(s->timer.clk);
-        s->mode |= (value >> 15) & 1;
-        if (s->last_wr == 0xf5) {
-            if ((value & 0xff) == 0xa0) {
-                if (s->mode) {
-                    s->mode = 0;
-                    omap_clk_put(s->timer.clk);
-                }
-            } else {
-                /* XXX: on T|E hardware somehow this has no effect,
-                 * on Zire 71 it works as specified.  */
-                s->reset = 1;
-                qemu_system_reset_request();
-            }
-        }
-        s->last_wr = value & 0xff;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_wd_timer_ops = {
-    .read = omap_wd_timer_read,
-    .write = omap_wd_timer_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s)
-{
-    qemu_del_timer(s->timer.timer);
-    if (!s->mode)
-        omap_clk_get(s->timer.clk);
-    s->mode = 1;
-    s->free = 1;
-    s->reset = 0;
-    s->timer.enable = 1;
-    s->timer.it_ena = 1;
-    s->timer.reset_val = 0xffff;
-    s->timer.val = 0;
-    s->timer.st = 0;
-    s->timer.ptv = 0;
-    s->timer.ar = 0;
-    omap_timer_update(&s->timer);
-}
-
-static struct omap_watchdog_timer_s *omap_wd_timer_init(MemoryRegion *memory,
-                hwaddr base,
-                qemu_irq irq, omap_clk clk)
-{
-    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *)
-            g_malloc0(sizeof(struct omap_watchdog_timer_s));
-
-    s->timer.irq = irq;
-    s->timer.clk = clk;
-    s->timer.timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, &s->timer);
-    omap_wd_timer_reset(s);
-    omap_timer_clk_setup(&s->timer);
-
-    memory_region_init_io(&s->iomem, &omap_wd_timer_ops, s,
-                          "omap-wd-timer", 0x100);
-    memory_region_add_subregion(memory, base, &s->iomem);
-
-    return s;
-}
-
-/* 32-kHz timer */
-struct omap_32khz_timer_s {
-    struct omap_mpu_timer_s timer;
-    MemoryRegion iomem;
-};
-
-static uint64_t omap_os_timer_read(void *opaque, hwaddr addr,
-                                   unsigned size)
-{
-    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00: /* TVR */
-        return s->timer.reset_val;
-
-    case 0x04: /* TCR */
-        return omap_timer_read(&s->timer);
-
-    case 0x08: /* CR */
-        return (s->timer.ar << 3) | (s->timer.it_ena << 2) | s->timer.st;
-
-    default:
-        break;
-    }
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_os_timer_write(void *opaque, hwaddr addr,
-                                uint64_t value, unsigned size)
-{
-    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00: /* TVR */
-        s->timer.reset_val = value & 0x00ffffff;
-        break;
-
-    case 0x04: /* TCR */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x08: /* CR */
-        s->timer.ar = (value >> 3) & 1;
-        s->timer.it_ena = (value >> 2) & 1;
-        if (s->timer.st != (value & 1) || (value & 2)) {
-            omap_timer_sync(&s->timer);
-            s->timer.enable = value & 1;
-            s->timer.st = value & 1;
-            omap_timer_update(&s->timer);
-        }
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_os_timer_ops = {
-    .read = omap_os_timer_read,
-    .write = omap_os_timer_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_os_timer_reset(struct omap_32khz_timer_s *s)
-{
-    qemu_del_timer(s->timer.timer);
-    s->timer.enable = 0;
-    s->timer.it_ena = 0;
-    s->timer.reset_val = 0x00ffffff;
-    s->timer.val = 0;
-    s->timer.st = 0;
-    s->timer.ptv = 0;
-    s->timer.ar = 1;
-}
-
-static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory,
-                hwaddr base,
-                qemu_irq irq, omap_clk clk)
-{
-    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *)
-            g_malloc0(sizeof(struct omap_32khz_timer_s));
-
-    s->timer.irq = irq;
-    s->timer.clk = clk;
-    s->timer.timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, &s->timer);
-    omap_os_timer_reset(s);
-    omap_timer_clk_setup(&s->timer);
-
-    memory_region_init_io(&s->iomem, &omap_os_timer_ops, s,
-                          "omap-os-timer", 0x800);
-    memory_region_add_subregion(memory, base, &s->iomem);
-
-    return s;
-}
-
-/* Ultra Low-Power Device Module */
-static uint64_t omap_ulpd_pm_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    uint16_t ret;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x14: /* IT_STATUS */
-        ret = s->ulpd_pm_regs[addr >> 2];
-        s->ulpd_pm_regs[addr >> 2] = 0;
-        qemu_irq_lower(qdev_get_gpio_in(s->ih[1], OMAP_INT_GAUGE_32K));
-        return ret;
-
-    case 0x18: /* Reserved */
-    case 0x1c: /* Reserved */
-    case 0x20: /* Reserved */
-    case 0x28: /* Reserved */
-    case 0x2c: /* Reserved */
-        OMAP_BAD_REG(addr);
-        /* fall through */
-    case 0x00: /* COUNTER_32_LSB */
-    case 0x04: /* COUNTER_32_MSB */
-    case 0x08: /* COUNTER_HIGH_FREQ_LSB */
-    case 0x0c: /* COUNTER_HIGH_FREQ_MSB */
-    case 0x10: /* GAUGING_CTRL */
-    case 0x24: /* SETUP_ANALOG_CELL3_ULPD1 */
-    case 0x30: /* CLOCK_CTRL */
-    case 0x34: /* SOFT_REQ */
-    case 0x38: /* COUNTER_32_FIQ */
-    case 0x3c: /* DPLL_CTRL */
-    case 0x40: /* STATUS_REQ */
-        /* XXX: check clk::usecount state for every clock */
-    case 0x48: /* LOCL_TIME */
-    case 0x4c: /* APLL_CTRL */
-    case 0x50: /* POWER_CTRL */
-        return s->ulpd_pm_regs[addr >> 2];
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static inline void omap_ulpd_clk_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    if (diff & (1 << 4))                               /* USB_MCLK_EN */
-        omap_clk_onoff(omap_findclk(s, "usb_clk0"), (value >> 4) & 1);
-    if (diff & (1 << 5))                               /* DIS_USB_PVCI_CLK */
-        omap_clk_onoff(omap_findclk(s, "usb_w2fc_ck"), (~value >> 5) & 1);
-}
-
-static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    if (diff & (1 << 0))                               /* SOFT_DPLL_REQ */
-        omap_clk_canidle(omap_findclk(s, "dpll4"), (~value >> 0) & 1);
-    if (diff & (1 << 1))                               /* SOFT_COM_REQ */
-        omap_clk_canidle(omap_findclk(s, "com_mclk_out"), (~value >> 1) & 1);
-    if (diff & (1 << 2))                               /* SOFT_SDW_REQ */
-        omap_clk_canidle(omap_findclk(s, "bt_mclk_out"), (~value >> 2) & 1);
-    if (diff & (1 << 3))                               /* SOFT_USB_REQ */
-        omap_clk_canidle(omap_findclk(s, "usb_clk0"), (~value >> 3) & 1);
-}
-
-static void omap_ulpd_pm_write(void *opaque, hwaddr addr,
-                               uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int64_t now, ticks;
-    int div, mult;
-    static const int bypass_div[4] = { 1, 2, 4, 4 };
-    uint16_t diff;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00: /* COUNTER_32_LSB */
-    case 0x04: /* COUNTER_32_MSB */
-    case 0x08: /* COUNTER_HIGH_FREQ_LSB */
-    case 0x0c: /* COUNTER_HIGH_FREQ_MSB */
-    case 0x14: /* IT_STATUS */
-    case 0x40: /* STATUS_REQ */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x10: /* GAUGING_CTRL */
-        /* Bits 0 and 1 seem to be confused in the OMAP 310 TRM */
-        if ((s->ulpd_pm_regs[addr >> 2] ^ value) & 1) {
-            now = qemu_get_clock_ns(vm_clock);
-
-            if (value & 1)
-                s->ulpd_gauge_start = now;
-            else {
-                now -= s->ulpd_gauge_start;
-
-                /* 32-kHz ticks */
-                ticks = muldiv64(now, 32768, get_ticks_per_sec());
-                s->ulpd_pm_regs[0x00 >> 2] = (ticks >>  0) & 0xffff;
-                s->ulpd_pm_regs[0x04 >> 2] = (ticks >> 16) & 0xffff;
-                if (ticks >> 32)       /* OVERFLOW_32K */
-                    s->ulpd_pm_regs[0x14 >> 2] |= 1 << 2;
-
-                /* High frequency ticks */
-                ticks = muldiv64(now, 12000000, get_ticks_per_sec());
-                s->ulpd_pm_regs[0x08 >> 2] = (ticks >>  0) & 0xffff;
-                s->ulpd_pm_regs[0x0c >> 2] = (ticks >> 16) & 0xffff;
-                if (ticks >> 32)       /* OVERFLOW_HI_FREQ */
-                    s->ulpd_pm_regs[0x14 >> 2] |= 1 << 1;
-
-                s->ulpd_pm_regs[0x14 >> 2] |= 1 << 0;  /* IT_GAUGING */
-                qemu_irq_raise(qdev_get_gpio_in(s->ih[1], OMAP_INT_GAUGE_32K));
-            }
-        }
-        s->ulpd_pm_regs[addr >> 2] = value;
-        break;
-
-    case 0x18: /* Reserved */
-    case 0x1c: /* Reserved */
-    case 0x20: /* Reserved */
-    case 0x28: /* Reserved */
-    case 0x2c: /* Reserved */
-        OMAP_BAD_REG(addr);
-        /* fall through */
-    case 0x24: /* SETUP_ANALOG_CELL3_ULPD1 */
-    case 0x38: /* COUNTER_32_FIQ */
-    case 0x48: /* LOCL_TIME */
-    case 0x50: /* POWER_CTRL */
-        s->ulpd_pm_regs[addr >> 2] = value;
-        break;
-
-    case 0x30: /* CLOCK_CTRL */
-        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
-        s->ulpd_pm_regs[addr >> 2] = value & 0x3f;
-        omap_ulpd_clk_update(s, diff, value);
-        break;
-
-    case 0x34: /* SOFT_REQ */
-        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
-        s->ulpd_pm_regs[addr >> 2] = value & 0x1f;
-        omap_ulpd_req_update(s, diff, value);
-        break;
-
-    case 0x3c: /* DPLL_CTRL */
-        /* XXX: OMAP310 TRM claims bit 3 is PLL_ENABLE, and bit 4 is
-         * omitted altogether, probably a typo.  */
-        /* This register has identical semantics with DPLL(1:3) control
-         * registers, see omap_dpll_write() */
-        diff = s->ulpd_pm_regs[addr >> 2] & value;
-        s->ulpd_pm_regs[addr >> 2] = value & 0x2fff;
-        if (diff & (0x3ff << 2)) {
-            if (value & (1 << 4)) {                    /* PLL_ENABLE */
-                div = ((value >> 5) & 3) + 1;          /* PLL_DIV */
-                mult = MIN((value >> 7) & 0x1f, 1);    /* PLL_MULT */
-            } else {
-                div = bypass_div[((value >> 2) & 3)];  /* BYPASS_DIV */
-                mult = 1;
-            }
-            omap_clk_setrate(omap_findclk(s, "dpll4"), div, mult);
-        }
-
-        /* Enter the desired mode.  */
-        s->ulpd_pm_regs[addr >> 2] =
-                (s->ulpd_pm_regs[addr >> 2] & 0xfffe) |
-                ((s->ulpd_pm_regs[addr >> 2] >> 4) & 1);
-
-        /* Act as if the lock is restored.  */
-        s->ulpd_pm_regs[addr >> 2] |= 2;
-        break;
-
-    case 0x4c: /* APLL_CTRL */
-        diff = s->ulpd_pm_regs[addr >> 2] & value;
-        s->ulpd_pm_regs[addr >> 2] = value & 0xf;
-        if (diff & (1 << 0))                           /* APLL_NDPLL_SWITCH */
-            omap_clk_reparent(omap_findclk(s, "ck_48m"), omap_findclk(s,
-                                    (value & (1 << 0)) ? "apll" : "dpll4"));
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_ulpd_pm_ops = {
-    .read = omap_ulpd_pm_read,
-    .write = omap_ulpd_pm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_ulpd_pm_reset(struct omap_mpu_state_s *mpu)
-{
-    mpu->ulpd_pm_regs[0x00 >> 2] = 0x0001;
-    mpu->ulpd_pm_regs[0x04 >> 2] = 0x0000;
-    mpu->ulpd_pm_regs[0x08 >> 2] = 0x0001;
-    mpu->ulpd_pm_regs[0x0c >> 2] = 0x0000;
-    mpu->ulpd_pm_regs[0x10 >> 2] = 0x0000;
-    mpu->ulpd_pm_regs[0x18 >> 2] = 0x01;
-    mpu->ulpd_pm_regs[0x1c >> 2] = 0x01;
-    mpu->ulpd_pm_regs[0x20 >> 2] = 0x01;
-    mpu->ulpd_pm_regs[0x24 >> 2] = 0x03ff;
-    mpu->ulpd_pm_regs[0x28 >> 2] = 0x01;
-    mpu->ulpd_pm_regs[0x2c >> 2] = 0x01;
-    omap_ulpd_clk_update(mpu, mpu->ulpd_pm_regs[0x30 >> 2], 0x0000);
-    mpu->ulpd_pm_regs[0x30 >> 2] = 0x0000;
-    omap_ulpd_req_update(mpu, mpu->ulpd_pm_regs[0x34 >> 2], 0x0000);
-    mpu->ulpd_pm_regs[0x34 >> 2] = 0x0000;
-    mpu->ulpd_pm_regs[0x38 >> 2] = 0x0001;
-    mpu->ulpd_pm_regs[0x3c >> 2] = 0x2211;
-    mpu->ulpd_pm_regs[0x40 >> 2] = 0x0000; /* FIXME: dump a real STATUS_REQ */
-    mpu->ulpd_pm_regs[0x48 >> 2] = 0x960;
-    mpu->ulpd_pm_regs[0x4c >> 2] = 0x08;
-    mpu->ulpd_pm_regs[0x50 >> 2] = 0x08;
-    omap_clk_setrate(omap_findclk(mpu, "dpll4"), 1, 4);
-    omap_clk_reparent(omap_findclk(mpu, "ck_48m"), omap_findclk(mpu, "dpll4"));
-}
-
-static void omap_ulpd_pm_init(MemoryRegion *system_memory,
-                hwaddr base,
-                struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->ulpd_pm_iomem, &omap_ulpd_pm_ops, mpu,
-                          "omap-ulpd-pm", 0x800);
-    memory_region_add_subregion(system_memory, base, &mpu->ulpd_pm_iomem);
-    omap_ulpd_pm_reset(mpu);
-}
-
-/* OMAP Pin Configuration */
-static uint64_t omap_pin_cfg_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00: /* FUNC_MUX_CTRL_0 */
-    case 0x04: /* FUNC_MUX_CTRL_1 */
-    case 0x08: /* FUNC_MUX_CTRL_2 */
-        return s->func_mux_ctrl[addr >> 2];
-
-    case 0x0c: /* COMP_MODE_CTRL_0 */
-        return s->comp_mode_ctrl[0];
-
-    case 0x10: /* FUNC_MUX_CTRL_3 */
-    case 0x14: /* FUNC_MUX_CTRL_4 */
-    case 0x18: /* FUNC_MUX_CTRL_5 */
-    case 0x1c: /* FUNC_MUX_CTRL_6 */
-    case 0x20: /* FUNC_MUX_CTRL_7 */
-    case 0x24: /* FUNC_MUX_CTRL_8 */
-    case 0x28: /* FUNC_MUX_CTRL_9 */
-    case 0x2c: /* FUNC_MUX_CTRL_A */
-    case 0x30: /* FUNC_MUX_CTRL_B */
-    case 0x34: /* FUNC_MUX_CTRL_C */
-    case 0x38: /* FUNC_MUX_CTRL_D */
-        return s->func_mux_ctrl[(addr >> 2) - 1];
-
-    case 0x40: /* PULL_DWN_CTRL_0 */
-    case 0x44: /* PULL_DWN_CTRL_1 */
-    case 0x48: /* PULL_DWN_CTRL_2 */
-    case 0x4c: /* PULL_DWN_CTRL_3 */
-        return s->pull_dwn_ctrl[(addr & 0xf) >> 2];
-
-    case 0x50: /* GATE_INH_CTRL_0 */
-        return s->gate_inh_ctrl[0];
-
-    case 0x60: /* VOLTAGE_CTRL_0 */
-        return s->voltage_ctrl[0];
-
-    case 0x70: /* TEST_DBG_CTRL_0 */
-        return s->test_dbg_ctrl[0];
-
-    case 0x80: /* MOD_CONF_CTRL_0 */
-        return s->mod_conf_ctrl[0];
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static inline void omap_pin_funcmux0_update(struct omap_mpu_state_s *s,
-                uint32_t diff, uint32_t value)
-{
-    if (s->compat1509) {
-        if (diff & (1 << 9))                   /* BLUETOOTH */
-            omap_clk_onoff(omap_findclk(s, "bt_mclk_out"),
-                            (~value >> 9) & 1);
-        if (diff & (1 << 7))                   /* USB.CLKO */
-            omap_clk_onoff(omap_findclk(s, "usb.clko"),
-                            (value >> 7) & 1);
-    }
-}
-
-static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s,
-                uint32_t diff, uint32_t value)
-{
-    if (s->compat1509) {
-        if (diff & (1 << 31))                  /* MCBSP3_CLK_HIZ_DI */
-            omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"),
-                            (value >> 31) & 1);
-        if (diff & (1 << 1))                   /* CLK32K */
-            omap_clk_onoff(omap_findclk(s, "clk32k_out"),
-                            (~value >> 1) & 1);
-    }
-}
-
-static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
-                uint32_t diff, uint32_t value)
-{
-    if (diff & (1 << 31))                      /* CONF_MOD_UART3_CLK_MODE_R */
-         omap_clk_reparent(omap_findclk(s, "uart3_ck"),
-                         omap_findclk(s, ((value >> 31) & 1) ?
-                                 "ck_48m" : "armper_ck"));
-    if (diff & (1 << 30))                      /* CONF_MOD_UART2_CLK_MODE_R */
-         omap_clk_reparent(omap_findclk(s, "uart2_ck"),
-                         omap_findclk(s, ((value >> 30) & 1) ?
-                                 "ck_48m" : "armper_ck"));
-    if (diff & (1 << 29))                      /* CONF_MOD_UART1_CLK_MODE_R */
-         omap_clk_reparent(omap_findclk(s, "uart1_ck"),
-                         omap_findclk(s, ((value >> 29) & 1) ?
-                                 "ck_48m" : "armper_ck"));
-    if (diff & (1 << 23))                      /* CONF_MOD_MMC_SD_CLK_REQ_R */
-         omap_clk_reparent(omap_findclk(s, "mmc_ck"),
-                         omap_findclk(s, ((value >> 23) & 1) ?
-                                 "ck_48m" : "armper_ck"));
-    if (diff & (1 << 12))                      /* CONF_MOD_COM_MCLK_12_48_S */
-         omap_clk_reparent(omap_findclk(s, "com_mclk_out"),
-                         omap_findclk(s, ((value >> 12) & 1) ?
-                                 "ck_48m" : "armper_ck"));
-    if (diff & (1 << 9))                       /* CONF_MOD_USB_HOST_HHC_UHO */
-         omap_clk_onoff(omap_findclk(s, "usb_hhc_ck"), (value >> 9) & 1);
-}
-
-static void omap_pin_cfg_write(void *opaque, hwaddr addr,
-                               uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    uint32_t diff;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00: /* FUNC_MUX_CTRL_0 */
-        diff = s->func_mux_ctrl[addr >> 2] ^ value;
-        s->func_mux_ctrl[addr >> 2] = value;
-        omap_pin_funcmux0_update(s, diff, value);
-        return;
-
-    case 0x04: /* FUNC_MUX_CTRL_1 */
-        diff = s->func_mux_ctrl[addr >> 2] ^ value;
-        s->func_mux_ctrl[addr >> 2] = value;
-        omap_pin_funcmux1_update(s, diff, value);
-        return;
-
-    case 0x08: /* FUNC_MUX_CTRL_2 */
-        s->func_mux_ctrl[addr >> 2] = value;
-        return;
-
-    case 0x0c: /* COMP_MODE_CTRL_0 */
-        s->comp_mode_ctrl[0] = value;
-        s->compat1509 = (value != 0x0000eaef);
-        omap_pin_funcmux0_update(s, ~0, s->func_mux_ctrl[0]);
-        omap_pin_funcmux1_update(s, ~0, s->func_mux_ctrl[1]);
-        return;
-
-    case 0x10: /* FUNC_MUX_CTRL_3 */
-    case 0x14: /* FUNC_MUX_CTRL_4 */
-    case 0x18: /* FUNC_MUX_CTRL_5 */
-    case 0x1c: /* FUNC_MUX_CTRL_6 */
-    case 0x20: /* FUNC_MUX_CTRL_7 */
-    case 0x24: /* FUNC_MUX_CTRL_8 */
-    case 0x28: /* FUNC_MUX_CTRL_9 */
-    case 0x2c: /* FUNC_MUX_CTRL_A */
-    case 0x30: /* FUNC_MUX_CTRL_B */
-    case 0x34: /* FUNC_MUX_CTRL_C */
-    case 0x38: /* FUNC_MUX_CTRL_D */
-        s->func_mux_ctrl[(addr >> 2) - 1] = value;
-        return;
-
-    case 0x40: /* PULL_DWN_CTRL_0 */
-    case 0x44: /* PULL_DWN_CTRL_1 */
-    case 0x48: /* PULL_DWN_CTRL_2 */
-    case 0x4c: /* PULL_DWN_CTRL_3 */
-        s->pull_dwn_ctrl[(addr & 0xf) >> 2] = value;
-        return;
-
-    case 0x50: /* GATE_INH_CTRL_0 */
-        s->gate_inh_ctrl[0] = value;
-        return;
-
-    case 0x60: /* VOLTAGE_CTRL_0 */
-        s->voltage_ctrl[0] = value;
-        return;
-
-    case 0x70: /* TEST_DBG_CTRL_0 */
-        s->test_dbg_ctrl[0] = value;
-        return;
-
-    case 0x80: /* MOD_CONF_CTRL_0 */
-        diff = s->mod_conf_ctrl[0] ^ value;
-        s->mod_conf_ctrl[0] = value;
-        omap_pin_modconf1_update(s, diff, value);
-        return;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_pin_cfg_ops = {
-    .read = omap_pin_cfg_read,
-    .write = omap_pin_cfg_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_pin_cfg_reset(struct omap_mpu_state_s *mpu)
-{
-    /* Start in Compatibility Mode.  */
-    mpu->compat1509 = 1;
-    omap_pin_funcmux0_update(mpu, mpu->func_mux_ctrl[0], 0);
-    omap_pin_funcmux1_update(mpu, mpu->func_mux_ctrl[1], 0);
-    omap_pin_modconf1_update(mpu, mpu->mod_conf_ctrl[0], 0);
-    memset(mpu->func_mux_ctrl, 0, sizeof(mpu->func_mux_ctrl));
-    memset(mpu->comp_mode_ctrl, 0, sizeof(mpu->comp_mode_ctrl));
-    memset(mpu->pull_dwn_ctrl, 0, sizeof(mpu->pull_dwn_ctrl));
-    memset(mpu->gate_inh_ctrl, 0, sizeof(mpu->gate_inh_ctrl));
-    memset(mpu->voltage_ctrl, 0, sizeof(mpu->voltage_ctrl));
-    memset(mpu->test_dbg_ctrl, 0, sizeof(mpu->test_dbg_ctrl));
-    memset(mpu->mod_conf_ctrl, 0, sizeof(mpu->mod_conf_ctrl));
-}
-
-static void omap_pin_cfg_init(MemoryRegion *system_memory,
-                hwaddr base,
-                struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->pin_cfg_iomem, &omap_pin_cfg_ops, mpu,
-                          "omap-pin-cfg", 0x800);
-    memory_region_add_subregion(system_memory, base, &mpu->pin_cfg_iomem);
-    omap_pin_cfg_reset(mpu);
-}
-
-/* Device Identification, Die Identification */
-static uint64_t omap_id_read(void *opaque, hwaddr addr,
-                             unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0xfffe1800:   /* DIE_ID_LSB */
-        return 0xc9581f0e;
-    case 0xfffe1804:   /* DIE_ID_MSB */
-        return 0xa8858bfa;
-
-    case 0xfffe2000:   /* PRODUCT_ID_LSB */
-        return 0x00aaaafc;
-    case 0xfffe2004:   /* PRODUCT_ID_MSB */
-        return 0xcafeb574;
-
-    case 0xfffed400:   /* JTAG_ID_LSB */
-        switch (s->mpu_model) {
-        case omap310:
-            return 0x03310315;
-        case omap1510:
-            return 0x03310115;
-        default:
-            hw_error("%s: bad mpu model\n", __FUNCTION__);
-        }
-        break;
-
-    case 0xfffed404:   /* JTAG_ID_MSB */
-        switch (s->mpu_model) {
-        case omap310:
-            return 0xfb57402f;
-        case omap1510:
-            return 0xfb47002f;
-        default:
-            hw_error("%s: bad mpu model\n", __FUNCTION__);
-        }
-        break;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_id_write(void *opaque, hwaddr addr,
-                          uint64_t value, unsigned size)
-{
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    OMAP_BAD_REG(addr);
-}
-
-static const MemoryRegionOps omap_id_ops = {
-    .read = omap_id_read,
-    .write = omap_id_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_id_init(MemoryRegion *memory, struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->id_iomem, &omap_id_ops, mpu,
-                          "omap-id", 0x100000000ULL);
-    memory_region_init_alias(&mpu->id_iomem_e18, "omap-id-e18", &mpu->id_iomem,
-                             0xfffe1800, 0x800);
-    memory_region_add_subregion(memory, 0xfffe1800, &mpu->id_iomem_e18);
-    memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-ed4", &mpu->id_iomem,
-                             0xfffed400, 0x100);
-    memory_region_add_subregion(memory, 0xfffed400, &mpu->id_iomem_ed4);
-    if (!cpu_is_omap15xx(mpu)) {
-        memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-e20",
-                                 &mpu->id_iomem, 0xfffe2000, 0x800);
-        memory_region_add_subregion(memory, 0xfffe2000, &mpu->id_iomem_e20);
-    }
-}
-
-/* MPUI Control (Dummy) */
-static uint64_t omap_mpui_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00: /* CTRL */
-        return s->mpui_ctrl;
-    case 0x04: /* DEBUG_ADDR */
-        return 0x01ffffff;
-    case 0x08: /* DEBUG_DATA */
-        return 0xffffffff;
-    case 0x0c: /* DEBUG_FLAG */
-        return 0x00000800;
-    case 0x10: /* STATUS */
-        return 0x00000000;
-
-    /* Not in OMAP310 */
-    case 0x14: /* DSP_STATUS */
-    case 0x18: /* DSP_BOOT_CONFIG */
-        return 0x00000000;
-    case 0x1c: /* DSP_MPUI_CONFIG */
-        return 0x0000ffff;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mpui_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00: /* CTRL */
-        s->mpui_ctrl = value & 0x007fffff;
-        break;
-
-    case 0x04: /* DEBUG_ADDR */
-    case 0x08: /* DEBUG_DATA */
-    case 0x0c: /* DEBUG_FLAG */
-    case 0x10: /* STATUS */
-    /* Not in OMAP310 */
-    case 0x14: /* DSP_STATUS */
-        OMAP_RO_REG(addr);
-        break;
-    case 0x18: /* DSP_BOOT_CONFIG */
-    case 0x1c: /* DSP_MPUI_CONFIG */
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_mpui_ops = {
-    .read = omap_mpui_read,
-    .write = omap_mpui_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_mpui_reset(struct omap_mpu_state_s *s)
-{
-    s->mpui_ctrl = 0x0003ff1b;
-}
-
-static void omap_mpui_init(MemoryRegion *memory, hwaddr base,
-                struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->mpui_iomem, &omap_mpui_ops, mpu,
-                          "omap-mpui", 0x100);
-    memory_region_add_subregion(memory, base, &mpu->mpui_iomem);
-
-    omap_mpui_reset(mpu);
-}
-
-/* TIPB Bridges */
-struct omap_tipb_bridge_s {
-    qemu_irq abort;
-    MemoryRegion iomem;
-
-    int width_intr;
-    uint16_t control;
-    uint16_t alloc;
-    uint16_t buffer;
-    uint16_t enh_control;
-};
-
-static uint64_t omap_tipb_bridge_read(void *opaque, hwaddr addr,
-                                      unsigned size)
-{
-    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
-
-    if (size < 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00: /* TIPB_CNTL */
-        return s->control;
-    case 0x04: /* TIPB_BUS_ALLOC */
-        return s->alloc;
-    case 0x08: /* MPU_TIPB_CNTL */
-        return s->buffer;
-    case 0x0c: /* ENHANCED_TIPB_CNTL */
-        return s->enh_control;
-    case 0x10: /* ADDRESS_DBG */
-    case 0x14: /* DATA_DEBUG_LOW */
-    case 0x18: /* DATA_DEBUG_HIGH */
-        return 0xffff;
-    case 0x1c: /* DEBUG_CNTR_SIG */
-        return 0x00f8;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_tipb_bridge_write(void *opaque, hwaddr addr,
-                                   uint64_t value, unsigned size)
-{
-    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
-
-    if (size < 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00: /* TIPB_CNTL */
-        s->control = value & 0xffff;
-        break;
-
-    case 0x04: /* TIPB_BUS_ALLOC */
-        s->alloc = value & 0x003f;
-        break;
-
-    case 0x08: /* MPU_TIPB_CNTL */
-        s->buffer = value & 0x0003;
-        break;
-
-    case 0x0c: /* ENHANCED_TIPB_CNTL */
-        s->width_intr = !(value & 2);
-        s->enh_control = value & 0x000f;
-        break;
-
-    case 0x10: /* ADDRESS_DBG */
-    case 0x14: /* DATA_DEBUG_LOW */
-    case 0x18: /* DATA_DEBUG_HIGH */
-    case 0x1c: /* DEBUG_CNTR_SIG */
-        OMAP_RO_REG(addr);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_tipb_bridge_ops = {
-    .read = omap_tipb_bridge_read,
-    .write = omap_tipb_bridge_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_tipb_bridge_reset(struct omap_tipb_bridge_s *s)
-{
-    s->control = 0xffff;
-    s->alloc = 0x0009;
-    s->buffer = 0x0000;
-    s->enh_control = 0x000f;
-}
-
-static struct omap_tipb_bridge_s *omap_tipb_bridge_init(
-    MemoryRegion *memory, hwaddr base,
-    qemu_irq abort_irq, omap_clk clk)
-{
-    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *)
-            g_malloc0(sizeof(struct omap_tipb_bridge_s));
-
-    s->abort = abort_irq;
-    omap_tipb_bridge_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_tipb_bridge_ops, s,
-                          "omap-tipb-bridge", 0x100);
-    memory_region_add_subregion(memory, base, &s->iomem);
-
-    return s;
-}
-
-/* Dummy Traffic Controller's Memory Interface */
-static uint64_t omap_tcmi_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    uint32_t ret;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00: /* IMIF_PRIO */
-    case 0x04: /* EMIFS_PRIO */
-    case 0x08: /* EMIFF_PRIO */
-    case 0x0c: /* EMIFS_CONFIG */
-    case 0x10: /* EMIFS_CS0_CONFIG */
-    case 0x14: /* EMIFS_CS1_CONFIG */
-    case 0x18: /* EMIFS_CS2_CONFIG */
-    case 0x1c: /* EMIFS_CS3_CONFIG */
-    case 0x24: /* EMIFF_MRS */
-    case 0x28: /* TIMEOUT1 */
-    case 0x2c: /* TIMEOUT2 */
-    case 0x30: /* TIMEOUT3 */
-    case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
-    case 0x40: /* EMIFS_CFG_DYN_WAIT */
-        return s->tcmi_regs[addr >> 2];
-
-    case 0x20: /* EMIFF_SDRAM_CONFIG */
-        ret = s->tcmi_regs[addr >> 2];
-        s->tcmi_regs[addr >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */
-        /* XXX: We can try using the VGA_DIRTY flag for this */
-        return ret;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_tcmi_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00: /* IMIF_PRIO */
-    case 0x04: /* EMIFS_PRIO */
-    case 0x08: /* EMIFF_PRIO */
-    case 0x10: /* EMIFS_CS0_CONFIG */
-    case 0x14: /* EMIFS_CS1_CONFIG */
-    case 0x18: /* EMIFS_CS2_CONFIG */
-    case 0x1c: /* EMIFS_CS3_CONFIG */
-    case 0x20: /* EMIFF_SDRAM_CONFIG */
-    case 0x24: /* EMIFF_MRS */
-    case 0x28: /* TIMEOUT1 */
-    case 0x2c: /* TIMEOUT2 */
-    case 0x30: /* TIMEOUT3 */
-    case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
-    case 0x40: /* EMIFS_CFG_DYN_WAIT */
-        s->tcmi_regs[addr >> 2] = value;
-        break;
-    case 0x0c: /* EMIFS_CONFIG */
-        s->tcmi_regs[addr >> 2] = (value & 0xf) | (1 << 4);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_tcmi_ops = {
-    .read = omap_tcmi_read,
-    .write = omap_tcmi_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_tcmi_reset(struct omap_mpu_state_s *mpu)
-{
-    mpu->tcmi_regs[0x00 >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x04 >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x08 >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x0c >> 2] = 0x00000010;
-    mpu->tcmi_regs[0x10 >> 2] = 0x0010fffb;
-    mpu->tcmi_regs[0x14 >> 2] = 0x0010fffb;
-    mpu->tcmi_regs[0x18 >> 2] = 0x0010fffb;
-    mpu->tcmi_regs[0x1c >> 2] = 0x0010fffb;
-    mpu->tcmi_regs[0x20 >> 2] = 0x00618800;
-    mpu->tcmi_regs[0x24 >> 2] = 0x00000037;
-    mpu->tcmi_regs[0x28 >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x2c >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x30 >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x3c >> 2] = 0x00000003;
-    mpu->tcmi_regs[0x40 >> 2] = 0x00000000;
-}
-
-static void omap_tcmi_init(MemoryRegion *memory, hwaddr base,
-                struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->tcmi_iomem, &omap_tcmi_ops, mpu,
-                          "omap-tcmi", 0x100);
-    memory_region_add_subregion(memory, base, &mpu->tcmi_iomem);
-    omap_tcmi_reset(mpu);
-}
-
-/* Digital phase-locked loops control */
-struct dpll_ctl_s {
-    MemoryRegion iomem;
-    uint16_t mode;
-    omap_clk dpll;
-};
-
-static uint64_t omap_dpll_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    if (addr == 0x00)  /* CTL_REG */
-        return s->mode;
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_dpll_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
-    uint16_t diff;
-    static const int bypass_div[4] = { 1, 2, 4, 4 };
-    int div, mult;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    if (addr == 0x00) {        /* CTL_REG */
-        /* See omap_ulpd_pm_write() too */
-        diff = s->mode & value;
-        s->mode = value & 0x2fff;
-        if (diff & (0x3ff << 2)) {
-            if (value & (1 << 4)) {                    /* PLL_ENABLE */
-                div = ((value >> 5) & 3) + 1;          /* PLL_DIV */
-                mult = MIN((value >> 7) & 0x1f, 1);    /* PLL_MULT */
-            } else {
-                div = bypass_div[((value >> 2) & 3)];  /* BYPASS_DIV */
-                mult = 1;
-            }
-            omap_clk_setrate(s->dpll, div, mult);
-        }
-
-        /* Enter the desired mode.  */
-        s->mode = (s->mode & 0xfffe) | ((s->mode >> 4) & 1);
-
-        /* Act as if the lock is restored.  */
-        s->mode |= 2;
-    } else {
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_dpll_ops = {
-    .read = omap_dpll_read,
-    .write = omap_dpll_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_dpll_reset(struct dpll_ctl_s *s)
-{
-    s->mode = 0x2002;
-    omap_clk_setrate(s->dpll, 1, 1);
-}
-
-static struct dpll_ctl_s  *omap_dpll_init(MemoryRegion *memory,
-                           hwaddr base, omap_clk clk)
-{
-    struct dpll_ctl_s *s = g_malloc0(sizeof(*s));
-    memory_region_init_io(&s->iomem, &omap_dpll_ops, s, "omap-dpll", 0x100);
-
-    s->dpll = clk;
-    omap_dpll_reset(s);
-
-    memory_region_add_subregion(memory, base, &s->iomem);
-    return s;
-}
-
-/* MPU Clock/Reset/Power Mode Control */
-static uint64_t omap_clkm_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00: /* ARM_CKCTL */
-        return s->clkm.arm_ckctl;
-
-    case 0x04: /* ARM_IDLECT1 */
-        return s->clkm.arm_idlect1;
-
-    case 0x08: /* ARM_IDLECT2 */
-        return s->clkm.arm_idlect2;
-
-    case 0x0c: /* ARM_EWUPCT */
-        return s->clkm.arm_ewupct;
-
-    case 0x10: /* ARM_RSTCT1 */
-        return s->clkm.arm_rstct1;
-
-    case 0x14: /* ARM_RSTCT2 */
-        return s->clkm.arm_rstct2;
-
-    case 0x18: /* ARM_SYSST */
-        return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start;
-
-    case 0x1c: /* ARM_CKOUT1 */
-        return s->clkm.arm_ckout1;
-
-    case 0x20: /* ARM_CKOUT2 */
-        break;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static inline void omap_clkm_ckctl_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-    if (diff & (1 << 14)) {                            /* ARM_INTHCK_SEL */
-        if (value & (1 << 14))
-            /* Reserved */;
-        else {
-            clk = omap_findclk(s, "arminth_ck");
-            omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
-        }
-    }
-    if (diff & (1 << 12)) {                            /* ARM_TIMXO */
-        clk = omap_findclk(s, "armtim_ck");
-        if (value & (1 << 12))
-            omap_clk_reparent(clk, omap_findclk(s, "clkin"));
-        else
-            omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
-    }
-    /* XXX: en_dspck */
-    if (diff & (3 << 10)) {                            /* DSPMMUDIV */
-        clk = omap_findclk(s, "dspmmu_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 10) & 3), 1);
-    }
-    if (diff & (3 << 8)) {                             /* TCDIV */
-        clk = omap_findclk(s, "tc_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 8) & 3), 1);
-    }
-    if (diff & (3 << 6)) {                             /* DSPDIV */
-        clk = omap_findclk(s, "dsp_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 6) & 3), 1);
-    }
-    if (diff & (3 << 4)) {                             /* ARMDIV */
-        clk = omap_findclk(s, "arm_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 4) & 3), 1);
-    }
-    if (diff & (3 << 2)) {                             /* LCDDIV */
-        clk = omap_findclk(s, "lcd_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 2) & 3), 1);
-    }
-    if (diff & (3 << 0)) {                             /* PERDIV */
-        clk = omap_findclk(s, "armper_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 0) & 3), 1);
-    }
-}
-
-static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-    if (value & (1 << 11)) {                            /* SETARM_IDLE */
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
-    }
-    if (!(value & (1 << 10)))                          /* WKUP_MODE */
-        qemu_system_shutdown_request();        /* XXX: disable wakeup from IRQ */
-
-#define SET_CANIDLE(clock, bit)                                \
-    if (diff & (1 << bit)) {                           \
-        clk = omap_findclk(s, clock);                  \
-        omap_clk_canidle(clk, (value >> bit) & 1);     \
-    }
-    SET_CANIDLE("mpuwd_ck", 0)                         /* IDLWDT_ARM */
-    SET_CANIDLE("armxor_ck", 1)                                /* IDLXORP_ARM */
-    SET_CANIDLE("mpuper_ck", 2)                                /* IDLPER_ARM */
-    SET_CANIDLE("lcd_ck", 3)                           /* IDLLCD_ARM */
-    SET_CANIDLE("lb_ck", 4)                            /* IDLLB_ARM */
-    SET_CANIDLE("hsab_ck", 5)                          /* IDLHSAB_ARM */
-    SET_CANIDLE("tipb_ck", 6)                          /* IDLIF_ARM */
-    SET_CANIDLE("dma_ck", 6)                           /* IDLIF_ARM */
-    SET_CANIDLE("tc_ck", 6)                            /* IDLIF_ARM */
-    SET_CANIDLE("dpll1", 7)                            /* IDLDPLL_ARM */
-    SET_CANIDLE("dpll2", 7)                            /* IDLDPLL_ARM */
-    SET_CANIDLE("dpll3", 7)                            /* IDLDPLL_ARM */
-    SET_CANIDLE("mpui_ck", 8)                          /* IDLAPI_ARM */
-    SET_CANIDLE("armtim_ck", 9)                                /* IDLTIM_ARM */
-}
-
-static inline void omap_clkm_idlect2_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-#define SET_ONOFF(clock, bit)                          \
-    if (diff & (1 << bit)) {                           \
-        clk = omap_findclk(s, clock);                  \
-        omap_clk_onoff(clk, (value >> bit) & 1);       \
-    }
-    SET_ONOFF("mpuwd_ck", 0)                           /* EN_WDTCK */
-    SET_ONOFF("armxor_ck", 1)                          /* EN_XORPCK */
-    SET_ONOFF("mpuper_ck", 2)                          /* EN_PERCK */
-    SET_ONOFF("lcd_ck", 3)                             /* EN_LCDCK */
-    SET_ONOFF("lb_ck", 4)                              /* EN_LBCK */
-    SET_ONOFF("hsab_ck", 5)                            /* EN_HSABCK */
-    SET_ONOFF("mpui_ck", 6)                            /* EN_APICK */
-    SET_ONOFF("armtim_ck", 7)                          /* EN_TIMCK */
-    SET_CANIDLE("dma_ck", 8)                           /* DMACK_REQ */
-    SET_ONOFF("arm_gpio_ck", 9)                                /* EN_GPIOCK */
-    SET_ONOFF("lbfree_ck", 10)                         /* EN_LBFREECK */
-}
-
-static inline void omap_clkm_ckout1_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-    if (diff & (3 << 4)) {                             /* TCLKOUT */
-        clk = omap_findclk(s, "tclk_out");
-        switch ((value >> 4) & 3) {
-        case 1:
-            omap_clk_reparent(clk, omap_findclk(s, "ck_gen3"));
-            omap_clk_onoff(clk, 1);
-            break;
-        case 2:
-            omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
-            omap_clk_onoff(clk, 1);
-            break;
-        default:
-            omap_clk_onoff(clk, 0);
-        }
-    }
-    if (diff & (3 << 2)) {                             /* DCLKOUT */
-        clk = omap_findclk(s, "dclk_out");
-        switch ((value >> 2) & 3) {
-        case 0:
-            omap_clk_reparent(clk, omap_findclk(s, "dspmmu_ck"));
-            break;
-        case 1:
-            omap_clk_reparent(clk, omap_findclk(s, "ck_gen2"));
-            break;
-        case 2:
-            omap_clk_reparent(clk, omap_findclk(s, "dsp_ck"));
-            break;
-        case 3:
-            omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
-            break;
-        }
-    }
-    if (diff & (3 << 0)) {                             /* ACLKOUT */
-        clk = omap_findclk(s, "aclk_out");
-        switch ((value >> 0) & 3) {
-        case 1:
-            omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
-            omap_clk_onoff(clk, 1);
-            break;
-        case 2:
-            omap_clk_reparent(clk, omap_findclk(s, "arm_ck"));
-            omap_clk_onoff(clk, 1);
-            break;
-        case 3:
-            omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
-            omap_clk_onoff(clk, 1);
-            break;
-        default:
-            omap_clk_onoff(clk, 0);
-        }
-    }
-}
-
-static void omap_clkm_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    uint16_t diff;
-    omap_clk clk;
-    static const char *clkschemename[8] = {
-        "fully synchronous", "fully asynchronous", "synchronous scalable",
-        "mix mode 1", "mix mode 2", "bypass mode", "mix mode 3", "mix mode 4",
-    };
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00: /* ARM_CKCTL */
-        diff = s->clkm.arm_ckctl ^ value;
-        s->clkm.arm_ckctl = value & 0x7fff;
-        omap_clkm_ckctl_update(s, diff, value);
-        return;
-
-    case 0x04: /* ARM_IDLECT1 */
-        diff = s->clkm.arm_idlect1 ^ value;
-        s->clkm.arm_idlect1 = value & 0x0fff;
-        omap_clkm_idlect1_update(s, diff, value);
-        return;
-
-    case 0x08: /* ARM_IDLECT2 */
-        diff = s->clkm.arm_idlect2 ^ value;
-        s->clkm.arm_idlect2 = value & 0x07ff;
-        omap_clkm_idlect2_update(s, diff, value);
-        return;
-
-    case 0x0c: /* ARM_EWUPCT */
-        s->clkm.arm_ewupct = value & 0x003f;
-        return;
-
-    case 0x10: /* ARM_RSTCT1 */
-        diff = s->clkm.arm_rstct1 ^ value;
-        s->clkm.arm_rstct1 = value & 0x0007;
-        if (value & 9) {
-            qemu_system_reset_request();
-            s->clkm.cold_start = 0xa;
-        }
-        if (diff & ~value & 4) {                               /* DSP_RST */
-            omap_mpui_reset(s);
-            omap_tipb_bridge_reset(s->private_tipb);
-            omap_tipb_bridge_reset(s->public_tipb);
-        }
-        if (diff & 2) {                                                /* DSP_EN */
-            clk = omap_findclk(s, "dsp_ck");
-            omap_clk_canidle(clk, (~value >> 1) & 1);
-        }
-        return;
-
-    case 0x14: /* ARM_RSTCT2 */
-        s->clkm.arm_rstct2 = value & 0x0001;
-        return;
-
-    case 0x18: /* ARM_SYSST */
-        if ((s->clkm.clocking_scheme ^ (value >> 11)) & 7) {
-            s->clkm.clocking_scheme = (value >> 11) & 7;
-            printf("%s: clocking scheme set to %s\n", __FUNCTION__,
-                            clkschemename[s->clkm.clocking_scheme]);
-        }
-        s->clkm.cold_start &= value & 0x3f;
-        return;
-
-    case 0x1c: /* ARM_CKOUT1 */
-        diff = s->clkm.arm_ckout1 ^ value;
-        s->clkm.arm_ckout1 = value & 0x003f;
-        omap_clkm_ckout1_update(s, diff, value);
-        return;
-
-    case 0x20: /* ARM_CKOUT2 */
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_clkm_ops = {
-    .read = omap_clkm_read,
-    .write = omap_clkm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
-                                 unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x04: /* DSP_IDLECT1 */
-        return s->clkm.dsp_idlect1;
-
-    case 0x08: /* DSP_IDLECT2 */
-        return s->clkm.dsp_idlect2;
-
-    case 0x14: /* DSP_RSTCT2 */
-        return s->clkm.dsp_rstct2;
-
-    case 0x18: /* DSP_SYSST */
-        return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
-                (s->cpu->env.halted << 6);      /* Quite useless... */
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static inline void omap_clkdsp_idlect1_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-    SET_CANIDLE("dspxor_ck", 1);                       /* IDLXORP_DSP */
-}
-
-static inline void omap_clkdsp_idlect2_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-    SET_ONOFF("dspxor_ck", 1);                         /* EN_XORPCK */
-}
-
-static void omap_clkdsp_write(void *opaque, hwaddr addr,
-                              uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    uint16_t diff;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x04: /* DSP_IDLECT1 */
-        diff = s->clkm.dsp_idlect1 ^ value;
-        s->clkm.dsp_idlect1 = value & 0x01f7;
-        omap_clkdsp_idlect1_update(s, diff, value);
-        break;
-
-    case 0x08: /* DSP_IDLECT2 */
-        s->clkm.dsp_idlect2 = value & 0x0037;
-        diff = s->clkm.dsp_idlect1 ^ value;
-        omap_clkdsp_idlect2_update(s, diff, value);
-        break;
-
-    case 0x14: /* DSP_RSTCT2 */
-        s->clkm.dsp_rstct2 = value & 0x0001;
-        break;
-
-    case 0x18: /* DSP_SYSST */
-        s->clkm.cold_start &= value & 0x3f;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_clkdsp_ops = {
-    .read = omap_clkdsp_read,
-    .write = omap_clkdsp_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_clkm_reset(struct omap_mpu_state_s *s)
-{
-    if (s->wdt && s->wdt->reset)
-        s->clkm.cold_start = 0x6;
-    s->clkm.clocking_scheme = 0;
-    omap_clkm_ckctl_update(s, ~0, 0x3000);
-    s->clkm.arm_ckctl = 0x3000;
-    omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 ^ 0x0400, 0x0400);
-    s->clkm.arm_idlect1 = 0x0400;
-    omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 ^ 0x0100, 0x0100);
-    s->clkm.arm_idlect2 = 0x0100;
-    s->clkm.arm_ewupct = 0x003f;
-    s->clkm.arm_rstct1 = 0x0000;
-    s->clkm.arm_rstct2 = 0x0000;
-    s->clkm.arm_ckout1 = 0x0015;
-    s->clkm.dpll1_mode = 0x2002;
-    omap_clkdsp_idlect1_update(s, s->clkm.dsp_idlect1 ^ 0x0040, 0x0040);
-    s->clkm.dsp_idlect1 = 0x0040;
-    omap_clkdsp_idlect2_update(s, ~0, 0x0000);
-    s->clkm.dsp_idlect2 = 0x0000;
-    s->clkm.dsp_rstct2 = 0x0000;
-}
-
-static void omap_clkm_init(MemoryRegion *memory, hwaddr mpu_base,
-                hwaddr dsp_base, struct omap_mpu_state_s *s)
-{
-    memory_region_init_io(&s->clkm_iomem, &omap_clkm_ops, s,
-                          "omap-clkm", 0x100);
-    memory_region_init_io(&s->clkdsp_iomem, &omap_clkdsp_ops, s,
-                          "omap-clkdsp", 0x1000);
-
-    s->clkm.arm_idlect1 = 0x03ff;
-    s->clkm.arm_idlect2 = 0x0100;
-    s->clkm.dsp_idlect1 = 0x0002;
-    omap_clkm_reset(s);
-    s->clkm.cold_start = 0x3a;
-
-    memory_region_add_subregion(memory, mpu_base, &s->clkm_iomem);
-    memory_region_add_subregion(memory, dsp_base, &s->clkdsp_iomem);
-}
-
-/* MPU I/O */
-struct omap_mpuio_s {
-    qemu_irq irq;
-    qemu_irq kbd_irq;
-    qemu_irq *in;
-    qemu_irq handler[16];
-    qemu_irq wakeup;
-    MemoryRegion iomem;
-
-    uint16_t inputs;
-    uint16_t outputs;
-    uint16_t dir;
-    uint16_t edge;
-    uint16_t mask;
-    uint16_t ints;
-
-    uint16_t debounce;
-    uint16_t latch;
-    uint8_t event;
-
-    uint8_t buttons[5];
-    uint8_t row_latch;
-    uint8_t cols;
-    int kbd_mask;
-    int clk;
-};
-
-static void omap_mpuio_set(void *opaque, int line, int level)
-{
-    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
-    uint16_t prev = s->inputs;
-
-    if (level)
-        s->inputs |= 1 << line;
-    else
-        s->inputs &= ~(1 << line);
-
-    if (((1 << line) & s->dir & ~s->mask) && s->clk) {
-        if ((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) {
-            s->ints |= 1 << line;
-            qemu_irq_raise(s->irq);
-            /* TODO: wakeup */
-        }
-        if ((s->event & (1 << 0)) &&           /* SET_GPIO_EVENT_MODE */
-                (s->event >> 1) == line)       /* PIN_SELECT */
-            s->latch = s->inputs;
-    }
-}
-
-static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
-{
-    int i;
-    uint8_t *row, rows = 0, cols = ~s->cols;
-
-    for (row = s->buttons + 4, i = 1 << 4; i; row --, i >>= 1)
-        if (*row & cols)
-            rows |= i;
-
-    qemu_set_irq(s->kbd_irq, rows && !s->kbd_mask && s->clk);
-    s->row_latch = ~rows;
-}
-
-static uint64_t omap_mpuio_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-    uint16_t ret;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00: /* INPUT_LATCH */
-        return s->inputs;
-
-    case 0x04: /* OUTPUT_REG */
-        return s->outputs;
-
-    case 0x08: /* IO_CNTL */
-        return s->dir;
-
-    case 0x10: /* KBR_LATCH */
-        return s->row_latch;
-
-    case 0x14: /* KBC_REG */
-        return s->cols;
-
-    case 0x18: /* GPIO_EVENT_MODE_REG */
-        return s->event;
-
-    case 0x1c: /* GPIO_INT_EDGE_REG */
-        return s->edge;
-
-    case 0x20: /* KBD_INT */
-        return (~s->row_latch & 0x1f) && !s->kbd_mask;
-
-    case 0x24: /* GPIO_INT */
-        ret = s->ints;
-        s->ints &= s->mask;
-        if (ret)
-            qemu_irq_lower(s->irq);
-        return ret;
-
-    case 0x28: /* KBD_MASKIT */
-        return s->kbd_mask;
-
-    case 0x2c: /* GPIO_MASKIT */
-        return s->mask;
-
-    case 0x30: /* GPIO_DEBOUNCING_REG */
-        return s->debounce;
-
-    case 0x34: /* GPIO_LATCH_REG */
-        return s->latch;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mpuio_write(void *opaque, hwaddr addr,
-                             uint64_t value, unsigned size)
-{
-    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-    uint16_t diff;
-    int ln;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x04: /* OUTPUT_REG */
-        diff = (s->outputs ^ value) & ~s->dir;
-        s->outputs = value;
-        while ((ln = ffs(diff))) {
-            ln --;
-            if (s->handler[ln])
-                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
-            diff &= ~(1 << ln);
-        }
-        break;
-
-    case 0x08: /* IO_CNTL */
-        diff = s->outputs & (s->dir ^ value);
-        s->dir = value;
-
-        value = s->outputs & ~s->dir;
-        while ((ln = ffs(diff))) {
-            ln --;
-            if (s->handler[ln])
-                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
-            diff &= ~(1 << ln);
-        }
-        break;
-
-    case 0x14: /* KBC_REG */
-        s->cols = value;
-        omap_mpuio_kbd_update(s);
-        break;
-
-    case 0x18: /* GPIO_EVENT_MODE_REG */
-        s->event = value & 0x1f;
-        break;
-
-    case 0x1c: /* GPIO_INT_EDGE_REG */
-        s->edge = value;
-        break;
-
-    case 0x28: /* KBD_MASKIT */
-        s->kbd_mask = value & 1;
-        omap_mpuio_kbd_update(s);
-        break;
-
-    case 0x2c: /* GPIO_MASKIT */
-        s->mask = value;
-        break;
-
-    case 0x30: /* GPIO_DEBOUNCING_REG */
-        s->debounce = value & 0x1ff;
-        break;
-
-    case 0x00: /* INPUT_LATCH */
-    case 0x10: /* KBR_LATCH */
-    case 0x20: /* KBD_INT */
-    case 0x24: /* GPIO_INT */
-    case 0x34: /* GPIO_LATCH_REG */
-        OMAP_RO_REG(addr);
-        return;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_mpuio_ops  = {
-    .read = omap_mpuio_read,
-    .write = omap_mpuio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_mpuio_reset(struct omap_mpuio_s *s)
-{
-    s->inputs = 0;
-    s->outputs = 0;
-    s->dir = ~0;
-    s->event = 0;
-    s->edge = 0;
-    s->kbd_mask = 0;
-    s->mask = 0;
-    s->debounce = 0;
-    s->latch = 0;
-    s->ints = 0;
-    s->row_latch = 0x1f;
-    s->clk = 1;
-}
-
-static void omap_mpuio_onoff(void *opaque, int line, int on)
-{
-    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
-
-    s->clk = on;
-    if (on)
-        omap_mpuio_kbd_update(s);
-}
-
-static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory,
-                hwaddr base,
-                qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
-                omap_clk clk)
-{
-    struct omap_mpuio_s *s = (struct omap_mpuio_s *)
-            g_malloc0(sizeof(struct omap_mpuio_s));
-
-    s->irq = gpio_int;
-    s->kbd_irq = kbd_int;
-    s->wakeup = wakeup;
-    s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
-    omap_mpuio_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_mpuio_ops, s,
-                          "omap-mpuio", 0x800);
-    memory_region_add_subregion(memory, base, &s->iomem);
-
-    omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
-
-    return s;
-}
-
-qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
-{
-    return s->in;
-}
-
-void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
-{
-    if (line >= 16 || line < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
-    s->handler[line] = handler;
-}
-
-void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
-{
-    if (row >= 5 || row < 0)
-        hw_error("%s: No key %i-%i\n", __FUNCTION__, col, row);
-
-    if (down)
-        s->buttons[row] |= 1 << col;
-    else
-        s->buttons[row] &= ~(1 << col);
-
-    omap_mpuio_kbd_update(s);
-}
-
-/* MicroWire Interface */
-struct omap_uwire_s {
-    MemoryRegion iomem;
-    qemu_irq txirq;
-    qemu_irq rxirq;
-    qemu_irq txdrq;
-
-    uint16_t txbuf;
-    uint16_t rxbuf;
-    uint16_t control;
-    uint16_t setup[5];
-
-    uWireSlave *chip[4];
-};
-
-static void omap_uwire_transfer_start(struct omap_uwire_s *s)
-{
-    int chipselect = (s->control >> 10) & 3;           /* INDEX */
-    uWireSlave *slave = s->chip[chipselect];
-
-    if ((s->control >> 5) & 0x1f) {                    /* NB_BITS_WR */
-        if (s->control & (1 << 12))                    /* CS_CMD */
-            if (slave && slave->send)
-                slave->send(slave->opaque,
-                                s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
-        s->control &= ~(1 << 14);                      /* CSRB */
-        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
-         * a DRQ.  When is the level IRQ supposed to be reset?  */
-    }
-
-    if ((s->control >> 0) & 0x1f) {                    /* NB_BITS_RD */
-        if (s->control & (1 << 12))                    /* CS_CMD */
-            if (slave && slave->receive)
-                s->rxbuf = slave->receive(slave->opaque);
-        s->control |= 1 << 15;                         /* RDRB */
-        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
-         * a DRQ.  When is the level IRQ supposed to be reset?  */
-    }
-}
-
-static uint64_t omap_uwire_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00: /* RDR */
-        s->control &= ~(1 << 15);                      /* RDRB */
-        return s->rxbuf;
-
-    case 0x04: /* CSR */
-        return s->control;
-
-    case 0x08: /* SR1 */
-        return s->setup[0];
-    case 0x0c: /* SR2 */
-        return s->setup[1];
-    case 0x10: /* SR3 */
-        return s->setup[2];
-    case 0x14: /* SR4 */
-        return s->setup[3];
-    case 0x18: /* SR5 */
-        return s->setup[4];
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_uwire_write(void *opaque, hwaddr addr,
-                             uint64_t value, unsigned size)
-{
-    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00: /* TDR */
-        s->txbuf = value;                              /* TD */
-        if ((s->setup[4] & (1 << 2)) &&                        /* AUTO_TX_EN */
-                        ((s->setup[4] & (1 << 3)) ||   /* CS_TOGGLE_TX_EN */
-                         (s->control & (1 << 12)))) {  /* CS_CMD */
-            s->control |= 1 << 14;                     /* CSRB */
-            omap_uwire_transfer_start(s);
-        }
-        break;
-
-    case 0x04: /* CSR */
-        s->control = value & 0x1fff;
-        if (value & (1 << 13))                         /* START */
-            omap_uwire_transfer_start(s);
-        break;
-
-    case 0x08: /* SR1 */
-        s->setup[0] = value & 0x003f;
-        break;
-
-    case 0x0c: /* SR2 */
-        s->setup[1] = value & 0x0fc0;
-        break;
-
-    case 0x10: /* SR3 */
-        s->setup[2] = value & 0x0003;
-        break;
-
-    case 0x14: /* SR4 */
-        s->setup[3] = value & 0x0001;
-        break;
-
-    case 0x18: /* SR5 */
-        s->setup[4] = value & 0x000f;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_uwire_ops = {
-    .read = omap_uwire_read,
-    .write = omap_uwire_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_uwire_reset(struct omap_uwire_s *s)
-{
-    s->control = 0;
-    s->setup[0] = 0;
-    s->setup[1] = 0;
-    s->setup[2] = 0;
-    s->setup[3] = 0;
-    s->setup[4] = 0;
-}
-
-static struct omap_uwire_s *omap_uwire_init(MemoryRegion *system_memory,
-                                            hwaddr base,
-                                            qemu_irq txirq, qemu_irq rxirq,
-                                            qemu_irq dma,
-                                            omap_clk clk)
-{
-    struct omap_uwire_s *s = (struct omap_uwire_s *)
-            g_malloc0(sizeof(struct omap_uwire_s));
-
-    s->txirq = txirq;
-    s->rxirq = rxirq;
-    s->txdrq = dma;
-    omap_uwire_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_uwire_ops, s, "omap-uwire", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    return s;
-}
-
-void omap_uwire_attach(struct omap_uwire_s *s,
-                uWireSlave *slave, int chipselect)
-{
-    if (chipselect < 0 || chipselect > 3) {
-        fprintf(stderr, "%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
-        exit(-1);
-    }
-
-    s->chip[chipselect] = slave;
-}
-
-/* Pseudonoise Pulse-Width Light Modulator */
-struct omap_pwl_s {
-    MemoryRegion iomem;
-    uint8_t output;
-    uint8_t level;
-    uint8_t enable;
-    int clk;
-};
-
-static void omap_pwl_update(struct omap_pwl_s *s)
-{
-    int output = (s->clk && s->enable) ? s->level : 0;
-
-    if (output != s->output) {
-        s->output = output;
-        printf("%s: Backlight now at %i/256\n", __FUNCTION__, output);
-    }
-}
-
-static uint64_t omap_pwl_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_read8(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00: /* PWL_LEVEL */
-        return s->level;
-    case 0x04: /* PWL_CTRL */
-        return s->enable;
-    }
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_pwl_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_write8(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00: /* PWL_LEVEL */
-        s->level = value;
-        omap_pwl_update(s);
-        break;
-    case 0x04: /* PWL_CTRL */
-        s->enable = value & 1;
-        omap_pwl_update(s);
-        break;
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_pwl_ops = {
-    .read = omap_pwl_read,
-    .write = omap_pwl_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_pwl_reset(struct omap_pwl_s *s)
-{
-    s->output = 0;
-    s->level = 0;
-    s->enable = 0;
-    s->clk = 1;
-    omap_pwl_update(s);
-}
-
-static void omap_pwl_clk_update(void *opaque, int line, int on)
-{
-    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
-
-    s->clk = on;
-    omap_pwl_update(s);
-}
-
-static struct omap_pwl_s *omap_pwl_init(MemoryRegion *system_memory,
-                                        hwaddr base,
-                                        omap_clk clk)
-{
-    struct omap_pwl_s *s = g_malloc0(sizeof(*s));
-
-    omap_pwl_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_pwl_ops, s,
-                          "omap-pwl", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
-    return s;
-}
-
-/* Pulse-Width Tone module */
-struct omap_pwt_s {
-    MemoryRegion iomem;
-    uint8_t frc;
-    uint8_t vrc;
-    uint8_t gcr;
-    omap_clk clk;
-};
-
-static uint64_t omap_pwt_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_read8(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00: /* FRC */
-        return s->frc;
-    case 0x04: /* VCR */
-        return s->vrc;
-    case 0x08: /* GCR */
-        return s->gcr;
-    }
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_pwt_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_write8(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00: /* FRC */
-        s->frc = value & 0x3f;
-        break;
-    case 0x04: /* VRC */
-        if ((value ^ s->vrc) & 1) {
-            if (value & 1)
-                printf("%s: %iHz buzz on\n", __FUNCTION__, (int)
-                                /* 1.5 MHz from a 12-MHz or 13-MHz PWT_CLK */
-                                ((omap_clk_getrate(s->clk) >> 3) /
-                                 /* Pre-multiplexer divider */
-                                 ((s->gcr & 2) ? 1 : 154) /
-                                 /* Octave multiplexer */
-                                 (2 << (value & 3)) *
-                                 /* 101/107 divider */
-                                 ((value & (1 << 2)) ? 101 : 107) *
-                                 /*  49/55 divider */
-                                 ((value & (1 << 3)) ?  49 : 55) *
-                                 /*  50/63 divider */
-                                 ((value & (1 << 4)) ?  50 : 63) *
-                                 /*  80/127 divider */
-                                 ((value & (1 << 5)) ?  80 : 127) /
-                                 (107 * 55 * 63 * 127)));
-            else
-                printf("%s: silence!\n", __FUNCTION__);
-        }
-        s->vrc = value & 0x7f;
-        break;
-    case 0x08: /* GCR */
-        s->gcr = value & 3;
-        break;
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_pwt_ops = {
-    .read =omap_pwt_read,
-    .write = omap_pwt_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_pwt_reset(struct omap_pwt_s *s)
-{
-    s->frc = 0;
-    s->vrc = 0;
-    s->gcr = 0;
-}
-
-static struct omap_pwt_s *omap_pwt_init(MemoryRegion *system_memory,
-                                        hwaddr base,
-                                        omap_clk clk)
-{
-    struct omap_pwt_s *s = g_malloc0(sizeof(*s));
-    s->clk = clk;
-    omap_pwt_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_pwt_ops, s,
-                          "omap-pwt", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-    return s;
-}
-
-/* Real-time Clock module */
-struct omap_rtc_s {
-    MemoryRegion iomem;
-    qemu_irq irq;
-    qemu_irq alarm;
-    QEMUTimer *clk;
-
-    uint8_t interrupts;
-    uint8_t status;
-    int16_t comp_reg;
-    int running;
-    int pm_am;
-    int auto_comp;
-    int round;
-    struct tm alarm_tm;
-    time_t alarm_ti;
-
-    struct tm current_tm;
-    time_t ti;
-    uint64_t tick;
-};
-
-static void omap_rtc_interrupts_update(struct omap_rtc_s *s)
-{
-    /* s->alarm is level-triggered */
-    qemu_set_irq(s->alarm, (s->status >> 6) & 1);
-}
-
-static void omap_rtc_alarm_update(struct omap_rtc_s *s)
-{
-    s->alarm_ti = mktimegm(&s->alarm_tm);
-    if (s->alarm_ti == -1)
-        printf("%s: conversion failed\n", __FUNCTION__);
-}
-
-static uint64_t omap_rtc_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-    uint8_t i;
-
-    if (size != 1) {
-        return omap_badwidth_read8(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00: /* SECONDS_REG */
-        return to_bcd(s->current_tm.tm_sec);
-
-    case 0x04: /* MINUTES_REG */
-        return to_bcd(s->current_tm.tm_min);
-
-    case 0x08: /* HOURS_REG */
-        if (s->pm_am)
-            return ((s->current_tm.tm_hour > 11) << 7) |
-                    to_bcd(((s->current_tm.tm_hour - 1) % 12) + 1);
-        else
-            return to_bcd(s->current_tm.tm_hour);
-
-    case 0x0c: /* DAYS_REG */
-        return to_bcd(s->current_tm.tm_mday);
-
-    case 0x10: /* MONTHS_REG */
-        return to_bcd(s->current_tm.tm_mon + 1);
-
-    case 0x14: /* YEARS_REG */
-        return to_bcd(s->current_tm.tm_year % 100);
-
-    case 0x18: /* WEEK_REG */
-        return s->current_tm.tm_wday;
-
-    case 0x20: /* ALARM_SECONDS_REG */
-        return to_bcd(s->alarm_tm.tm_sec);
-
-    case 0x24: /* ALARM_MINUTES_REG */
-        return to_bcd(s->alarm_tm.tm_min);
-
-    case 0x28: /* ALARM_HOURS_REG */
-        if (s->pm_am)
-            return ((s->alarm_tm.tm_hour > 11) << 7) |
-                    to_bcd(((s->alarm_tm.tm_hour - 1) % 12) + 1);
-        else
-            return to_bcd(s->alarm_tm.tm_hour);
-
-    case 0x2c: /* ALARM_DAYS_REG */
-        return to_bcd(s->alarm_tm.tm_mday);
-
-    case 0x30: /* ALARM_MONTHS_REG */
-        return to_bcd(s->alarm_tm.tm_mon + 1);
-
-    case 0x34: /* ALARM_YEARS_REG */
-        return to_bcd(s->alarm_tm.tm_year % 100);
-
-    case 0x40: /* RTC_CTRL_REG */
-        return (s->pm_am << 3) | (s->auto_comp << 2) |
-                (s->round << 1) | s->running;
-
-    case 0x44: /* RTC_STATUS_REG */
-        i = s->status;
-        s->status &= ~0x3d;
-        return i;
-
-    case 0x48: /* RTC_INTERRUPTS_REG */
-        return s->interrupts;
-
-    case 0x4c: /* RTC_COMP_LSB_REG */
-        return ((uint16_t) s->comp_reg) & 0xff;
-
-    case 0x50: /* RTC_COMP_MSB_REG */
-        return ((uint16_t) s->comp_reg) >> 8;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_rtc_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-    struct tm new_tm;
-    time_t ti[2];
-
-    if (size != 1) {
-        return omap_badwidth_write8(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00: /* SECONDS_REG */
-#ifdef ALMDEBUG
-        printf("RTC SEC_REG <-- %02x\n", value);
-#endif
-        s->ti -= s->current_tm.tm_sec;
-        s->ti += from_bcd(value);
-        return;
-
-    case 0x04: /* MINUTES_REG */
-#ifdef ALMDEBUG
-        printf("RTC MIN_REG <-- %02x\n", value);
-#endif
-        s->ti -= s->current_tm.tm_min * 60;
-        s->ti += from_bcd(value) * 60;
-        return;
-
-    case 0x08: /* HOURS_REG */
-#ifdef ALMDEBUG
-        printf("RTC HRS_REG <-- %02x\n", value);
-#endif
-        s->ti -= s->current_tm.tm_hour * 3600;
-        if (s->pm_am) {
-            s->ti += (from_bcd(value & 0x3f) & 12) * 3600;
-            s->ti += ((value >> 7) & 1) * 43200;
-        } else
-            s->ti += from_bcd(value & 0x3f) * 3600;
-        return;
-
-    case 0x0c: /* DAYS_REG */
-#ifdef ALMDEBUG
-        printf("RTC DAY_REG <-- %02x\n", value);
-#endif
-        s->ti -= s->current_tm.tm_mday * 86400;
-        s->ti += from_bcd(value) * 86400;
-        return;
-
-    case 0x10: /* MONTHS_REG */
-#ifdef ALMDEBUG
-        printf("RTC MTH_REG <-- %02x\n", value);
-#endif
-        memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
-        new_tm.tm_mon = from_bcd(value);
-        ti[0] = mktimegm(&s->current_tm);
-        ti[1] = mktimegm(&new_tm);
-
-        if (ti[0] != -1 && ti[1] != -1) {
-            s->ti -= ti[0];
-            s->ti += ti[1];
-        } else {
-            /* A less accurate version */
-            s->ti -= s->current_tm.tm_mon * 2592000;
-            s->ti += from_bcd(value) * 2592000;
-        }
-        return;
-
-    case 0x14: /* YEARS_REG */
-#ifdef ALMDEBUG
-        printf("RTC YRS_REG <-- %02x\n", value);
-#endif
-        memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
-        new_tm.tm_year += from_bcd(value) - (new_tm.tm_year % 100);
-        ti[0] = mktimegm(&s->current_tm);
-        ti[1] = mktimegm(&new_tm);
-
-        if (ti[0] != -1 && ti[1] != -1) {
-            s->ti -= ti[0];
-            s->ti += ti[1];
-        } else {
-            /* A less accurate version */
-            s->ti -= (s->current_tm.tm_year % 100) * 31536000;
-            s->ti += from_bcd(value) * 31536000;
-        }
-        return;
-
-    case 0x18: /* WEEK_REG */
-        return;        /* Ignored */
-
-    case 0x20: /* ALARM_SECONDS_REG */
-#ifdef ALMDEBUG
-        printf("ALM SEC_REG <-- %02x\n", value);
-#endif
-        s->alarm_tm.tm_sec = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x24: /* ALARM_MINUTES_REG */
-#ifdef ALMDEBUG
-        printf("ALM MIN_REG <-- %02x\n", value);
-#endif
-        s->alarm_tm.tm_min = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x28: /* ALARM_HOURS_REG */
-#ifdef ALMDEBUG
-        printf("ALM HRS_REG <-- %02x\n", value);
-#endif
-        if (s->pm_am)
-            s->alarm_tm.tm_hour =
-                    ((from_bcd(value & 0x3f)) % 12) +
-                    ((value >> 7) & 1) * 12;
-        else
-            s->alarm_tm.tm_hour = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x2c: /* ALARM_DAYS_REG */
-#ifdef ALMDEBUG
-        printf("ALM DAY_REG <-- %02x\n", value);
-#endif
-        s->alarm_tm.tm_mday = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x30: /* ALARM_MONTHS_REG */
-#ifdef ALMDEBUG
-        printf("ALM MON_REG <-- %02x\n", value);
-#endif
-        s->alarm_tm.tm_mon = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x34: /* ALARM_YEARS_REG */
-#ifdef ALMDEBUG
-        printf("ALM YRS_REG <-- %02x\n", value);
-#endif
-        s->alarm_tm.tm_year = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x40: /* RTC_CTRL_REG */
-#ifdef ALMDEBUG
-        printf("RTC CONTROL <-- %02x\n", value);
-#endif
-        s->pm_am = (value >> 3) & 1;
-        s->auto_comp = (value >> 2) & 1;
-        s->round = (value >> 1) & 1;
-        s->running = value & 1;
-        s->status &= 0xfd;
-        s->status |= s->running << 1;
-        return;
-
-    case 0x44: /* RTC_STATUS_REG */
-#ifdef ALMDEBUG
-        printf("RTC STATUSL <-- %02x\n", value);
-#endif
-        s->status &= ~((value & 0xc0) ^ 0x80);
-        omap_rtc_interrupts_update(s);
-        return;
-
-    case 0x48: /* RTC_INTERRUPTS_REG */
-#ifdef ALMDEBUG
-        printf("RTC INTRS <-- %02x\n", value);
-#endif
-        s->interrupts = value;
-        return;
-
-    case 0x4c: /* RTC_COMP_LSB_REG */
-#ifdef ALMDEBUG
-        printf("RTC COMPLSB <-- %02x\n", value);
-#endif
-        s->comp_reg &= 0xff00;
-        s->comp_reg |= 0x00ff & value;
-        return;
-
-    case 0x50: /* RTC_COMP_MSB_REG */
-#ifdef ALMDEBUG
-        printf("RTC COMPMSB <-- %02x\n", value);
-#endif
-        s->comp_reg &= 0x00ff;
-        s->comp_reg |= 0xff00 & (value << 8);
-        return;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_rtc_ops = {
-    .read = omap_rtc_read,
-    .write = omap_rtc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_rtc_tick(void *opaque)
-{
-    struct omap_rtc_s *s = opaque;
-
-    if (s->round) {
-        /* Round to nearest full minute.  */
-        if (s->current_tm.tm_sec < 30)
-            s->ti -= s->current_tm.tm_sec;
-        else
-            s->ti += 60 - s->current_tm.tm_sec;
-
-        s->round = 0;
-    }
-
-    localtime_r(&s->ti, &s->current_tm);
-
-    if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
-        s->status |= 0x40;
-        omap_rtc_interrupts_update(s);
-    }
-
-    if (s->interrupts & 0x04)
-        switch (s->interrupts & 3) {
-        case 0:
-            s->status |= 0x04;
-            qemu_irq_pulse(s->irq);
-            break;
-        case 1:
-            if (s->current_tm.tm_sec)
-                break;
-            s->status |= 0x08;
-            qemu_irq_pulse(s->irq);
-            break;
-        case 2:
-            if (s->current_tm.tm_sec || s->current_tm.tm_min)
-                break;
-            s->status |= 0x10;
-            qemu_irq_pulse(s->irq);
-            break;
-        case 3:
-            if (s->current_tm.tm_sec ||
-                            s->current_tm.tm_min || s->current_tm.tm_hour)
-                break;
-            s->status |= 0x20;
-            qemu_irq_pulse(s->irq);
-            break;
-        }
-
-    /* Move on */
-    if (s->running)
-        s->ti ++;
-    s->tick += 1000;
-
-    /*
-     * Every full hour add a rough approximation of the compensation
-     * register to the 32kHz Timer (which drives the RTC) value. 
-     */
-    if (s->auto_comp && !s->current_tm.tm_sec && !s->current_tm.tm_min)
-        s->tick += s->comp_reg * 1000 / 32768;
-
-    qemu_mod_timer(s->clk, s->tick);
-}
-
-static void omap_rtc_reset(struct omap_rtc_s *s)
-{
-    struct tm tm;
-
-    s->interrupts = 0;
-    s->comp_reg = 0;
-    s->running = 0;
-    s->pm_am = 0;
-    s->auto_comp = 0;
-    s->round = 0;
-    s->tick = qemu_get_clock_ms(rtc_clock);
-    memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
-    s->alarm_tm.tm_mday = 0x01;
-    s->status = 1 << 7;
-    qemu_get_timedate(&tm, 0);
-    s->ti = mktimegm(&tm);
-
-    omap_rtc_alarm_update(s);
-    omap_rtc_tick(s);
-}
-
-static struct omap_rtc_s *omap_rtc_init(MemoryRegion *system_memory,
-                                        hwaddr base,
-                                        qemu_irq timerirq, qemu_irq alarmirq,
-                                        omap_clk clk)
-{
-    struct omap_rtc_s *s = (struct omap_rtc_s *)
-            g_malloc0(sizeof(struct omap_rtc_s));
-
-    s->irq = timerirq;
-    s->alarm = alarmirq;
-    s->clk = qemu_new_timer_ms(rtc_clock, omap_rtc_tick, s);
-
-    omap_rtc_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_rtc_ops, s,
-                          "omap-rtc", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    return s;
-}
-
-/* Multi-channel Buffered Serial Port interfaces */
-struct omap_mcbsp_s {
-    MemoryRegion iomem;
-    qemu_irq txirq;
-    qemu_irq rxirq;
-    qemu_irq txdrq;
-    qemu_irq rxdrq;
-
-    uint16_t spcr[2];
-    uint16_t rcr[2];
-    uint16_t xcr[2];
-    uint16_t srgr[2];
-    uint16_t mcr[2];
-    uint16_t pcr;
-    uint16_t rcer[8];
-    uint16_t xcer[8];
-    int tx_rate;
-    int rx_rate;
-    int tx_req;
-    int rx_req;
-
-    I2SCodec *codec;
-    QEMUTimer *source_timer;
-    QEMUTimer *sink_timer;
-};
-
-static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s)
-{
-    int irq;
-
-    switch ((s->spcr[0] >> 4) & 3) {                   /* RINTM */
-    case 0:
-        irq = (s->spcr[0] >> 1) & 1;                   /* RRDY */
-        break;
-    case 3:
-        irq = (s->spcr[0] >> 3) & 1;                   /* RSYNCERR */
-        break;
-    default:
-        irq = 0;
-        break;
-    }
-
-    if (irq)
-        qemu_irq_pulse(s->rxirq);
-
-    switch ((s->spcr[1] >> 4) & 3) {                   /* XINTM */
-    case 0:
-        irq = (s->spcr[1] >> 1) & 1;                   /* XRDY */
-        break;
-    case 3:
-        irq = (s->spcr[1] >> 3) & 1;                   /* XSYNCERR */
-        break;
-    default:
-        irq = 0;
-        break;
-    }
-
-    if (irq)
-        qemu_irq_pulse(s->txirq);
-}
-
-static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s)
-{
-    if ((s->spcr[0] >> 1) & 1)                         /* RRDY */
-        s->spcr[0] |= 1 << 2;                          /* RFULL */
-    s->spcr[0] |= 1 << 1;                              /* RRDY */
-    qemu_irq_raise(s->rxdrq);
-    omap_mcbsp_intr_update(s);
-}
-
-static void omap_mcbsp_source_tick(void *opaque)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-    static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
-
-    if (!s->rx_rate)
-        return;
-    if (s->rx_req)
-        printf("%s: Rx FIFO overrun\n", __FUNCTION__);
-
-    s->rx_req = s->rx_rate << bps[(s->rcr[0] >> 5) & 7];
-
-    omap_mcbsp_rx_newdata(s);
-    qemu_mod_timer(s->source_timer, qemu_get_clock_ns(vm_clock) +
-                   get_ticks_per_sec());
-}
-
-static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s)
-{
-    if (!s->codec || !s->codec->rts)
-        omap_mcbsp_source_tick(s);
-    else if (s->codec->in.len) {
-        s->rx_req = s->codec->in.len;
-        omap_mcbsp_rx_newdata(s);
-    }
-}
-
-static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s)
-{
-    qemu_del_timer(s->source_timer);
-}
-
-static void omap_mcbsp_rx_done(struct omap_mcbsp_s *s)
-{
-    s->spcr[0] &= ~(1 << 1);                           /* RRDY */
-    qemu_irq_lower(s->rxdrq);
-    omap_mcbsp_intr_update(s);
-}
-
-static void omap_mcbsp_tx_newdata(struct omap_mcbsp_s *s)
-{
-    s->spcr[1] |= 1 << 1;                              /* XRDY */
-    qemu_irq_raise(s->txdrq);
-    omap_mcbsp_intr_update(s);
-}
-
-static void omap_mcbsp_sink_tick(void *opaque)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-    static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
-
-    if (!s->tx_rate)
-        return;
-    if (s->tx_req)
-        printf("%s: Tx FIFO underrun\n", __FUNCTION__);
-
-    s->tx_req = s->tx_rate << bps[(s->xcr[0] >> 5) & 7];
-
-    omap_mcbsp_tx_newdata(s);
-    qemu_mod_timer(s->sink_timer, qemu_get_clock_ns(vm_clock) +
-                   get_ticks_per_sec());
-}
-
-static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s)
-{
-    if (!s->codec || !s->codec->cts)
-        omap_mcbsp_sink_tick(s);
-    else if (s->codec->out.size) {
-        s->tx_req = s->codec->out.size;
-        omap_mcbsp_tx_newdata(s);
-    }
-}
-
-static void omap_mcbsp_tx_done(struct omap_mcbsp_s *s)
-{
-    s->spcr[1] &= ~(1 << 1);                           /* XRDY */
-    qemu_irq_lower(s->txdrq);
-    omap_mcbsp_intr_update(s);
-    if (s->codec && s->codec->cts)
-        s->codec->tx_swallow(s->codec->opaque);
-}
-
-static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s)
-{
-    s->tx_req = 0;
-    omap_mcbsp_tx_done(s);
-    qemu_del_timer(s->sink_timer);
-}
-
-static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
-{
-    int prev_rx_rate, prev_tx_rate;
-    int rx_rate = 0, tx_rate = 0;
-    int cpu_rate = 1500000;    /* XXX */
-
-    /* TODO: check CLKSTP bit */
-    if (s->spcr[1] & (1 << 6)) {                       /* GRST */
-        if (s->spcr[0] & (1 << 0)) {                   /* RRST */
-            if ((s->srgr[1] & (1 << 13)) &&            /* CLKSM */
-                            (s->pcr & (1 << 8))) {     /* CLKRM */
-                if (~s->pcr & (1 << 7))                        /* SCLKME */
-                    rx_rate = cpu_rate /
-                            ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
-            } else
-                if (s->codec)
-                    rx_rate = s->codec->rx_rate;
-        }
-
-        if (s->spcr[1] & (1 << 0)) {                   /* XRST */
-            if ((s->srgr[1] & (1 << 13)) &&            /* CLKSM */
-                            (s->pcr & (1 << 9))) {     /* CLKXM */
-                if (~s->pcr & (1 << 7))                        /* SCLKME */
-                    tx_rate = cpu_rate /
-                            ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
-            } else
-                if (s->codec)
-                    tx_rate = s->codec->tx_rate;
-        }
-    }
-    prev_tx_rate = s->tx_rate;
-    prev_rx_rate = s->rx_rate;
-    s->tx_rate = tx_rate;
-    s->rx_rate = rx_rate;
-
-    if (s->codec)
-        s->codec->set_rate(s->codec->opaque, rx_rate, tx_rate);
-
-    if (!prev_tx_rate && tx_rate)
-        omap_mcbsp_tx_start(s);
-    else if (s->tx_rate && !tx_rate)
-        omap_mcbsp_tx_stop(s);
-
-    if (!prev_rx_rate && rx_rate)
-        omap_mcbsp_rx_start(s);
-    else if (prev_tx_rate && !tx_rate)
-        omap_mcbsp_rx_stop(s);
-}
-
-static uint64_t omap_mcbsp_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-    uint16_t ret;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00: /* DRR2 */
-        if (((s->rcr[0] >> 5) & 7) < 3)                        /* RWDLEN1 */
-            return 0x0000;
-        /* Fall through.  */
-    case 0x02: /* DRR1 */
-        if (s->rx_req < 2) {
-            printf("%s: Rx FIFO underrun\n", __FUNCTION__);
-            omap_mcbsp_rx_done(s);
-        } else {
-            s->tx_req -= 2;
-            if (s->codec && s->codec->in.len >= 2) {
-                ret = s->codec->in.fifo[s->codec->in.start ++] << 8;
-                ret |= s->codec->in.fifo[s->codec->in.start ++];
-                s->codec->in.len -= 2;
-            } else
-                ret = 0x0000;
-            if (!s->tx_req)
-                omap_mcbsp_rx_done(s);
-            return ret;
-        }
-        return 0x0000;
-
-    case 0x04: /* DXR2 */
-    case 0x06: /* DXR1 */
-        return 0x0000;
-
-    case 0x08: /* SPCR2 */
-        return s->spcr[1];
-    case 0x0a: /* SPCR1 */
-        return s->spcr[0];
-    case 0x0c: /* RCR2 */
-        return s->rcr[1];
-    case 0x0e: /* RCR1 */
-        return s->rcr[0];
-    case 0x10: /* XCR2 */
-        return s->xcr[1];
-    case 0x12: /* XCR1 */
-        return s->xcr[0];
-    case 0x14: /* SRGR2 */
-        return s->srgr[1];
-    case 0x16: /* SRGR1 */
-        return s->srgr[0];
-    case 0x18: /* MCR2 */
-        return s->mcr[1];
-    case 0x1a: /* MCR1 */
-        return s->mcr[0];
-    case 0x1c: /* RCERA */
-        return s->rcer[0];
-    case 0x1e: /* RCERB */
-        return s->rcer[1];
-    case 0x20: /* XCERA */
-        return s->xcer[0];
-    case 0x22: /* XCERB */
-        return s->xcer[1];
-    case 0x24: /* PCR0 */
-        return s->pcr;
-    case 0x26: /* RCERC */
-        return s->rcer[2];
-    case 0x28: /* RCERD */
-        return s->rcer[3];
-    case 0x2a: /* XCERC */
-        return s->xcer[2];
-    case 0x2c: /* XCERD */
-        return s->xcer[3];
-    case 0x2e: /* RCERE */
-        return s->rcer[4];
-    case 0x30: /* RCERF */
-        return s->rcer[5];
-    case 0x32: /* XCERE */
-        return s->xcer[4];
-    case 0x34: /* XCERF */
-        return s->xcer[5];
-    case 0x36: /* RCERG */
-        return s->rcer[6];
-    case 0x38: /* RCERH */
-        return s->rcer[7];
-    case 0x3a: /* XCERG */
-        return s->xcer[6];
-    case 0x3c: /* XCERH */
-        return s->xcer[7];
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mcbsp_writeh(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    switch (offset) {
-    case 0x00: /* DRR2 */
-    case 0x02: /* DRR1 */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x04: /* DXR2 */
-        if (((s->xcr[0] >> 5) & 7) < 3)                        /* XWDLEN1 */
-            return;
-        /* Fall through.  */
-    case 0x06: /* DXR1 */
-        if (s->tx_req > 1) {
-            s->tx_req -= 2;
-            if (s->codec && s->codec->cts) {
-                s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff;
-                s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff;
-            }
-            if (s->tx_req < 2)
-                omap_mcbsp_tx_done(s);
-        } else
-            printf("%s: Tx FIFO overrun\n", __FUNCTION__);
-        return;
-
-    case 0x08: /* SPCR2 */
-        s->spcr[1] &= 0x0002;
-        s->spcr[1] |= 0x03f9 & value;
-        s->spcr[1] |= 0x0004 & (value << 2);           /* XEMPTY := XRST */
-        if (~value & 1)                                        /* XRST */
-            s->spcr[1] &= ~6;
-        omap_mcbsp_req_update(s);
-        return;
-    case 0x0a: /* SPCR1 */
-        s->spcr[0] &= 0x0006;
-        s->spcr[0] |= 0xf8f9 & value;
-        if (value & (1 << 15))                         /* DLB */
-            printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__);
-        if (~value & 1) {                              /* RRST */
-            s->spcr[0] &= ~6;
-            s->rx_req = 0;
-            omap_mcbsp_rx_done(s);
-        }
-        omap_mcbsp_req_update(s);
-        return;
-
-    case 0x0c: /* RCR2 */
-        s->rcr[1] = value & 0xffff;
-        return;
-    case 0x0e: /* RCR1 */
-        s->rcr[0] = value & 0x7fe0;
-        return;
-    case 0x10: /* XCR2 */
-        s->xcr[1] = value & 0xffff;
-        return;
-    case 0x12: /* XCR1 */
-        s->xcr[0] = value & 0x7fe0;
-        return;
-    case 0x14: /* SRGR2 */
-        s->srgr[1] = value & 0xffff;
-        omap_mcbsp_req_update(s);
-        return;
-    case 0x16: /* SRGR1 */
-        s->srgr[0] = value & 0xffff;
-        omap_mcbsp_req_update(s);
-        return;
-    case 0x18: /* MCR2 */
-        s->mcr[1] = value & 0x03e3;
-        if (value & 3)                                 /* XMCM */
-            printf("%s: Tx channel selection mode enable attempt\n",
-                            __FUNCTION__);
-        return;
-    case 0x1a: /* MCR1 */
-        s->mcr[0] = value & 0x03e1;
-        if (value & 1)                                 /* RMCM */
-            printf("%s: Rx channel selection mode enable attempt\n",
-                            __FUNCTION__);
-        return;
-    case 0x1c: /* RCERA */
-        s->rcer[0] = value & 0xffff;
-        return;
-    case 0x1e: /* RCERB */
-        s->rcer[1] = value & 0xffff;
-        return;
-    case 0x20: /* XCERA */
-        s->xcer[0] = value & 0xffff;
-        return;
-    case 0x22: /* XCERB */
-        s->xcer[1] = value & 0xffff;
-        return;
-    case 0x24: /* PCR0 */
-        s->pcr = value & 0x7faf;
-        return;
-    case 0x26: /* RCERC */
-        s->rcer[2] = value & 0xffff;
-        return;
-    case 0x28: /* RCERD */
-        s->rcer[3] = value & 0xffff;
-        return;
-    case 0x2a: /* XCERC */
-        s->xcer[2] = value & 0xffff;
-        return;
-    case 0x2c: /* XCERD */
-        s->xcer[3] = value & 0xffff;
-        return;
-    case 0x2e: /* RCERE */
-        s->rcer[4] = value & 0xffff;
-        return;
-    case 0x30: /* RCERF */
-        s->rcer[5] = value & 0xffff;
-        return;
-    case 0x32: /* XCERE */
-        s->xcer[4] = value & 0xffff;
-        return;
-    case 0x34: /* XCERF */
-        s->xcer[5] = value & 0xffff;
-        return;
-    case 0x36: /* RCERG */
-        s->rcer[6] = value & 0xffff;
-        return;
-    case 0x38: /* RCERH */
-        s->rcer[7] = value & 0xffff;
-        return;
-    case 0x3a: /* XCERG */
-        s->xcer[6] = value & 0xffff;
-        return;
-    case 0x3c: /* XCERH */
-        s->xcer[7] = value & 0xffff;
-        return;
-    }
-
-    OMAP_BAD_REG(addr);
-}
-
-static void omap_mcbsp_writew(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (offset == 0x04) {                              /* DXR */
-        if (((s->xcr[0] >> 5) & 7) < 3)                        /* XWDLEN1 */
-            return;
-        if (s->tx_req > 3) {
-            s->tx_req -= 4;
-            if (s->codec && s->codec->cts) {
-                s->codec->out.fifo[s->codec->out.len ++] =
-                        (value >> 24) & 0xff;
-                s->codec->out.fifo[s->codec->out.len ++] =
-                        (value >> 16) & 0xff;
-                s->codec->out.fifo[s->codec->out.len ++] =
-                        (value >> 8) & 0xff;
-                s->codec->out.fifo[s->codec->out.len ++] =
-                        (value >> 0) & 0xff;
-            }
-            if (s->tx_req < 4)
-                omap_mcbsp_tx_done(s);
-        } else
-            printf("%s: Tx FIFO overrun\n", __FUNCTION__);
-        return;
-    }
-
-    omap_badwidth_write16(opaque, addr, value);
-}
-
-static void omap_mcbsp_write(void *opaque, hwaddr addr,
-                             uint64_t value, unsigned size)
-{
-    switch (size) {
-    case 2: return omap_mcbsp_writeh(opaque, addr, value);
-    case 4: return omap_mcbsp_writew(opaque, addr, value);
-    default: return omap_badwidth_write16(opaque, addr, value);
-    }
-}
-
-static const MemoryRegionOps omap_mcbsp_ops = {
-    .read = omap_mcbsp_read,
-    .write = omap_mcbsp_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_mcbsp_reset(struct omap_mcbsp_s *s)
-{
-    memset(&s->spcr, 0, sizeof(s->spcr));
-    memset(&s->rcr, 0, sizeof(s->rcr));
-    memset(&s->xcr, 0, sizeof(s->xcr));
-    s->srgr[0] = 0x0001;
-    s->srgr[1] = 0x2000;
-    memset(&s->mcr, 0, sizeof(s->mcr));
-    memset(&s->pcr, 0, sizeof(s->pcr));
-    memset(&s->rcer, 0, sizeof(s->rcer));
-    memset(&s->xcer, 0, sizeof(s->xcer));
-    s->tx_req = 0;
-    s->rx_req = 0;
-    s->tx_rate = 0;
-    s->rx_rate = 0;
-    qemu_del_timer(s->source_timer);
-    qemu_del_timer(s->sink_timer);
-}
-
-static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory,
-                                            hwaddr base,
-                                            qemu_irq txirq, qemu_irq rxirq,
-                                            qemu_irq *dma, omap_clk clk)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
-            g_malloc0(sizeof(struct omap_mcbsp_s));
-
-    s->txirq = txirq;
-    s->rxirq = rxirq;
-    s->txdrq = dma[0];
-    s->rxdrq = dma[1];
-    s->sink_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_sink_tick, s);
-    s->source_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_source_tick, s);
-    omap_mcbsp_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_mcbsp_ops, s, "omap-mcbsp", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    return s;
-}
-
-static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-
-    if (s->rx_rate) {
-        s->rx_req = s->codec->in.len;
-        omap_mcbsp_rx_newdata(s);
-    }
-}
-
-static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-
-    if (s->tx_rate) {
-        s->tx_req = s->codec->out.size;
-        omap_mcbsp_tx_newdata(s);
-    }
-}
-
-void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave)
-{
-    s->codec = slave;
-    slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
-    slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
-}
-
-/* LED Pulse Generators */
-struct omap_lpg_s {
-    MemoryRegion iomem;
-    QEMUTimer *tm;
-
-    uint8_t control;
-    uint8_t power;
-    int64_t on;
-    int64_t period;
-    int clk;
-    int cycle;
-};
-
-static void omap_lpg_tick(void *opaque)
-{
-    struct omap_lpg_s *s = opaque;
-
-    if (s->cycle)
-        qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->period - s->on);
-    else
-        qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->on);
-
-    s->cycle = !s->cycle;
-    printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off");
-}
-
-static void omap_lpg_update(struct omap_lpg_s *s)
-{
-    int64_t on, period = 1, ticks = 1000;
-    static const int per[8] = { 1, 2, 4, 8, 12, 16, 20, 24 };
-
-    if (~s->control & (1 << 6))                                        /* LPGRES */
-        on = 0;
-    else if (s->control & (1 << 7))                            /* PERM_ON */
-        on = period;
-    else {
-        period = muldiv64(ticks, per[s->control & 7],          /* PERCTRL */
-                        256 / 32);
-        on = (s->clk && s->power) ? muldiv64(ticks,
-                        per[(s->control >> 3) & 7], 256) : 0;  /* ONCTRL */
-    }
-
-    qemu_del_timer(s->tm);
-    if (on == period && s->on < s->period)
-        printf("%s: LED is on\n", __FUNCTION__);
-    else if (on == 0 && s->on)
-        printf("%s: LED is off\n", __FUNCTION__);
-    else if (on && (on != s->on || period != s->period)) {
-        s->cycle = 0;
-        s->on = on;
-        s->period = period;
-        omap_lpg_tick(s);
-        return;
-    }
-
-    s->on = on;
-    s->period = period;
-}
-
-static void omap_lpg_reset(struct omap_lpg_s *s)
-{
-    s->control = 0x00;
-    s->power = 0x00;
-    s->clk = 1;
-    omap_lpg_update(s);
-}
-
-static uint64_t omap_lpg_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_read8(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00: /* LCR */
-        return s->control;
-
-    case 0x04: /* PMR */
-        return s->power;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_lpg_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_write8(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00: /* LCR */
-        if (~value & (1 << 6))                                 /* LPGRES */
-            omap_lpg_reset(s);
-        s->control = value & 0xff;
-        omap_lpg_update(s);
-        return;
-
-    case 0x04: /* PMR */
-        s->power = value & 0x01;
-        omap_lpg_update(s);
-        return;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_lpg_ops = {
-    .read = omap_lpg_read,
-    .write = omap_lpg_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_lpg_clk_update(void *opaque, int line, int on)
-{
-    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
-
-    s->clk = on;
-    omap_lpg_update(s);
-}
-
-static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory,
-                                        hwaddr base, omap_clk clk)
-{
-    struct omap_lpg_s *s = (struct omap_lpg_s *)
-            g_malloc0(sizeof(struct omap_lpg_s));
-
-    s->tm = qemu_new_timer_ms(vm_clock, omap_lpg_tick, s);
-
-    omap_lpg_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_lpg_ops, s, "omap-lpg", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
-
-    return s;
-}
-
-/* MPUI Peripheral Bridge configuration */
-static uint64_t omap_mpui_io_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    if (addr == OMAP_MPUI_BASE)        /* CMR */
-        return 0xfe4d;
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mpui_io_write(void *opaque, hwaddr addr,
-                               uint64_t value, unsigned size)
-{
-    /* FIXME: infinite loop */
-    omap_badwidth_write16(opaque, addr, value);
-}
-
-static const MemoryRegionOps omap_mpui_io_ops = {
-    .read = omap_mpui_io_read,
-    .write = omap_mpui_io_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_setup_mpui_io(MemoryRegion *system_memory,
-                               struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->mpui_io_iomem, &omap_mpui_io_ops, mpu,
-                          "omap-mpui-io", 0x7fff);
-    memory_region_add_subregion(system_memory, OMAP_MPUI_BASE,
-                                &mpu->mpui_io_iomem);
-}
-
-/* General chip reset */
-static void omap1_mpu_reset(void *opaque)
-{
-    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
-
-    omap_dma_reset(mpu->dma);
-    omap_mpu_timer_reset(mpu->timer[0]);
-    omap_mpu_timer_reset(mpu->timer[1]);
-    omap_mpu_timer_reset(mpu->timer[2]);
-    omap_wd_timer_reset(mpu->wdt);
-    omap_os_timer_reset(mpu->os_timer);
-    omap_lcdc_reset(mpu->lcd);
-    omap_ulpd_pm_reset(mpu);
-    omap_pin_cfg_reset(mpu);
-    omap_mpui_reset(mpu);
-    omap_tipb_bridge_reset(mpu->private_tipb);
-    omap_tipb_bridge_reset(mpu->public_tipb);
-    omap_dpll_reset(mpu->dpll[0]);
-    omap_dpll_reset(mpu->dpll[1]);
-    omap_dpll_reset(mpu->dpll[2]);
-    omap_uart_reset(mpu->uart[0]);
-    omap_uart_reset(mpu->uart[1]);
-    omap_uart_reset(mpu->uart[2]);
-    omap_mmc_reset(mpu->mmc);
-    omap_mpuio_reset(mpu->mpuio);
-    omap_uwire_reset(mpu->microwire);
-    omap_pwl_reset(mpu->pwl);
-    omap_pwt_reset(mpu->pwt);
-    omap_rtc_reset(mpu->rtc);
-    omap_mcbsp_reset(mpu->mcbsp1);
-    omap_mcbsp_reset(mpu->mcbsp2);
-    omap_mcbsp_reset(mpu->mcbsp3);
-    omap_lpg_reset(mpu->led[0]);
-    omap_lpg_reset(mpu->led[1]);
-    omap_clkm_reset(mpu);
-    cpu_reset(CPU(mpu->cpu));
-}
-
-static const struct omap_map_s {
-    hwaddr phys_dsp;
-    hwaddr phys_mpu;
-    uint32_t size;
-    const char *name;
-} omap15xx_dsp_mm[] = {
-    /* Strobe 0 */
-    { 0xe1010000, 0xfffb0000, 0x800, "UART1 BT" },             /* CS0 */
-    { 0xe1010800, 0xfffb0800, 0x800, "UART2 COM" },            /* CS1 */
-    { 0xe1011800, 0xfffb1800, 0x800, "McBSP1 audio" },         /* CS3 */
-    { 0xe1012000, 0xfffb2000, 0x800, "MCSI2 communication" },  /* CS4 */
-    { 0xe1012800, 0xfffb2800, 0x800, "MCSI1 BT u-Law" },       /* CS5 */
-    { 0xe1013000, 0xfffb3000, 0x800, "uWire" },                        /* CS6 */
-    { 0xe1013800, 0xfffb3800, 0x800, "I^2C" },                 /* CS7 */
-    { 0xe1014000, 0xfffb4000, 0x800, "USB W2FC" },             /* CS8 */
-    { 0xe1014800, 0xfffb4800, 0x800, "RTC" },                  /* CS9 */
-    { 0xe1015000, 0xfffb5000, 0x800, "MPUIO" },                        /* CS10 */
-    { 0xe1015800, 0xfffb5800, 0x800, "PWL" },                  /* CS11 */
-    { 0xe1016000, 0xfffb6000, 0x800, "PWT" },                  /* CS12 */
-    { 0xe1017000, 0xfffb7000, 0x800, "McBSP3" },               /* CS14 */
-    { 0xe1017800, 0xfffb7800, 0x800, "MMC" },                  /* CS15 */
-    { 0xe1019000, 0xfffb9000, 0x800, "32-kHz timer" },         /* CS18 */
-    { 0xe1019800, 0xfffb9800, 0x800, "UART3" },                        /* CS19 */
-    { 0xe101c800, 0xfffbc800, 0x800, "TIPB switches" },                /* CS25 */
-    /* Strobe 1 */
-    { 0xe101e000, 0xfffce000, 0x800, "GPIOs" },                        /* CS28 */
-
-    { 0 }
-};
-
-static void omap_setup_dsp_mapping(MemoryRegion *system_memory,
-                                   const struct omap_map_s *map)
-{
-    MemoryRegion *io;
-
-    for (; map->phys_dsp; map ++) {
-        io = g_new(MemoryRegion, 1);
-        memory_region_init_alias(io, map->name,
-                                 system_memory, map->phys_mpu, map->size);
-        memory_region_add_subregion(system_memory, map->phys_dsp, io);
-    }
-}
-
-void omap_mpu_wakeup(void *opaque, int irq, int req)
-{
-    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
-
-    if (mpu->cpu->env.halted) {
-        cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
-    }
-}
-
-static const struct dma_irq_map omap1_dma_irq_map[] = {
-    { 0, OMAP_INT_DMA_CH0_6 },
-    { 0, OMAP_INT_DMA_CH1_7 },
-    { 0, OMAP_INT_DMA_CH2_8 },
-    { 0, OMAP_INT_DMA_CH3 },
-    { 0, OMAP_INT_DMA_CH4 },
-    { 0, OMAP_INT_DMA_CH5 },
-    { 1, OMAP_INT_1610_DMA_CH6 },
-    { 1, OMAP_INT_1610_DMA_CH7 },
-    { 1, OMAP_INT_1610_DMA_CH8 },
-    { 1, OMAP_INT_1610_DMA_CH9 },
-    { 1, OMAP_INT_1610_DMA_CH10 },
-    { 1, OMAP_INT_1610_DMA_CH11 },
-    { 1, OMAP_INT_1610_DMA_CH12 },
-    { 1, OMAP_INT_1610_DMA_CH13 },
-    { 1, OMAP_INT_1610_DMA_CH14 },
-    { 1, OMAP_INT_1610_DMA_CH15 }
-};
-
-/* DMA ports for OMAP1 */
-static int omap_validate_emiff_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(OMAP_EMIFF_BASE, s->sdram_size, addr);
-}
-
-static int omap_validate_emifs_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(OMAP_EMIFS_BASE, OMAP_EMIFF_BASE - OMAP_EMIFS_BASE,
-                             addr);
-}
-
-static int omap_validate_imif_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(OMAP_IMIF_BASE, s->sram_size, addr);
-}
-
-static int omap_validate_tipb_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(0xfffb0000, 0xffff0000 - 0xfffb0000, addr);
-}
-
-static int omap_validate_local_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(OMAP_LOCALBUS_BASE, 0x1000000, addr);
-}
-
-static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(0xe1010000, 0xe1020004 - 0xe1010000, addr);
-}
-
-struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
-                unsigned long sdram_size,
-                const char *core)
-{
-    int i;
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
-            g_malloc0(sizeof(struct omap_mpu_state_s));
-    qemu_irq *cpu_irq;
-    qemu_irq dma_irqs[6];
-    DriveInfo *dinfo;
-    SysBusDevice *busdev;
-
-    if (!core)
-        core = "ti925t";
-
-    /* Core */
-    s->mpu_model = omap310;
-    s->cpu = cpu_arm_init(core);
-    if (s->cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    s->sdram_size = sdram_size;
-    s->sram_size = OMAP15XX_SRAM_SIZE;
-
-    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
-
-    /* Clocks */
-    omap_clk_init(s);
-
-    /* Memory-mapped stuff */
-    memory_region_init_ram(&s->emiff_ram, "omap1.dram", s->sdram_size);
-    vmstate_register_ram_global(&s->emiff_ram);
-    memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram);
-    memory_region_init_ram(&s->imif_ram, "omap1.sram", s->sram_size);
-    vmstate_register_ram_global(&s->imif_ram);
-    memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram);
-
-    omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s);
-
-    cpu_irq = arm_pic_init_cpu(s->cpu);
-    s->ih[0] = qdev_create(NULL, "omap-intc");
-    qdev_prop_set_uint32(s->ih[0], "size", 0x100);
-    qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck"));
-    qdev_init_nofail(s->ih[0]);
-    busdev = SYS_BUS_DEVICE(s->ih[0]);
-    sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
-    sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
-    sysbus_mmio_map(busdev, 0, 0xfffecb00);
-    s->ih[1] = qdev_create(NULL, "omap-intc");
-    qdev_prop_set_uint32(s->ih[1], "size", 0x800);
-    qdev_prop_set_ptr(s->ih[1], "clk", omap_findclk(s, "arminth_ck"));
-    qdev_init_nofail(s->ih[1]);
-    busdev = SYS_BUS_DEVICE(s->ih[1]);
-    sysbus_connect_irq(busdev, 0,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_15XX_IH2_IRQ));
-    /* The second interrupt controller's FIQ output is not wired up */
-    sysbus_mmio_map(busdev, 0, 0xfffe0000);
-
-    for (i = 0; i < 6; i++) {
-        dma_irqs[i] = qdev_get_gpio_in(s->ih[omap1_dma_irq_map[i].ih],
-                                       omap1_dma_irq_map[i].intr);
-    }
-    s->dma = omap_dma_init(0xfffed800, dma_irqs, system_memory,
-                           qdev_get_gpio_in(s->ih[0], OMAP_INT_DMA_LCD),
-                           s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
-
-    s->port[emiff    ].addr_valid = omap_validate_emiff_addr;
-    s->port[emifs    ].addr_valid = omap_validate_emifs_addr;
-    s->port[imif     ].addr_valid = omap_validate_imif_addr;
-    s->port[tipb     ].addr_valid = omap_validate_tipb_addr;
-    s->port[local    ].addr_valid = omap_validate_local_addr;
-    s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr;
-
-    /* Register SDRAM and SRAM DMA ports for fast transfers.  */
-    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->emiff_ram),
-                         OMAP_EMIFF_BASE, s->sdram_size);
-    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->imif_ram),
-                         OMAP_IMIF_BASE, s->sram_size);
-
-    s->timer[0] = omap_mpu_timer_init(system_memory, 0xfffec500,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER1),
-                    omap_findclk(s, "mputim_ck"));
-    s->timer[1] = omap_mpu_timer_init(system_memory, 0xfffec600,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER2),
-                    omap_findclk(s, "mputim_ck"));
-    s->timer[2] = omap_mpu_timer_init(system_memory, 0xfffec700,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER3),
-                    omap_findclk(s, "mputim_ck"));
-
-    s->wdt = omap_wd_timer_init(system_memory, 0xfffec800,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_WD_TIMER),
-                    omap_findclk(s, "armwdt_ck"));
-
-    s->os_timer = omap_os_timer_init(system_memory, 0xfffb9000,
-                    qdev_get_gpio_in(s->ih[1], OMAP_INT_OS_TIMER),
-                    omap_findclk(s, "clk32-kHz"));
-
-    s->lcd = omap_lcdc_init(system_memory, 0xfffec000,
-                            qdev_get_gpio_in(s->ih[0], OMAP_INT_LCD_CTRL),
-                            omap_dma_get_lcdch(s->dma),
-                            omap_findclk(s, "lcd_ck"));
-
-    omap_ulpd_pm_init(system_memory, 0xfffe0800, s);
-    omap_pin_cfg_init(system_memory, 0xfffe1000, s);
-    omap_id_init(system_memory, s);
-
-    omap_mpui_init(system_memory, 0xfffec900, s);
-
-    s->private_tipb = omap_tipb_bridge_init(system_memory, 0xfffeca00,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_BRIDGE_PRIV),
-                    omap_findclk(s, "tipb_ck"));
-    s->public_tipb = omap_tipb_bridge_init(system_memory, 0xfffed300,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_BRIDGE_PUB),
-                    omap_findclk(s, "tipb_ck"));
-
-    omap_tcmi_init(system_memory, 0xfffecc00, s);
-
-    s->uart[0] = omap_uart_init(0xfffb0000,
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_UART1),
-                    omap_findclk(s, "uart1_ck"),
-                    omap_findclk(s, "uart1_ck"),
-                    s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX],
-                    "uart1",
-                    serial_hds[0]);
-    s->uart[1] = omap_uart_init(0xfffb0800,
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_UART2),
-                    omap_findclk(s, "uart2_ck"),
-                    omap_findclk(s, "uart2_ck"),
-                    s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX],
-                    "uart2",
-                    serial_hds[0] ? serial_hds[1] : NULL);
-    s->uart[2] = omap_uart_init(0xfffb9800,
-                                qdev_get_gpio_in(s->ih[0], OMAP_INT_UART3),
-                    omap_findclk(s, "uart3_ck"),
-                    omap_findclk(s, "uart3_ck"),
-                    s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX],
-                    "uart3",
-                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
-
-    s->dpll[0] = omap_dpll_init(system_memory, 0xfffecf00,
-                                omap_findclk(s, "dpll1"));
-    s->dpll[1] = omap_dpll_init(system_memory, 0xfffed000,
-                                omap_findclk(s, "dpll2"));
-    s->dpll[2] = omap_dpll_init(system_memory, 0xfffed100,
-                                omap_findclk(s, "dpll3"));
-
-    dinfo = drive_get(IF_SD, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "qemu: missing SecureDigital device\n");
-        exit(1);
-    }
-    s->mmc = omap_mmc_init(0xfffb7800, system_memory, dinfo->bdrv,
-                           qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
-                           &s->drq[OMAP_DMA_MMC_TX],
-                    omap_findclk(s, "mmc_ck"));
-
-    s->mpuio = omap_mpuio_init(system_memory, 0xfffb5000,
-                               qdev_get_gpio_in(s->ih[1], OMAP_INT_KEYBOARD),
-                               qdev_get_gpio_in(s->ih[1], OMAP_INT_MPUIO),
-                               s->wakeup, omap_findclk(s, "clk32-kHz"));
-
-    s->gpio = qdev_create(NULL, "omap-gpio");
-    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
-    qdev_prop_set_ptr(s->gpio, "clk", omap_findclk(s, "arm_gpio_ck"));
-    qdev_init_nofail(s->gpio);
-    sysbus_connect_irq(SYS_BUS_DEVICE(s->gpio), 0,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_GPIO_BANK1));
-    sysbus_mmio_map(SYS_BUS_DEVICE(s->gpio), 0, 0xfffce000);
-
-    s->microwire = omap_uwire_init(system_memory, 0xfffb3000,
-                                   qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireTX),
-                                   qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireRX),
-                    s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
-
-    s->pwl = omap_pwl_init(system_memory, 0xfffb5800,
-                           omap_findclk(s, "armxor_ck"));
-    s->pwt = omap_pwt_init(system_memory, 0xfffb6000,
-                           omap_findclk(s, "armxor_ck"));
-
-    s->i2c[0] = qdev_create(NULL, "omap_i2c");
-    qdev_prop_set_uint8(s->i2c[0], "revision", 0x11);
-    qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "mpuper_ck"));
-    qdev_init_nofail(s->i2c[0]);
-    busdev = SYS_BUS_DEVICE(s->i2c[0]);
-    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C));
-    sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_I2C_TX]);
-    sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_I2C_RX]);
-    sysbus_mmio_map(busdev, 0, 0xfffb3800);
-
-    s->rtc = omap_rtc_init(system_memory, 0xfffb4800,
-                           qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_TIMER),
-                           qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_ALARM),
-                    omap_findclk(s, "clk32-kHz"));
-
-    s->mcbsp1 = omap_mcbsp_init(system_memory, 0xfffb1800,
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP1TX),
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP1RX),
-                    &s->drq[OMAP_DMA_MCBSP1_TX], omap_findclk(s, "dspxor_ck"));
-    s->mcbsp2 = omap_mcbsp_init(system_memory, 0xfffb1000,
-                                qdev_get_gpio_in(s->ih[0],
-                                                 OMAP_INT_310_McBSP2_TX),
-                                qdev_get_gpio_in(s->ih[0],
-                                                 OMAP_INT_310_McBSP2_RX),
-                    &s->drq[OMAP_DMA_MCBSP2_TX], omap_findclk(s, "mpuper_ck"));
-    s->mcbsp3 = omap_mcbsp_init(system_memory, 0xfffb7000,
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP3TX),
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP3RX),
-                    &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck"));
-
-    s->led[0] = omap_lpg_init(system_memory,
-                              0xfffbd000, omap_findclk(s, "clk32-kHz"));
-    s->led[1] = omap_lpg_init(system_memory,
-                              0xfffbd800, omap_findclk(s, "clk32-kHz"));
-
-    /* Register mappings not currenlty implemented:
-     * MCSI2 Comm      fffb2000 - fffb27ff (not mapped on OMAP310)
-     * MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310)
-     * USB W2FC                fffb4000 - fffb47ff
-     * Camera Interface        fffb6800 - fffb6fff
-     * USB Host                fffba000 - fffba7ff
-     * FAC             fffba800 - fffbafff
-     * HDQ/1-Wire      fffbc000 - fffbc7ff
-     * TIPB switches   fffbc800 - fffbcfff
-     * Mailbox         fffcf000 - fffcf7ff
-     * Local bus IF    fffec100 - fffec1ff
-     * Local bus MMU   fffec200 - fffec2ff
-     * DSP MMU         fffed200 - fffed2ff
-     */
-
-    omap_setup_dsp_mapping(system_memory, omap15xx_dsp_mm);
-    omap_setup_mpui_io(system_memory, s);
-
-    qemu_register_reset(omap1_mpu_reset, s);
-
-    return s;
-}
diff --git a/hw/omap2.c b/hw/omap2.c
deleted file mode 100644 (file)
index 038a82a..0000000
+++ /dev/null
@@ -1,2684 +0,0 @@
-/*
- * TI OMAP processors emulation.
- *
- * Copyright (C) 2007-2008 Nokia Corporation
- * Written by Andrzej Zaborowski <andrew@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
- *
- * 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 "sysemu/blockdev.h"
-#include "hw.h"
-#include "arm-misc.h"
-#include "omap.h"
-#include "sysemu/sysemu.h"
-#include "qemu/timer.h"
-#include "char/char.h"
-#include "flash.h"
-#include "soc_dma.h"
-#include "sysbus.h"
-#include "audio/audio.h"
-
-/* Enhanced Audio Controller (CODEC only) */
-struct omap_eac_s {
-    qemu_irq irq;
-    MemoryRegion iomem;
-
-    uint16_t sysconfig;
-    uint8_t config[4];
-    uint8_t control;
-    uint8_t address;
-    uint16_t data;
-    uint8_t vtol;
-    uint8_t vtsl;
-    uint16_t mixer;
-    uint16_t gain[4];
-    uint8_t att;
-    uint16_t max[7];
-
-    struct {
-        qemu_irq txdrq;
-        qemu_irq rxdrq;
-        uint32_t (*txrx)(void *opaque, uint32_t, int);
-        void *opaque;
-
-#define EAC_BUF_LEN 1024
-        uint32_t rxbuf[EAC_BUF_LEN];
-        int rxoff;
-        int rxlen;
-        int rxavail;
-        uint32_t txbuf[EAC_BUF_LEN];
-        int txlen;
-        int txavail;
-
-        int enable;
-        int rate;
-
-        uint16_t config[4];
-
-        /* These need to be moved to the actual codec */
-        QEMUSoundCard card;
-        SWVoiceIn *in_voice;
-        SWVoiceOut *out_voice;
-        int hw_enable;
-    } codec;
-
-    struct {
-        uint8_t control;
-        uint16_t config;
-    } modem, bt;
-};
-
-static inline void omap_eac_interrupt_update(struct omap_eac_s *s)
-{
-    qemu_set_irq(s->irq, (s->codec.config[1] >> 14) & 1);      /* AURDI */
-}
-
-static inline void omap_eac_in_dmarequest_update(struct omap_eac_s *s)
-{
-    qemu_set_irq(s->codec.rxdrq, (s->codec.rxavail || s->codec.rxlen) &&
-                    ((s->codec.config[1] >> 12) & 1));         /* DMAREN */
-}
-
-static inline void omap_eac_out_dmarequest_update(struct omap_eac_s *s)
-{
-    qemu_set_irq(s->codec.txdrq, s->codec.txlen < s->codec.txavail &&
-                    ((s->codec.config[1] >> 11) & 1));         /* DMAWEN */
-}
-
-static inline void omap_eac_in_refill(struct omap_eac_s *s)
-{
-    int left = MIN(EAC_BUF_LEN - s->codec.rxlen, s->codec.rxavail) << 2;
-    int start = ((s->codec.rxoff + s->codec.rxlen) & (EAC_BUF_LEN - 1)) << 2;
-    int leftwrap = MIN(left, (EAC_BUF_LEN << 2) - start);
-    int recv = 1;
-    uint8_t *buf = (uint8_t *) s->codec.rxbuf + start;
-
-    left -= leftwrap;
-    start = 0;
-    while (leftwrap && (recv = AUD_read(s->codec.in_voice, buf + start,
-                                    leftwrap)) > 0) {  /* Be defensive */
-        start += recv;
-        leftwrap -= recv;
-    }
-    if (recv <= 0)
-        s->codec.rxavail = 0;
-    else
-        s->codec.rxavail -= start >> 2;
-    s->codec.rxlen += start >> 2;
-
-    if (recv > 0 && left > 0) {
-        start = 0;
-        while (left && (recv = AUD_read(s->codec.in_voice,
-                                        (uint8_t *) s->codec.rxbuf + start,
-                                        left)) > 0) {  /* Be defensive */
-            start += recv;
-            left -= recv;
-        }
-        if (recv <= 0)
-            s->codec.rxavail = 0;
-        else
-            s->codec.rxavail -= start >> 2;
-        s->codec.rxlen += start >> 2;
-    }
-}
-
-static inline void omap_eac_out_empty(struct omap_eac_s *s)
-{
-    int left = s->codec.txlen << 2;
-    int start = 0;
-    int sent = 1;
-
-    while (left && (sent = AUD_write(s->codec.out_voice,
-                                    (uint8_t *) s->codec.txbuf + start,
-                                    left)) > 0) {      /* Be defensive */
-        start += sent;
-        left -= sent;
-    }
-
-    if (!sent) {
-        s->codec.txavail = 0;
-        omap_eac_out_dmarequest_update(s);
-    }
-
-    if (start)
-        s->codec.txlen = 0;
-}
-
-static void omap_eac_in_cb(void *opaque, int avail_b)
-{
-    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
-
-    s->codec.rxavail = avail_b >> 2;
-    omap_eac_in_refill(s);
-    /* TODO: possibly discard current buffer if overrun */
-    omap_eac_in_dmarequest_update(s);
-}
-
-static void omap_eac_out_cb(void *opaque, int free_b)
-{
-    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
-
-    s->codec.txavail = free_b >> 2;
-    if (s->codec.txlen)
-        omap_eac_out_empty(s);
-    else
-        omap_eac_out_dmarequest_update(s);
-}
-
-static void omap_eac_enable_update(struct omap_eac_s *s)
-{
-    s->codec.enable = !(s->codec.config[1] & 1) &&             /* EACPWD */
-            (s->codec.config[1] & 2) &&                                /* AUDEN */
-            s->codec.hw_enable;
-}
-
-static const int omap_eac_fsint[4] = {
-    8000,
-    11025,
-    22050,
-    44100,
-};
-
-static const int omap_eac_fsint2[8] = {
-    8000,
-    11025,
-    22050,
-    44100,
-    48000,
-    0, 0, 0,
-};
-
-static const int omap_eac_fsint3[16] = {
-    8000,
-    11025,
-    16000,
-    22050,
-    24000,
-    32000,
-    44100,
-    48000,
-    0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-static void omap_eac_rate_update(struct omap_eac_s *s)
-{
-    int fsint[3];
-
-    fsint[2] = (s->codec.config[3] >> 9) & 0xf;
-    fsint[1] = (s->codec.config[2] >> 0) & 0x7;
-    fsint[0] = (s->codec.config[0] >> 6) & 0x3;
-    if (fsint[2] < 0xf)
-        s->codec.rate = omap_eac_fsint3[fsint[2]];
-    else if (fsint[1] < 0x7)
-        s->codec.rate = omap_eac_fsint2[fsint[1]];
-    else
-        s->codec.rate = omap_eac_fsint[fsint[0]];
-}
-
-static void omap_eac_volume_update(struct omap_eac_s *s)
-{
-    /* TODO */
-}
-
-static void omap_eac_format_update(struct omap_eac_s *s)
-{
-    struct audsettings fmt;
-
-    /* The hardware buffers at most one sample */
-    if (s->codec.rxlen)
-        s->codec.rxlen = 1;
-
-    if (s->codec.in_voice) {
-        AUD_set_active_in(s->codec.in_voice, 0);
-        AUD_close_in(&s->codec.card, s->codec.in_voice);
-        s->codec.in_voice = NULL;
-    }
-    if (s->codec.out_voice) {
-        omap_eac_out_empty(s);
-        AUD_set_active_out(s->codec.out_voice, 0);
-        AUD_close_out(&s->codec.card, s->codec.out_voice);
-        s->codec.out_voice = NULL;
-        s->codec.txavail = 0;
-    }
-    /* Discard what couldn't be written */
-    s->codec.txlen = 0;
-
-    omap_eac_enable_update(s);
-    if (!s->codec.enable)
-        return;
-
-    omap_eac_rate_update(s);
-    fmt.endianness = ((s->codec.config[0] >> 8) & 1);          /* LI_BI */
-    fmt.nchannels = ((s->codec.config[0] >> 10) & 1) ? 2 : 1;  /* MN_ST */
-    fmt.freq = s->codec.rate;
-    /* TODO: signedness possibly depends on the CODEC hardware - or
-     * does I2S specify it?  */
-    /* All register writes are 16 bits so we we store 16-bit samples
-     * in the buffers regardless of AGCFR[B8_16] value.  */
-    fmt.fmt = AUD_FMT_U16;
-
-    s->codec.in_voice = AUD_open_in(&s->codec.card, s->codec.in_voice,
-                    "eac.codec.in", s, omap_eac_in_cb, &fmt);
-    s->codec.out_voice = AUD_open_out(&s->codec.card, s->codec.out_voice,
-                    "eac.codec.out", s, omap_eac_out_cb, &fmt);
-
-    omap_eac_volume_update(s);
-
-    AUD_set_active_in(s->codec.in_voice, 1);
-    AUD_set_active_out(s->codec.out_voice, 1);
-}
-
-static void omap_eac_reset(struct omap_eac_s *s)
-{
-    s->sysconfig = 0;
-    s->config[0] = 0x0c;
-    s->config[1] = 0x09;
-    s->config[2] = 0xab;
-    s->config[3] = 0x03;
-    s->control = 0x00;
-    s->address = 0x00;
-    s->data = 0x0000;
-    s->vtol = 0x00;
-    s->vtsl = 0x00;
-    s->mixer = 0x0000;
-    s->gain[0] = 0xe7e7;
-    s->gain[1] = 0x6767;
-    s->gain[2] = 0x6767;
-    s->gain[3] = 0x6767;
-    s->att = 0xce;
-    s->max[0] = 0;
-    s->max[1] = 0;
-    s->max[2] = 0;
-    s->max[3] = 0;
-    s->max[4] = 0;
-    s->max[5] = 0;
-    s->max[6] = 0;
-
-    s->modem.control = 0x00;
-    s->modem.config = 0x0000;
-    s->bt.control = 0x00;
-    s->bt.config = 0x0000;
-    s->codec.config[0] = 0x0649;
-    s->codec.config[1] = 0x0000;
-    s->codec.config[2] = 0x0007;
-    s->codec.config[3] = 0x1ffc;
-    s->codec.rxoff = 0;
-    s->codec.rxlen = 0;
-    s->codec.txlen = 0;
-    s->codec.rxavail = 0;
-    s->codec.txavail = 0;
-
-    omap_eac_format_update(s);
-    omap_eac_interrupt_update(s);
-}
-
-static uint64_t omap_eac_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
-    uint32_t ret;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x000:        /* CPCFR1 */
-        return s->config[0];
-    case 0x004:        /* CPCFR2 */
-        return s->config[1];
-    case 0x008:        /* CPCFR3 */
-        return s->config[2];
-    case 0x00c:        /* CPCFR4 */
-        return s->config[3];
-
-    case 0x010:        /* CPTCTL */
-        return s->control | ((s->codec.rxavail + s->codec.rxlen > 0) << 7) |
-                ((s->codec.txlen < s->codec.txavail) << 5);
-
-    case 0x014:        /* CPTTADR */
-        return s->address;
-    case 0x018:        /* CPTDATL */
-        return s->data & 0xff;
-    case 0x01c:        /* CPTDATH */
-        return s->data >> 8;
-    case 0x020:        /* CPTVSLL */
-        return s->vtol;
-    case 0x024:        /* CPTVSLH */
-        return s->vtsl | (3 << 5);     /* CRDY1 | CRDY2 */
-    case 0x040:        /* MPCTR */
-        return s->modem.control;
-    case 0x044:        /* MPMCCFR */
-        return s->modem.config;
-    case 0x060:        /* BPCTR */
-        return s->bt.control;
-    case 0x064:        /* BPMCCFR */
-        return s->bt.config;
-    case 0x080:        /* AMSCFR */
-        return s->mixer;
-    case 0x084:        /* AMVCTR */
-        return s->gain[0];
-    case 0x088:        /* AM1VCTR */
-        return s->gain[1];
-    case 0x08c:        /* AM2VCTR */
-        return s->gain[2];
-    case 0x090:        /* AM3VCTR */
-        return s->gain[3];
-    case 0x094:        /* ASTCTR */
-        return s->att;
-    case 0x098:        /* APD1LCR */
-        return s->max[0];
-    case 0x09c:        /* APD1RCR */
-        return s->max[1];
-    case 0x0a0:        /* APD2LCR */
-        return s->max[2];
-    case 0x0a4:        /* APD2RCR */
-        return s->max[3];
-    case 0x0a8:        /* APD3LCR */
-        return s->max[4];
-    case 0x0ac:        /* APD3RCR */
-        return s->max[5];
-    case 0x0b0:        /* APD4R */
-        return s->max[6];
-    case 0x0b4:        /* ADWR */
-        /* This should be write-only?  Docs list it as read-only.  */
-        return 0x0000;
-    case 0x0b8:        /* ADRDR */
-        if (likely(s->codec.rxlen > 1)) {
-            ret = s->codec.rxbuf[s->codec.rxoff ++];
-            s->codec.rxlen --;
-            s->codec.rxoff &= EAC_BUF_LEN - 1;
-            return ret;
-        } else if (s->codec.rxlen) {
-            ret = s->codec.rxbuf[s->codec.rxoff ++];
-            s->codec.rxlen --;
-            s->codec.rxoff &= EAC_BUF_LEN - 1;
-            if (s->codec.rxavail)
-                omap_eac_in_refill(s);
-            omap_eac_in_dmarequest_update(s);
-            return ret;
-        }
-        return 0x0000;
-    case 0x0bc:        /* AGCFR */
-        return s->codec.config[0];
-    case 0x0c0:        /* AGCTR */
-        return s->codec.config[1] | ((s->codec.config[1] & 2) << 14);
-    case 0x0c4:        /* AGCFR2 */
-        return s->codec.config[2];
-    case 0x0c8:        /* AGCFR3 */
-        return s->codec.config[3];
-    case 0x0cc:        /* MBPDMACTR */
-    case 0x0d0:        /* MPDDMARR */
-    case 0x0d8:        /* MPUDMARR */
-    case 0x0e4:        /* BPDDMARR */
-    case 0x0ec:        /* BPUDMARR */
-        return 0x0000;
-
-    case 0x100:        /* VERSION_NUMBER */
-        return 0x0010;
-
-    case 0x104:        /* SYSCONFIG */
-        return s->sysconfig;
-
-    case 0x108:        /* SYSSTATUS */
-        return 1 | 0xe;                                        /* RESETDONE | stuff */
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_eac_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x098:        /* APD1LCR */
-    case 0x09c:        /* APD1RCR */
-    case 0x0a0:        /* APD2LCR */
-    case 0x0a4:        /* APD2RCR */
-    case 0x0a8:        /* APD3LCR */
-    case 0x0ac:        /* APD3RCR */
-    case 0x0b0:        /* APD4R */
-    case 0x0b8:        /* ADRDR */
-    case 0x0d0:        /* MPDDMARR */
-    case 0x0d8:        /* MPUDMARR */
-    case 0x0e4:        /* BPDDMARR */
-    case 0x0ec:        /* BPUDMARR */
-    case 0x100:        /* VERSION_NUMBER */
-    case 0x108:        /* SYSSTATUS */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x000:        /* CPCFR1 */
-        s->config[0] = value & 0xff;
-        omap_eac_format_update(s);
-        break;
-    case 0x004:        /* CPCFR2 */
-        s->config[1] = value & 0xff;
-        omap_eac_format_update(s);
-        break;
-    case 0x008:        /* CPCFR3 */
-        s->config[2] = value & 0xff;
-        omap_eac_format_update(s);
-        break;
-    case 0x00c:        /* CPCFR4 */
-        s->config[3] = value & 0xff;
-        omap_eac_format_update(s);
-        break;
-
-    case 0x010:        /* CPTCTL */
-        /* Assuming TXF and TXE bits are read-only... */
-        s->control = value & 0x5f;
-        omap_eac_interrupt_update(s);
-        break;
-
-    case 0x014:        /* CPTTADR */
-        s->address = value & 0xff;
-        break;
-    case 0x018:        /* CPTDATL */
-        s->data &= 0xff00;
-        s->data |= value & 0xff;
-        break;
-    case 0x01c:        /* CPTDATH */
-        s->data &= 0x00ff;
-        s->data |= value << 8;
-        break;
-    case 0x020:        /* CPTVSLL */
-        s->vtol = value & 0xf8;
-        break;
-    case 0x024:        /* CPTVSLH */
-        s->vtsl = value & 0x9f;
-        break;
-    case 0x040:        /* MPCTR */
-        s->modem.control = value & 0x8f;
-        break;
-    case 0x044:        /* MPMCCFR */
-        s->modem.config = value & 0x7fff;
-        break;
-    case 0x060:        /* BPCTR */
-        s->bt.control = value & 0x8f;
-        break;
-    case 0x064:        /* BPMCCFR */
-        s->bt.config = value & 0x7fff;
-        break;
-    case 0x080:        /* AMSCFR */
-        s->mixer = value & 0x0fff;
-        break;
-    case 0x084:        /* AMVCTR */
-        s->gain[0] = value & 0xffff;
-        break;
-    case 0x088:        /* AM1VCTR */
-        s->gain[1] = value & 0xff7f;
-        break;
-    case 0x08c:        /* AM2VCTR */
-        s->gain[2] = value & 0xff7f;
-        break;
-    case 0x090:        /* AM3VCTR */
-        s->gain[3] = value & 0xff7f;
-        break;
-    case 0x094:        /* ASTCTR */
-        s->att = value & 0xff;
-        break;
-
-    case 0x0b4:        /* ADWR */
-        s->codec.txbuf[s->codec.txlen ++] = value;
-        if (unlikely(s->codec.txlen == EAC_BUF_LEN ||
-                                s->codec.txlen == s->codec.txavail)) {
-            if (s->codec.txavail)
-                omap_eac_out_empty(s);
-            /* Discard what couldn't be written */
-            s->codec.txlen = 0;
-        }
-        break;
-
-    case 0x0bc:        /* AGCFR */
-        s->codec.config[0] = value & 0x07ff;
-        omap_eac_format_update(s);
-        break;
-    case 0x0c0:        /* AGCTR */
-        s->codec.config[1] = value & 0x780f;
-        omap_eac_format_update(s);
-        break;
-    case 0x0c4:        /* AGCFR2 */
-        s->codec.config[2] = value & 0x003f;
-        omap_eac_format_update(s);
-        break;
-    case 0x0c8:        /* AGCFR3 */
-        s->codec.config[3] = value & 0xffff;
-        omap_eac_format_update(s);
-        break;
-    case 0x0cc:        /* MBPDMACTR */
-    case 0x0d4:        /* MPDDMAWR */
-    case 0x0e0:        /* MPUDMAWR */
-    case 0x0e8:        /* BPDDMAWR */
-    case 0x0f0:        /* BPUDMAWR */
-        break;
-
-    case 0x104:        /* SYSCONFIG */
-        if (value & (1 << 1))                          /* SOFTRESET */
-            omap_eac_reset(s);
-        s->sysconfig = value & 0x31d;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_eac_ops = {
-    .read = omap_eac_read,
-    .write = omap_eac_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
-                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
-{
-    struct omap_eac_s *s = (struct omap_eac_s *)
-            g_malloc0(sizeof(struct omap_eac_s));
-
-    s->irq = irq;
-    s->codec.rxdrq = *drq ++;
-    s->codec.txdrq = *drq;
-    omap_eac_reset(s);
-
-    AUD_register_card("OMAP EAC", &s->codec.card);
-
-    memory_region_init_io(&s->iomem, &omap_eac_ops, s, "omap.eac",
-                          omap_l4_region_size(ta, 0));
-    omap_l4_attach(ta, 0, &s->iomem);
-
-    return s;
-}
-
-/* STI/XTI (emulation interface) console - reverse engineered only */
-struct omap_sti_s {
-    qemu_irq irq;
-    MemoryRegion iomem;
-    MemoryRegion iomem_fifo;
-    CharDriverState *chr;
-
-    uint32_t sysconfig;
-    uint32_t systest;
-    uint32_t irqst;
-    uint32_t irqen;
-    uint32_t clkcontrol;
-    uint32_t serial_config;
-};
-
-#define STI_TRACE_CONSOLE_CHANNEL      239
-#define STI_TRACE_CONTROL_CHANNEL      253
-
-static inline void omap_sti_interrupt_update(struct omap_sti_s *s)
-{
-    qemu_set_irq(s->irq, s->irqst & s->irqen);
-}
-
-static void omap_sti_reset(struct omap_sti_s *s)
-{
-    s->sysconfig = 0;
-    s->irqst = 0;
-    s->irqen = 0;
-    s->clkcontrol = 0;
-    s->serial_config = 0;
-
-    omap_sti_interrupt_update(s);
-}
-
-static uint64_t omap_sti_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00: /* STI_REVISION */
-        return 0x10;
-
-    case 0x10: /* STI_SYSCONFIG */
-        return s->sysconfig;
-
-    case 0x14: /* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
-        return 0x00;
-
-    case 0x18: /* STI_IRQSTATUS */
-        return s->irqst;
-
-    case 0x1c: /* STI_IRQSETEN / STI_IRQCLREN */
-        return s->irqen;
-
-    case 0x24: /* STI_ER / STI_DR / XTI_TRACESELECT */
-    case 0x28: /* STI_RX_DR / XTI_RXDATA */
-        /* TODO */
-        return 0;
-
-    case 0x2c: /* STI_CLK_CTRL / XTI_SCLKCRTL */
-        return s->clkcontrol;
-
-    case 0x30: /* STI_SERIAL_CFG / XTI_SCONFIG */
-        return s->serial_config;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_sti_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00: /* STI_REVISION */
-    case 0x14: /* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x10: /* STI_SYSCONFIG */
-        if (value & (1 << 1))                          /* SOFTRESET */
-            omap_sti_reset(s);
-        s->sysconfig = value & 0xfe;
-        break;
-
-    case 0x18: /* STI_IRQSTATUS */
-        s->irqst &= ~value;
-        omap_sti_interrupt_update(s);
-        break;
-
-    case 0x1c: /* STI_IRQSETEN / STI_IRQCLREN */
-        s->irqen = value & 0xffff;
-        omap_sti_interrupt_update(s);
-        break;
-
-    case 0x2c: /* STI_CLK_CTRL / XTI_SCLKCRTL */
-        s->clkcontrol = value & 0xff;
-        break;
-
-    case 0x30: /* STI_SERIAL_CFG / XTI_SCONFIG */
-        s->serial_config = value & 0xff;
-        break;
-
-    case 0x24: /* STI_ER / STI_DR / XTI_TRACESELECT */
-    case 0x28: /* STI_RX_DR / XTI_RXDATA */
-        /* TODO */
-        return;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_sti_ops = {
-    .read = omap_sti_read,
-    .write = omap_sti_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr,
-                                   unsigned size)
-{
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_sti_fifo_write(void *opaque, hwaddr addr,
-                                uint64_t value, unsigned size)
-{
-    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
-    int ch = addr >> 6;
-    uint8_t byte = value;
-
-    if (size != 1) {
-        return omap_badwidth_write8(opaque, addr, size);
-    }
-
-    if (ch == STI_TRACE_CONTROL_CHANNEL) {
-        /* Flush channel <i>value</i>.  */
-        qemu_chr_fe_write(s->chr, (const uint8_t *) "\r", 1);
-    } else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
-        if (value == 0xc0 || value == 0xc3) {
-            /* Open channel <i>ch</i>.  */
-        } else if (value == 0x00)
-            qemu_chr_fe_write(s->chr, (const uint8_t *) "\n", 1);
-        else
-            qemu_chr_fe_write(s->chr, &byte, 1);
-    }
-}
-
-static const MemoryRegionOps omap_sti_fifo_ops = {
-    .read = omap_sti_fifo_read,
-    .write = omap_sti_fifo_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
-                MemoryRegion *sysmem,
-                hwaddr channel_base, qemu_irq irq, omap_clk clk,
-                CharDriverState *chr)
-{
-    struct omap_sti_s *s = (struct omap_sti_s *)
-            g_malloc0(sizeof(struct omap_sti_s));
-
-    s->irq = irq;
-    omap_sti_reset(s);
-
-    s->chr = chr ?: qemu_chr_new("null", "null", NULL);
-
-    memory_region_init_io(&s->iomem, &omap_sti_ops, s, "omap.sti",
-                          omap_l4_region_size(ta, 0));
-    omap_l4_attach(ta, 0, &s->iomem);
-
-    memory_region_init_io(&s->iomem_fifo, &omap_sti_fifo_ops, s,
-                          "omap.sti.fifo", 0x10000);
-    memory_region_add_subregion(sysmem, channel_base, &s->iomem_fifo);
-
-    return s;
-}
-
-/* L4 Interconnect */
-#define L4TA(n)                (n)
-#define L4TAO(n)       ((n) + 39)
-
-static const struct omap_l4_region_s omap_l4_region[125] = {
-    [  1] = { 0x40800,  0x800, 32          }, /* Initiator agent */
-    [  2] = { 0x41000, 0x1000, 32          }, /* Link agent */
-    [  0] = { 0x40000,  0x800, 32          }, /* Address and protection */
-    [  3] = { 0x00000, 0x1000, 32 | 16 | 8 }, /* System Control and Pinout */
-    [  4] = { 0x01000, 0x1000, 32 | 16 | 8 }, /* L4TAO1 */
-    [  5] = { 0x04000, 0x1000, 32 | 16     }, /* 32K Timer */
-    [  6] = { 0x05000, 0x1000, 32 | 16 | 8 }, /* L4TAO2 */
-    [  7] = { 0x08000,  0x800, 32          }, /* PRCM Region A */
-    [  8] = { 0x08800,  0x800, 32          }, /* PRCM Region B */
-    [  9] = { 0x09000, 0x1000, 32 | 16 | 8 }, /* L4TAO */
-    [ 10] = { 0x12000, 0x1000, 32 | 16 | 8 }, /* Test (BCM) */
-    [ 11] = { 0x13000, 0x1000, 32 | 16 | 8 }, /* L4TA1 */
-    [ 12] = { 0x14000, 0x1000, 32          }, /* Test/emulation (TAP) */
-    [ 13] = { 0x15000, 0x1000, 32 | 16 | 8 }, /* L4TA2 */
-    [ 14] = { 0x18000, 0x1000, 32 | 16 | 8 }, /* GPIO1 */
-    [ 16] = { 0x1a000, 0x1000, 32 | 16 | 8 }, /* GPIO2 */
-    [ 18] = { 0x1c000, 0x1000, 32 | 16 | 8 }, /* GPIO3 */
-    [ 19] = { 0x1e000, 0x1000, 32 | 16 | 8 }, /* GPIO4 */
-    [ 15] = { 0x19000, 0x1000, 32 | 16 | 8 }, /* Quad GPIO TOP */
-    [ 17] = { 0x1b000, 0x1000, 32 | 16 | 8 }, /* L4TA3 */
-    [ 20] = { 0x20000, 0x1000, 32 | 16 | 8 }, /* WD Timer 1 (Secure) */
-    [ 22] = { 0x22000, 0x1000, 32 | 16 | 8 }, /* WD Timer 2 (OMAP) */
-    [ 21] = { 0x21000, 0x1000, 32 | 16 | 8 }, /* Dual WD timer TOP */
-    [ 23] = { 0x23000, 0x1000, 32 | 16 | 8 }, /* L4TA4 */
-    [ 24] = { 0x28000, 0x1000, 32 | 16 | 8 }, /* GP Timer 1 */
-    [ 25] = { 0x29000, 0x1000, 32 | 16 | 8 }, /* L4TA7 */
-    [ 26] = { 0x48000, 0x2000, 32 | 16 | 8 }, /* Emulation (ARM11ETB) */
-    [ 27] = { 0x4a000, 0x1000, 32 | 16 | 8 }, /* L4TA9 */
-    [ 28] = { 0x50000,  0x400, 32 | 16 | 8 }, /* Display top */
-    [ 29] = { 0x50400,  0x400, 32 | 16 | 8 }, /* Display control */
-    [ 30] = { 0x50800,  0x400, 32 | 16 | 8 }, /* Display RFBI */
-    [ 31] = { 0x50c00,  0x400, 32 | 16 | 8 }, /* Display encoder */
-    [ 32] = { 0x51000, 0x1000, 32 | 16 | 8 }, /* L4TA10 */
-    [ 33] = { 0x52000,  0x400, 32 | 16 | 8 }, /* Camera top */
-    [ 34] = { 0x52400,  0x400, 32 | 16 | 8 }, /* Camera core */
-    [ 35] = { 0x52800,  0x400, 32 | 16 | 8 }, /* Camera DMA */
-    [ 36] = { 0x52c00,  0x400, 32 | 16 | 8 }, /* Camera MMU */
-    [ 37] = { 0x53000, 0x1000, 32 | 16 | 8 }, /* L4TA11 */
-    [ 38] = { 0x56000, 0x1000, 32 | 16 | 8 }, /* sDMA */
-    [ 39] = { 0x57000, 0x1000, 32 | 16 | 8 }, /* L4TA12 */
-    [ 40] = { 0x58000, 0x1000, 32 | 16 | 8 }, /* SSI top */
-    [ 41] = { 0x59000, 0x1000, 32 | 16 | 8 }, /* SSI GDD */
-    [ 42] = { 0x5a000, 0x1000, 32 | 16 | 8 }, /* SSI Port1 */
-    [ 43] = { 0x5b000, 0x1000, 32 | 16 | 8 }, /* SSI Port2 */
-    [ 44] = { 0x5c000, 0x1000, 32 | 16 | 8 }, /* L4TA13 */
-    [ 45] = { 0x5e000, 0x1000, 32 | 16 | 8 }, /* USB OTG */
-    [ 46] = { 0x5f000, 0x1000, 32 | 16 | 8 }, /* L4TAO4 */
-    [ 47] = { 0x60000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER1SDRC) */
-    [ 48] = { 0x61000, 0x1000, 32 | 16 | 8 }, /* L4TA14 */
-    [ 49] = { 0x62000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER2GPMC) */
-    [ 50] = { 0x63000, 0x1000, 32 | 16 | 8 }, /* L4TA15 */
-    [ 51] = { 0x64000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER3OCM) */
-    [ 52] = { 0x65000, 0x1000, 32 | 16 | 8 }, /* L4TA16 */
-    [ 53] = { 0x66000,  0x300, 32 | 16 | 8 }, /* Emulation (WIN_TRACER4L4) */
-    [ 54] = { 0x67000, 0x1000, 32 | 16 | 8 }, /* L4TA17 */
-    [ 55] = { 0x68000, 0x1000, 32 | 16 | 8 }, /* Emulation (XTI) */
-    [ 56] = { 0x69000, 0x1000, 32 | 16 | 8 }, /* L4TA18 */
-    [ 57] = { 0x6a000, 0x1000,      16 | 8 }, /* UART1 */
-    [ 58] = { 0x6b000, 0x1000, 32 | 16 | 8 }, /* L4TA19 */
-    [ 59] = { 0x6c000, 0x1000,      16 | 8 }, /* UART2 */
-    [ 60] = { 0x6d000, 0x1000, 32 | 16 | 8 }, /* L4TA20 */
-    [ 61] = { 0x6e000, 0x1000,      16 | 8 }, /* UART3 */
-    [ 62] = { 0x6f000, 0x1000, 32 | 16 | 8 }, /* L4TA21 */
-    [ 63] = { 0x70000, 0x1000,      16     }, /* I2C1 */
-    [ 64] = { 0x71000, 0x1000, 32 | 16 | 8 }, /* L4TAO5 */
-    [ 65] = { 0x72000, 0x1000,      16     }, /* I2C2 */
-    [ 66] = { 0x73000, 0x1000, 32 | 16 | 8 }, /* L4TAO6 */
-    [ 67] = { 0x74000, 0x1000,      16     }, /* McBSP1 */
-    [ 68] = { 0x75000, 0x1000, 32 | 16 | 8 }, /* L4TAO7 */
-    [ 69] = { 0x76000, 0x1000,      16     }, /* McBSP2 */
-    [ 70] = { 0x77000, 0x1000, 32 | 16 | 8 }, /* L4TAO8 */
-    [ 71] = { 0x24000, 0x1000, 32 | 16 | 8 }, /* WD Timer 3 (DSP) */
-    [ 72] = { 0x25000, 0x1000, 32 | 16 | 8 }, /* L4TA5 */
-    [ 73] = { 0x26000, 0x1000, 32 | 16 | 8 }, /* WD Timer 4 (IVA) */
-    [ 74] = { 0x27000, 0x1000, 32 | 16 | 8 }, /* L4TA6 */
-    [ 75] = { 0x2a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 2 */
-    [ 76] = { 0x2b000, 0x1000, 32 | 16 | 8 }, /* L4TA8 */
-    [ 77] = { 0x78000, 0x1000, 32 | 16 | 8 }, /* GP Timer 3 */
-    [ 78] = { 0x79000, 0x1000, 32 | 16 | 8 }, /* L4TA22 */
-    [ 79] = { 0x7a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 4 */
-    [ 80] = { 0x7b000, 0x1000, 32 | 16 | 8 }, /* L4TA23 */
-    [ 81] = { 0x7c000, 0x1000, 32 | 16 | 8 }, /* GP Timer 5 */
-    [ 82] = { 0x7d000, 0x1000, 32 | 16 | 8 }, /* L4TA24 */
-    [ 83] = { 0x7e000, 0x1000, 32 | 16 | 8 }, /* GP Timer 6 */
-    [ 84] = { 0x7f000, 0x1000, 32 | 16 | 8 }, /* L4TA25 */
-    [ 85] = { 0x80000, 0x1000, 32 | 16 | 8 }, /* GP Timer 7 */
-    [ 86] = { 0x81000, 0x1000, 32 | 16 | 8 }, /* L4TA26 */
-    [ 87] = { 0x82000, 0x1000, 32 | 16 | 8 }, /* GP Timer 8 */
-    [ 88] = { 0x83000, 0x1000, 32 | 16 | 8 }, /* L4TA27 */
-    [ 89] = { 0x84000, 0x1000, 32 | 16 | 8 }, /* GP Timer 9 */
-    [ 90] = { 0x85000, 0x1000, 32 | 16 | 8 }, /* L4TA28 */
-    [ 91] = { 0x86000, 0x1000, 32 | 16 | 8 }, /* GP Timer 10 */
-    [ 92] = { 0x87000, 0x1000, 32 | 16 | 8 }, /* L4TA29 */
-    [ 93] = { 0x88000, 0x1000, 32 | 16 | 8 }, /* GP Timer 11 */
-    [ 94] = { 0x89000, 0x1000, 32 | 16 | 8 }, /* L4TA30 */
-    [ 95] = { 0x8a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 12 */
-    [ 96] = { 0x8b000, 0x1000, 32 | 16 | 8 }, /* L4TA31 */
-    [ 97] = { 0x90000, 0x1000,      16     }, /* EAC */
-    [ 98] = { 0x91000, 0x1000, 32 | 16 | 8 }, /* L4TA32 */
-    [ 99] = { 0x92000, 0x1000,      16     }, /* FAC */
-    [100] = { 0x93000, 0x1000, 32 | 16 | 8 }, /* L4TA33 */
-    [101] = { 0x94000, 0x1000, 32 | 16 | 8 }, /* IPC (MAILBOX) */
-    [102] = { 0x95000, 0x1000, 32 | 16 | 8 }, /* L4TA34 */
-    [103] = { 0x98000, 0x1000, 32 | 16 | 8 }, /* SPI1 */
-    [104] = { 0x99000, 0x1000, 32 | 16 | 8 }, /* L4TA35 */
-    [105] = { 0x9a000, 0x1000, 32 | 16 | 8 }, /* SPI2 */
-    [106] = { 0x9b000, 0x1000, 32 | 16 | 8 }, /* L4TA36 */
-    [107] = { 0x9c000, 0x1000,      16 | 8 }, /* MMC SDIO */
-    [108] = { 0x9d000, 0x1000, 32 | 16 | 8 }, /* L4TAO9 */
-    [109] = { 0x9e000, 0x1000, 32 | 16 | 8 }, /* MS_PRO */
-    [110] = { 0x9f000, 0x1000, 32 | 16 | 8 }, /* L4TAO10 */
-    [111] = { 0xa0000, 0x1000, 32          }, /* RNG */
-    [112] = { 0xa1000, 0x1000, 32 | 16 | 8 }, /* L4TAO11 */
-    [113] = { 0xa2000, 0x1000, 32          }, /* DES3DES */
-    [114] = { 0xa3000, 0x1000, 32 | 16 | 8 }, /* L4TAO12 */
-    [115] = { 0xa4000, 0x1000, 32          }, /* SHA1MD5 */
-    [116] = { 0xa5000, 0x1000, 32 | 16 | 8 }, /* L4TAO13 */
-    [117] = { 0xa6000, 0x1000, 32          }, /* AES */
-    [118] = { 0xa7000, 0x1000, 32 | 16 | 8 }, /* L4TA37 */
-    [119] = { 0xa8000, 0x2000, 32          }, /* PKA */
-    [120] = { 0xaa000, 0x1000, 32 | 16 | 8 }, /* L4TA38 */
-    [121] = { 0xb0000, 0x1000, 32          }, /* MG */
-    [122] = { 0xb1000, 0x1000, 32 | 16 | 8 },
-    [123] = { 0xb2000, 0x1000, 32          }, /* HDQ/1-Wire */
-    [124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */
-};
-
-static const struct omap_l4_agent_info_s omap_l4_agent_info[54] = {
-    { 0,           0, 3, 2 }, /* L4IA initiatior agent */
-    { L4TAO(1),    3, 2, 1 }, /* Control and pinout module */
-    { L4TAO(2),    5, 2, 1 }, /* 32K timer */
-    { L4TAO(3),    7, 3, 2 }, /* PRCM */
-    { L4TA(1),    10, 2, 1 }, /* BCM */
-    { L4TA(2),    12, 2, 1 }, /* Test JTAG */
-    { L4TA(3),    14, 6, 3 }, /* Quad GPIO */
-    { L4TA(4),    20, 4, 3 }, /* WD timer 1/2 */
-    { L4TA(7),    24, 2, 1 }, /* GP timer 1 */
-    { L4TA(9),    26, 2, 1 }, /* ATM11 ETB */
-    { L4TA(10),   28, 5, 4 }, /* Display subsystem */
-    { L4TA(11),   33, 5, 4 }, /* Camera subsystem */
-    { L4TA(12),   38, 2, 1 }, /* sDMA */
-    { L4TA(13),   40, 5, 4 }, /* SSI */
-    { L4TAO(4),   45, 2, 1 }, /* USB */
-    { L4TA(14),   47, 2, 1 }, /* Win Tracer1 */
-    { L4TA(15),   49, 2, 1 }, /* Win Tracer2 */
-    { L4TA(16),   51, 2, 1 }, /* Win Tracer3 */
-    { L4TA(17),   53, 2, 1 }, /* Win Tracer4 */
-    { L4TA(18),   55, 2, 1 }, /* XTI */
-    { L4TA(19),   57, 2, 1 }, /* UART1 */
-    { L4TA(20),   59, 2, 1 }, /* UART2 */
-    { L4TA(21),   61, 2, 1 }, /* UART3 */
-    { L4TAO(5),   63, 2, 1 }, /* I2C1 */
-    { L4TAO(6),   65, 2, 1 }, /* I2C2 */
-    { L4TAO(7),   67, 2, 1 }, /* McBSP1 */
-    { L4TAO(8),   69, 2, 1 }, /* McBSP2 */
-    { L4TA(5),    71, 2, 1 }, /* WD Timer 3 (DSP) */
-    { L4TA(6),    73, 2, 1 }, /* WD Timer 4 (IVA) */
-    { L4TA(8),    75, 2, 1 }, /* GP Timer 2 */
-    { L4TA(22),   77, 2, 1 }, /* GP Timer 3 */
-    { L4TA(23),   79, 2, 1 }, /* GP Timer 4 */
-    { L4TA(24),   81, 2, 1 }, /* GP Timer 5 */
-    { L4TA(25),   83, 2, 1 }, /* GP Timer 6 */
-    { L4TA(26),   85, 2, 1 }, /* GP Timer 7 */
-    { L4TA(27),   87, 2, 1 }, /* GP Timer 8 */
-    { L4TA(28),   89, 2, 1 }, /* GP Timer 9 */
-    { L4TA(29),   91, 2, 1 }, /* GP Timer 10 */
-    { L4TA(30),   93, 2, 1 }, /* GP Timer 11 */
-    { L4TA(31),   95, 2, 1 }, /* GP Timer 12 */
-    { L4TA(32),   97, 2, 1 }, /* EAC */
-    { L4TA(33),   99, 2, 1 }, /* FAC */
-    { L4TA(34),  101, 2, 1 }, /* IPC */
-    { L4TA(35),  103, 2, 1 }, /* SPI1 */
-    { L4TA(36),  105, 2, 1 }, /* SPI2 */
-    { L4TAO(9),  107, 2, 1 }, /* MMC SDIO */
-    { L4TAO(10), 109, 2, 1 },
-    { L4TAO(11), 111, 2, 1 }, /* RNG */
-    { L4TAO(12), 113, 2, 1 }, /* DES3DES */
-    { L4TAO(13), 115, 2, 1 }, /* SHA1MD5 */
-    { L4TA(37),  117, 2, 1 }, /* AES */
-    { L4TA(38),  119, 2, 1 }, /* PKA */
-    { -1,        121, 2, 1 },
-    { L4TA(39),  123, 2, 1 }, /* HDQ/1-Wire */
-};
-
-#define omap_l4ta(bus, cs)     \
-    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TA(cs))
-#define omap_l4tao(bus, cs)    \
-    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TAO(cs))
-
-/* Power, Reset, and Clock Management */
-struct omap_prcm_s {
-    qemu_irq irq[3];
-    struct omap_mpu_state_s *mpu;
-    MemoryRegion iomem0;
-    MemoryRegion iomem1;
-
-    uint32_t irqst[3];
-    uint32_t irqen[3];
-
-    uint32_t sysconfig;
-    uint32_t voltctrl;
-    uint32_t scratch[20];
-
-    uint32_t clksrc[1];
-    uint32_t clkout[1];
-    uint32_t clkemul[1];
-    uint32_t clkpol[1];
-    uint32_t clksel[8];
-    uint32_t clken[12];
-    uint32_t clkctrl[4];
-    uint32_t clkidle[7];
-    uint32_t setuptime[2];
-
-    uint32_t wkup[3];
-    uint32_t wken[3];
-    uint32_t wkst[3];
-    uint32_t rst[4];
-    uint32_t rstctrl[1];
-    uint32_t power[4];
-    uint32_t rsttime_wkup;
-
-    uint32_t ev;
-    uint32_t evtime[2];
-
-    int dpll_lock, apll_lock[2];
-};
-
-static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
-{
-    qemu_set_irq(s->irq[dom], s->irqst[dom] & s->irqen[dom]);
-    /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */
-}
-
-static uint64_t omap_prcm_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
-    uint32_t ret;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x000:        /* PRCM_REVISION */
-        return 0x10;
-
-    case 0x010:        /* PRCM_SYSCONFIG */
-        return s->sysconfig;
-
-    case 0x018:        /* PRCM_IRQSTATUS_MPU */
-        return s->irqst[0];
-
-    case 0x01c:        /* PRCM_IRQENABLE_MPU */
-        return s->irqen[0];
-
-    case 0x050:        /* PRCM_VOLTCTRL */
-        return s->voltctrl;
-    case 0x054:        /* PRCM_VOLTST */
-        return s->voltctrl & 3;
-
-    case 0x060:        /* PRCM_CLKSRC_CTRL */
-        return s->clksrc[0];
-    case 0x070:        /* PRCM_CLKOUT_CTRL */
-        return s->clkout[0];
-    case 0x078:        /* PRCM_CLKEMUL_CTRL */
-        return s->clkemul[0];
-    case 0x080:        /* PRCM_CLKCFG_CTRL */
-    case 0x084:        /* PRCM_CLKCFG_STATUS */
-        return 0;
-
-    case 0x090:        /* PRCM_VOLTSETUP */
-        return s->setuptime[0];
-
-    case 0x094:        /* PRCM_CLKSSETUP */
-        return s->setuptime[1];
-
-    case 0x098:        /* PRCM_POLCTRL */
-        return s->clkpol[0];
-
-    case 0x0b0:        /* GENERAL_PURPOSE1 */
-    case 0x0b4:        /* GENERAL_PURPOSE2 */
-    case 0x0b8:        /* GENERAL_PURPOSE3 */
-    case 0x0bc:        /* GENERAL_PURPOSE4 */
-    case 0x0c0:        /* GENERAL_PURPOSE5 */
-    case 0x0c4:        /* GENERAL_PURPOSE6 */
-    case 0x0c8:        /* GENERAL_PURPOSE7 */
-    case 0x0cc:        /* GENERAL_PURPOSE8 */
-    case 0x0d0:        /* GENERAL_PURPOSE9 */
-    case 0x0d4:        /* GENERAL_PURPOSE10 */
-    case 0x0d8:        /* GENERAL_PURPOSE11 */
-    case 0x0dc:        /* GENERAL_PURPOSE12 */
-    case 0x0e0:        /* GENERAL_PURPOSE13 */
-    case 0x0e4:        /* GENERAL_PURPOSE14 */
-    case 0x0e8:        /* GENERAL_PURPOSE15 */
-    case 0x0ec:        /* GENERAL_PURPOSE16 */
-    case 0x0f0:        /* GENERAL_PURPOSE17 */
-    case 0x0f4:        /* GENERAL_PURPOSE18 */
-    case 0x0f8:        /* GENERAL_PURPOSE19 */
-    case 0x0fc:        /* GENERAL_PURPOSE20 */
-        return s->scratch[(addr - 0xb0) >> 2];
-
-    case 0x140:        /* CM_CLKSEL_MPU */
-        return s->clksel[0];
-    case 0x148:        /* CM_CLKSTCTRL_MPU */
-        return s->clkctrl[0];
-
-    case 0x158:        /* RM_RSTST_MPU */
-        return s->rst[0];
-    case 0x1c8:        /* PM_WKDEP_MPU */
-        return s->wkup[0];
-    case 0x1d4:        /* PM_EVGENCTRL_MPU */
-        return s->ev;
-    case 0x1d8:        /* PM_EVEGENONTIM_MPU */
-        return s->evtime[0];
-    case 0x1dc:        /* PM_EVEGENOFFTIM_MPU */
-        return s->evtime[1];
-    case 0x1e0:        /* PM_PWSTCTRL_MPU */
-        return s->power[0];
-    case 0x1e4:        /* PM_PWSTST_MPU */
-        return 0;
-
-    case 0x200:        /* CM_FCLKEN1_CORE */
-        return s->clken[0];
-    case 0x204:        /* CM_FCLKEN2_CORE */
-        return s->clken[1];
-    case 0x210:        /* CM_ICLKEN1_CORE */
-        return s->clken[2];
-    case 0x214:        /* CM_ICLKEN2_CORE */
-        return s->clken[3];
-    case 0x21c:        /* CM_ICLKEN4_CORE */
-        return s->clken[4];
-
-    case 0x220:        /* CM_IDLEST1_CORE */
-        /* TODO: check the actual iclk status */
-        return 0x7ffffff9;
-    case 0x224:        /* CM_IDLEST2_CORE */
-        /* TODO: check the actual iclk status */
-        return 0x00000007;
-    case 0x22c:        /* CM_IDLEST4_CORE */
-        /* TODO: check the actual iclk status */
-        return 0x0000001f;
-
-    case 0x230:        /* CM_AUTOIDLE1_CORE */
-        return s->clkidle[0];
-    case 0x234:        /* CM_AUTOIDLE2_CORE */
-        return s->clkidle[1];
-    case 0x238:        /* CM_AUTOIDLE3_CORE */
-        return s->clkidle[2];
-    case 0x23c:        /* CM_AUTOIDLE4_CORE */
-        return s->clkidle[3];
-
-    case 0x240:        /* CM_CLKSEL1_CORE */
-        return s->clksel[1];
-    case 0x244:        /* CM_CLKSEL2_CORE */
-        return s->clksel[2];
-
-    case 0x248:        /* CM_CLKSTCTRL_CORE */
-        return s->clkctrl[1];
-
-    case 0x2a0:        /* PM_WKEN1_CORE */
-        return s->wken[0];
-    case 0x2a4:        /* PM_WKEN2_CORE */
-        return s->wken[1];
-
-    case 0x2b0:        /* PM_WKST1_CORE */
-        return s->wkst[0];
-    case 0x2b4:        /* PM_WKST2_CORE */
-        return s->wkst[1];
-    case 0x2c8:        /* PM_WKDEP_CORE */
-        return 0x1e;
-
-    case 0x2e0:        /* PM_PWSTCTRL_CORE */
-        return s->power[1];
-    case 0x2e4:        /* PM_PWSTST_CORE */
-        return 0x000030 | (s->power[1] & 0xfc00);
-
-    case 0x300:        /* CM_FCLKEN_GFX */
-        return s->clken[5];
-    case 0x310:        /* CM_ICLKEN_GFX */
-        return s->clken[6];
-    case 0x320:        /* CM_IDLEST_GFX */
-        /* TODO: check the actual iclk status */
-        return 0x00000001;
-    case 0x340:        /* CM_CLKSEL_GFX */
-        return s->clksel[3];
-    case 0x348:        /* CM_CLKSTCTRL_GFX */
-        return s->clkctrl[2];
-    case 0x350:        /* RM_RSTCTRL_GFX */
-        return s->rstctrl[0];
-    case 0x358:        /* RM_RSTST_GFX */
-        return s->rst[1];
-    case 0x3c8:        /* PM_WKDEP_GFX */
-        return s->wkup[1];
-
-    case 0x3e0:        /* PM_PWSTCTRL_GFX */
-        return s->power[2];
-    case 0x3e4:        /* PM_PWSTST_GFX */
-        return s->power[2] & 3;
-
-    case 0x400:        /* CM_FCLKEN_WKUP */
-        return s->clken[7];
-    case 0x410:        /* CM_ICLKEN_WKUP */
-        return s->clken[8];
-    case 0x420:        /* CM_IDLEST_WKUP */
-        /* TODO: check the actual iclk status */
-        return 0x0000003f;
-    case 0x430:        /* CM_AUTOIDLE_WKUP */
-        return s->clkidle[4];
-    case 0x440:        /* CM_CLKSEL_WKUP */
-        return s->clksel[4];
-    case 0x450:        /* RM_RSTCTRL_WKUP */
-        return 0;
-    case 0x454:        /* RM_RSTTIME_WKUP */
-        return s->rsttime_wkup;
-    case 0x458:        /* RM_RSTST_WKUP */
-        return s->rst[2];
-    case 0x4a0:        /* PM_WKEN_WKUP */
-        return s->wken[2];
-    case 0x4b0:        /* PM_WKST_WKUP */
-        return s->wkst[2];
-
-    case 0x500:        /* CM_CLKEN_PLL */
-        return s->clken[9];
-    case 0x520:        /* CM_IDLEST_CKGEN */
-        ret = 0x0000070 | (s->apll_lock[0] << 9) | (s->apll_lock[1] << 8);
-        if (!(s->clksel[6] & 3))
-            /* Core uses 32-kHz clock */
-            ret |= 3 << 0;
-        else if (!s->dpll_lock)
-            /* DPLL not locked, core uses ref_clk */
-            ret |= 1 << 0;
-        else
-            /* Core uses DPLL */
-            ret |= 2 << 0;
-        return ret;
-    case 0x530:        /* CM_AUTOIDLE_PLL */
-        return s->clkidle[5];
-    case 0x540:        /* CM_CLKSEL1_PLL */
-        return s->clksel[5];
-    case 0x544:        /* CM_CLKSEL2_PLL */
-        return s->clksel[6];
-
-    case 0x800:        /* CM_FCLKEN_DSP */
-        return s->clken[10];
-    case 0x810:        /* CM_ICLKEN_DSP */
-        return s->clken[11];
-    case 0x820:        /* CM_IDLEST_DSP */
-        /* TODO: check the actual iclk status */
-        return 0x00000103;
-    case 0x830:        /* CM_AUTOIDLE_DSP */
-        return s->clkidle[6];
-    case 0x840:        /* CM_CLKSEL_DSP */
-        return s->clksel[7];
-    case 0x848:        /* CM_CLKSTCTRL_DSP */
-        return s->clkctrl[3];
-    case 0x850:        /* RM_RSTCTRL_DSP */
-        return 0;
-    case 0x858:        /* RM_RSTST_DSP */
-        return s->rst[3];
-    case 0x8c8:        /* PM_WKDEP_DSP */
-        return s->wkup[2];
-    case 0x8e0:        /* PM_PWSTCTRL_DSP */
-        return s->power[3];
-    case 0x8e4:        /* PM_PWSTST_DSP */
-        return 0x008030 | (s->power[3] & 0x3003);
-
-    case 0x8f0:        /* PRCM_IRQSTATUS_DSP */
-        return s->irqst[1];
-    case 0x8f4:        /* PRCM_IRQENABLE_DSP */
-        return s->irqen[1];
-
-    case 0x8f8:        /* PRCM_IRQSTATUS_IVA */
-        return s->irqst[2];
-    case 0x8fc:        /* PRCM_IRQENABLE_IVA */
-        return s->irqen[2];
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_prcm_apll_update(struct omap_prcm_s *s)
-{
-    int mode[2];
-
-    mode[0] = (s->clken[9] >> 6) & 3;
-    s->apll_lock[0] = (mode[0] == 3);
-    mode[1] = (s->clken[9] >> 2) & 3;
-    s->apll_lock[1] = (mode[1] == 3);
-    /* TODO: update clocks */
-
-    if (mode[0] == 1 || mode[0] == 2 || mode[1] == 1 || mode[1] == 2)
-        fprintf(stderr, "%s: bad EN_54M_PLL or bad EN_96M_PLL\n",
-                        __FUNCTION__);
-}
-
-static void omap_prcm_dpll_update(struct omap_prcm_s *s)
-{
-    omap_clk dpll = omap_findclk(s->mpu, "dpll");
-    omap_clk dpll_x2 = omap_findclk(s->mpu, "dpll");
-    omap_clk core = omap_findclk(s->mpu, "core_clk");
-    int mode = (s->clken[9] >> 0) & 3;
-    int mult, div;
-
-    mult = (s->clksel[5] >> 12) & 0x3ff;
-    div = (s->clksel[5] >> 8) & 0xf;
-    if (mult == 0 || mult == 1)
-        mode = 1;      /* Bypass */
-
-    s->dpll_lock = 0;
-    switch (mode) {
-    case 0:
-        fprintf(stderr, "%s: bad EN_DPLL\n", __FUNCTION__);
-        break;
-    case 1:    /* Low-power bypass mode (Default) */
-    case 2:    /* Fast-relock bypass mode */
-        omap_clk_setrate(dpll, 1, 1);
-        omap_clk_setrate(dpll_x2, 1, 1);
-        break;
-    case 3:    /* Lock mode */
-        s->dpll_lock = 1; /* After 20 FINT cycles (ref_clk / (div + 1)).  */
-
-        omap_clk_setrate(dpll, div + 1, mult);
-        omap_clk_setrate(dpll_x2, div + 1, mult * 2);
-        break;
-    }
-
-    switch ((s->clksel[6] >> 0) & 3) {
-    case 0:
-        omap_clk_reparent(core, omap_findclk(s->mpu, "clk32-kHz"));
-        break;
-    case 1:
-        omap_clk_reparent(core, dpll);
-        break;
-    case 2:
-        /* Default */
-        omap_clk_reparent(core, dpll_x2);
-        break;
-    case 3:
-        fprintf(stderr, "%s: bad CORE_CLK_SRC\n", __FUNCTION__);
-        break;
-    }
-}
-
-static void omap_prcm_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x000:        /* PRCM_REVISION */
-    case 0x054:        /* PRCM_VOLTST */
-    case 0x084:        /* PRCM_CLKCFG_STATUS */
-    case 0x1e4:        /* PM_PWSTST_MPU */
-    case 0x220:        /* CM_IDLEST1_CORE */
-    case 0x224:        /* CM_IDLEST2_CORE */
-    case 0x22c:        /* CM_IDLEST4_CORE */
-    case 0x2c8:        /* PM_WKDEP_CORE */
-    case 0x2e4:        /* PM_PWSTST_CORE */
-    case 0x320:        /* CM_IDLEST_GFX */
-    case 0x3e4:        /* PM_PWSTST_GFX */
-    case 0x420:        /* CM_IDLEST_WKUP */
-    case 0x520:        /* CM_IDLEST_CKGEN */
-    case 0x820:        /* CM_IDLEST_DSP */
-    case 0x8e4:        /* PM_PWSTST_DSP */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x010:        /* PRCM_SYSCONFIG */
-        s->sysconfig = value & 1;
-        break;
-
-    case 0x018:        /* PRCM_IRQSTATUS_MPU */
-        s->irqst[0] &= ~value;
-        omap_prcm_int_update(s, 0);
-        break;
-    case 0x01c:        /* PRCM_IRQENABLE_MPU */
-        s->irqen[0] = value & 0x3f;
-        omap_prcm_int_update(s, 0);
-        break;
-
-    case 0x050:        /* PRCM_VOLTCTRL */
-        s->voltctrl = value & 0xf1c3;
-        break;
-
-    case 0x060:        /* PRCM_CLKSRC_CTRL */
-        s->clksrc[0] = value & 0xdb;
-        /* TODO update clocks */
-        break;
-
-    case 0x070:        /* PRCM_CLKOUT_CTRL */
-        s->clkout[0] = value & 0xbbbb;
-        /* TODO update clocks */
-        break;
-
-    case 0x078:        /* PRCM_CLKEMUL_CTRL */
-        s->clkemul[0] = value & 1;
-        /* TODO update clocks */
-        break;
-
-    case 0x080:        /* PRCM_CLKCFG_CTRL */
-        break;
-
-    case 0x090:        /* PRCM_VOLTSETUP */
-        s->setuptime[0] = value & 0xffff;
-        break;
-    case 0x094:        /* PRCM_CLKSSETUP */
-        s->setuptime[1] = value & 0xffff;
-        break;
-
-    case 0x098:        /* PRCM_POLCTRL */
-        s->clkpol[0] = value & 0x701;
-        break;
-
-    case 0x0b0:        /* GENERAL_PURPOSE1 */
-    case 0x0b4:        /* GENERAL_PURPOSE2 */
-    case 0x0b8:        /* GENERAL_PURPOSE3 */
-    case 0x0bc:        /* GENERAL_PURPOSE4 */
-    case 0x0c0:        /* GENERAL_PURPOSE5 */
-    case 0x0c4:        /* GENERAL_PURPOSE6 */
-    case 0x0c8:        /* GENERAL_PURPOSE7 */
-    case 0x0cc:        /* GENERAL_PURPOSE8 */
-    case 0x0d0:        /* GENERAL_PURPOSE9 */
-    case 0x0d4:        /* GENERAL_PURPOSE10 */
-    case 0x0d8:        /* GENERAL_PURPOSE11 */
-    case 0x0dc:        /* GENERAL_PURPOSE12 */
-    case 0x0e0:        /* GENERAL_PURPOSE13 */
-    case 0x0e4:        /* GENERAL_PURPOSE14 */
-    case 0x0e8:        /* GENERAL_PURPOSE15 */
-    case 0x0ec:        /* GENERAL_PURPOSE16 */
-    case 0x0f0:        /* GENERAL_PURPOSE17 */
-    case 0x0f4:        /* GENERAL_PURPOSE18 */
-    case 0x0f8:        /* GENERAL_PURPOSE19 */
-    case 0x0fc:        /* GENERAL_PURPOSE20 */
-        s->scratch[(addr - 0xb0) >> 2] = value;
-        break;
-
-    case 0x140:        /* CM_CLKSEL_MPU */
-        s->clksel[0] = value & 0x1f;
-        /* TODO update clocks */
-        break;
-    case 0x148:        /* CM_CLKSTCTRL_MPU */
-        s->clkctrl[0] = value & 0x1f;
-        break;
-
-    case 0x158:        /* RM_RSTST_MPU */
-        s->rst[0] &= ~value;
-        break;
-    case 0x1c8:        /* PM_WKDEP_MPU */
-        s->wkup[0] = value & 0x15;
-        break;
-
-    case 0x1d4:        /* PM_EVGENCTRL_MPU */
-        s->ev = value & 0x1f;
-        break;
-    case 0x1d8:        /* PM_EVEGENONTIM_MPU */
-        s->evtime[0] = value;
-        break;
-    case 0x1dc:        /* PM_EVEGENOFFTIM_MPU */
-        s->evtime[1] = value;
-        break;
-
-    case 0x1e0:        /* PM_PWSTCTRL_MPU */
-        s->power[0] = value & 0xc0f;
-        break;
-
-    case 0x200:        /* CM_FCLKEN1_CORE */
-        s->clken[0] = value & 0xbfffffff;
-        /* TODO update clocks */
-        /* The EN_EAC bit only gets/puts func_96m_clk.  */
-        break;
-    case 0x204:        /* CM_FCLKEN2_CORE */
-        s->clken[1] = value & 0x00000007;
-        /* TODO update clocks */
-        break;
-    case 0x210:        /* CM_ICLKEN1_CORE */
-        s->clken[2] = value & 0xfffffff9;
-        /* TODO update clocks */
-        /* The EN_EAC bit only gets/puts core_l4_iclk.  */
-        break;
-    case 0x214:        /* CM_ICLKEN2_CORE */
-        s->clken[3] = value & 0x00000007;
-        /* TODO update clocks */
-        break;
-    case 0x21c:        /* CM_ICLKEN4_CORE */
-        s->clken[4] = value & 0x0000001f;
-        /* TODO update clocks */
-        break;
-
-    case 0x230:        /* CM_AUTOIDLE1_CORE */
-        s->clkidle[0] = value & 0xfffffff9;
-        /* TODO update clocks */
-        break;
-    case 0x234:        /* CM_AUTOIDLE2_CORE */
-        s->clkidle[1] = value & 0x00000007;
-        /* TODO update clocks */
-        break;
-    case 0x238:        /* CM_AUTOIDLE3_CORE */
-        s->clkidle[2] = value & 0x00000007;
-        /* TODO update clocks */
-        break;
-    case 0x23c:        /* CM_AUTOIDLE4_CORE */
-        s->clkidle[3] = value & 0x0000001f;
-        /* TODO update clocks */
-        break;
-
-    case 0x240:        /* CM_CLKSEL1_CORE */
-        s->clksel[1] = value & 0x0fffbf7f;
-        /* TODO update clocks */
-        break;
-
-    case 0x244:        /* CM_CLKSEL2_CORE */
-        s->clksel[2] = value & 0x00fffffc;
-        /* TODO update clocks */
-        break;
-
-    case 0x248:        /* CM_CLKSTCTRL_CORE */
-        s->clkctrl[1] = value & 0x7;
-        break;
-
-    case 0x2a0:        /* PM_WKEN1_CORE */
-        s->wken[0] = value & 0x04667ff8;
-        break;
-    case 0x2a4:        /* PM_WKEN2_CORE */
-        s->wken[1] = value & 0x00000005;
-        break;
-
-    case 0x2b0:        /* PM_WKST1_CORE */
-        s->wkst[0] &= ~value;
-        break;
-    case 0x2b4:        /* PM_WKST2_CORE */
-        s->wkst[1] &= ~value;
-        break;
-
-    case 0x2e0:        /* PM_PWSTCTRL_CORE */
-        s->power[1] = (value & 0x00fc3f) | (1 << 2);
-        break;
-
-    case 0x300:        /* CM_FCLKEN_GFX */
-        s->clken[5] = value & 6;
-        /* TODO update clocks */
-        break;
-    case 0x310:        /* CM_ICLKEN_GFX */
-        s->clken[6] = value & 1;
-        /* TODO update clocks */
-        break;
-    case 0x340:        /* CM_CLKSEL_GFX */
-        s->clksel[3] = value & 7;
-        /* TODO update clocks */
-        break;
-    case 0x348:        /* CM_CLKSTCTRL_GFX */
-        s->clkctrl[2] = value & 1;
-        break;
-    case 0x350:        /* RM_RSTCTRL_GFX */
-        s->rstctrl[0] = value & 1;
-        /* TODO: reset */
-        break;
-    case 0x358:        /* RM_RSTST_GFX */
-        s->rst[1] &= ~value;
-        break;
-    case 0x3c8:        /* PM_WKDEP_GFX */
-        s->wkup[1] = value & 0x13;
-        break;
-    case 0x3e0:        /* PM_PWSTCTRL_GFX */
-        s->power[2] = (value & 0x00c0f) | (3 << 2);
-        break;
-
-    case 0x400:        /* CM_FCLKEN_WKUP */
-        s->clken[7] = value & 0xd;
-        /* TODO update clocks */
-        break;
-    case 0x410:        /* CM_ICLKEN_WKUP */
-        s->clken[8] = value & 0x3f;
-        /* TODO update clocks */
-        break;
-    case 0x430:        /* CM_AUTOIDLE_WKUP */
-        s->clkidle[4] = value & 0x0000003f;
-        /* TODO update clocks */
-        break;
-    case 0x440:        /* CM_CLKSEL_WKUP */
-        s->clksel[4] = value & 3;
-        /* TODO update clocks */
-        break;
-    case 0x450:        /* RM_RSTCTRL_WKUP */
-        /* TODO: reset */
-        if (value & 2)
-            qemu_system_reset_request();
-        break;
-    case 0x454:        /* RM_RSTTIME_WKUP */
-        s->rsttime_wkup = value & 0x1fff;
-        break;
-    case 0x458:        /* RM_RSTST_WKUP */
-        s->rst[2] &= ~value;
-        break;
-    case 0x4a0:        /* PM_WKEN_WKUP */
-        s->wken[2] = value & 0x00000005;
-        break;
-    case 0x4b0:        /* PM_WKST_WKUP */
-        s->wkst[2] &= ~value;
-        break;
-
-    case 0x500:        /* CM_CLKEN_PLL */
-        if (value & 0xffffff30)
-            fprintf(stderr, "%s: write 0s in CM_CLKEN_PLL for "
-                            "future compatibility\n", __FUNCTION__);
-        if ((s->clken[9] ^ value) & 0xcc) {
-            s->clken[9] &= ~0xcc;
-            s->clken[9] |= value & 0xcc;
-            omap_prcm_apll_update(s);
-        }
-        if ((s->clken[9] ^ value) & 3) {
-            s->clken[9] &= ~3;
-            s->clken[9] |= value & 3;
-            omap_prcm_dpll_update(s);
-        }
-        break;
-    case 0x530:        /* CM_AUTOIDLE_PLL */
-        s->clkidle[5] = value & 0x000000cf;
-        /* TODO update clocks */
-        break;
-    case 0x540:        /* CM_CLKSEL1_PLL */
-        if (value & 0xfc4000d7)
-            fprintf(stderr, "%s: write 0s in CM_CLKSEL1_PLL for "
-                            "future compatibility\n", __FUNCTION__);
-        if ((s->clksel[5] ^ value) & 0x003fff00) {
-            s->clksel[5] = value & 0x03bfff28;
-            omap_prcm_dpll_update(s);
-        }
-        /* TODO update the other clocks */
-
-        s->clksel[5] = value & 0x03bfff28;
-        break;
-    case 0x544:        /* CM_CLKSEL2_PLL */
-        if (value & ~3)
-            fprintf(stderr, "%s: write 0s in CM_CLKSEL2_PLL[31:2] for "
-                            "future compatibility\n", __FUNCTION__);
-        if (s->clksel[6] != (value & 3)) {
-            s->clksel[6] = value & 3;
-            omap_prcm_dpll_update(s);
-        }
-        break;
-
-    case 0x800:        /* CM_FCLKEN_DSP */
-        s->clken[10] = value & 0x501;
-        /* TODO update clocks */
-        break;
-    case 0x810:        /* CM_ICLKEN_DSP */
-        s->clken[11] = value & 0x2;
-        /* TODO update clocks */
-        break;
-    case 0x830:        /* CM_AUTOIDLE_DSP */
-        s->clkidle[6] = value & 0x2;
-        /* TODO update clocks */
-        break;
-    case 0x840:        /* CM_CLKSEL_DSP */
-        s->clksel[7] = value & 0x3fff;
-        /* TODO update clocks */
-        break;
-    case 0x848:        /* CM_CLKSTCTRL_DSP */
-        s->clkctrl[3] = value & 0x101;
-        break;
-    case 0x850:        /* RM_RSTCTRL_DSP */
-        /* TODO: reset */
-        break;
-    case 0x858:        /* RM_RSTST_DSP */
-        s->rst[3] &= ~value;
-        break;
-    case 0x8c8:        /* PM_WKDEP_DSP */
-        s->wkup[2] = value & 0x13;
-        break;
-    case 0x8e0:        /* PM_PWSTCTRL_DSP */
-        s->power[3] = (value & 0x03017) | (3 << 2);
-        break;
-
-    case 0x8f0:        /* PRCM_IRQSTATUS_DSP */
-        s->irqst[1] &= ~value;
-        omap_prcm_int_update(s, 1);
-        break;
-    case 0x8f4:        /* PRCM_IRQENABLE_DSP */
-        s->irqen[1] = value & 0x7;
-        omap_prcm_int_update(s, 1);
-        break;
-
-    case 0x8f8:        /* PRCM_IRQSTATUS_IVA */
-        s->irqst[2] &= ~value;
-        omap_prcm_int_update(s, 2);
-        break;
-    case 0x8fc:        /* PRCM_IRQENABLE_IVA */
-        s->irqen[2] = value & 0x7;
-        omap_prcm_int_update(s, 2);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_prcm_ops = {
-    .read = omap_prcm_read,
-    .write = omap_prcm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_prcm_reset(struct omap_prcm_s *s)
-{
-    s->sysconfig = 0;
-    s->irqst[0] = 0;
-    s->irqst[1] = 0;
-    s->irqst[2] = 0;
-    s->irqen[0] = 0;
-    s->irqen[1] = 0;
-    s->irqen[2] = 0;
-    s->voltctrl = 0x1040;
-    s->ev = 0x14;
-    s->evtime[0] = 0;
-    s->evtime[1] = 0;
-    s->clkctrl[0] = 0;
-    s->clkctrl[1] = 0;
-    s->clkctrl[2] = 0;
-    s->clkctrl[3] = 0;
-    s->clken[1] = 7;
-    s->clken[3] = 7;
-    s->clken[4] = 0;
-    s->clken[5] = 0;
-    s->clken[6] = 0;
-    s->clken[7] = 0xc;
-    s->clken[8] = 0x3e;
-    s->clken[9] = 0x0d;
-    s->clken[10] = 0;
-    s->clken[11] = 0;
-    s->clkidle[0] = 0;
-    s->clkidle[2] = 7;
-    s->clkidle[3] = 0;
-    s->clkidle[4] = 0;
-    s->clkidle[5] = 0x0c;
-    s->clkidle[6] = 0;
-    s->clksel[0] = 0x01;
-    s->clksel[1] = 0x02100121;
-    s->clksel[2] = 0x00000000;
-    s->clksel[3] = 0x01;
-    s->clksel[4] = 0;
-    s->clksel[7] = 0x0121;
-    s->wkup[0] = 0x15;
-    s->wkup[1] = 0x13;
-    s->wkup[2] = 0x13;
-    s->wken[0] = 0x04667ff8;
-    s->wken[1] = 0x00000005;
-    s->wken[2] = 5;
-    s->wkst[0] = 0;
-    s->wkst[1] = 0;
-    s->wkst[2] = 0;
-    s->power[0] = 0x00c;
-    s->power[1] = 4;
-    s->power[2] = 0x0000c;
-    s->power[3] = 0x14;
-    s->rstctrl[0] = 1;
-    s->rst[3] = 1;
-    omap_prcm_apll_update(s);
-    omap_prcm_dpll_update(s);
-}
-
-static void omap_prcm_coldreset(struct omap_prcm_s *s)
-{
-    s->setuptime[0] = 0;
-    s->setuptime[1] = 0;
-    memset(&s->scratch, 0, sizeof(s->scratch));
-    s->rst[0] = 0x01;
-    s->rst[1] = 0x00;
-    s->rst[2] = 0x01;
-    s->clken[0] = 0;
-    s->clken[2] = 0;
-    s->clkidle[1] = 0;
-    s->clksel[5] = 0;
-    s->clksel[6] = 2;
-    s->clksrc[0] = 0x43;
-    s->clkout[0] = 0x0303;
-    s->clkemul[0] = 0;
-    s->clkpol[0] = 0x100;
-    s->rsttime_wkup = 0x1002;
-
-    omap_prcm_reset(s);
-}
-
-static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
-                qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
-                struct omap_mpu_state_s *mpu)
-{
-    struct omap_prcm_s *s = (struct omap_prcm_s *)
-            g_malloc0(sizeof(struct omap_prcm_s));
-
-    s->irq[0] = mpu_int;
-    s->irq[1] = dsp_int;
-    s->irq[2] = iva_int;
-    s->mpu = mpu;
-    omap_prcm_coldreset(s);
-
-    memory_region_init_io(&s->iomem0, &omap_prcm_ops, s, "omap.pcrm0",
-                          omap_l4_region_size(ta, 0));
-    memory_region_init_io(&s->iomem1, &omap_prcm_ops, s, "omap.pcrm1",
-                          omap_l4_region_size(ta, 1));
-    omap_l4_attach(ta, 0, &s->iomem0);
-    omap_l4_attach(ta, 1, &s->iomem1);
-
-    return s;
-}
-
-/* System and Pinout control */
-struct omap_sysctl_s {
-    struct omap_mpu_state_s *mpu;
-    MemoryRegion iomem;
-
-    uint32_t sysconfig;
-    uint32_t devconfig;
-    uint32_t psaconfig;
-    uint32_t padconf[0x45];
-    uint8_t obs;
-    uint32_t msuspendmux[5];
-};
-
-static uint32_t omap_sysctl_read8(void *opaque, hwaddr addr)
-{
-
-    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
-    int pad_offset, byte_offset;
-    int value;
-
-    switch (addr) {
-    case 0x030 ... 0x140:      /* CONTROL_PADCONF - only used in the POP */
-        pad_offset = (addr - 0x30) >> 2;
-        byte_offset = (addr - 0x30) & (4 - 1);
-
-        value = s->padconf[pad_offset];
-        value = (value >> (byte_offset * 8)) & 0xff;
-
-        return value;
-
-    default:
-        break;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static uint32_t omap_sysctl_read(void *opaque, hwaddr addr)
-{
-    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
-
-    switch (addr) {
-    case 0x000:        /* CONTROL_REVISION */
-        return 0x20;
-
-    case 0x010:        /* CONTROL_SYSCONFIG */
-        return s->sysconfig;
-
-    case 0x030 ... 0x140:      /* CONTROL_PADCONF - only used in the POP */
-        return s->padconf[(addr - 0x30) >> 2];
-
-    case 0x270:        /* CONTROL_DEBOBS */
-        return s->obs;
-
-    case 0x274:        /* CONTROL_DEVCONF */
-        return s->devconfig;
-
-    case 0x28c:        /* CONTROL_EMU_SUPPORT */
-        return 0;
-
-    case 0x290:        /* CONTROL_MSUSPENDMUX_0 */
-        return s->msuspendmux[0];
-    case 0x294:        /* CONTROL_MSUSPENDMUX_1 */
-        return s->msuspendmux[1];
-    case 0x298:        /* CONTROL_MSUSPENDMUX_2 */
-        return s->msuspendmux[2];
-    case 0x29c:        /* CONTROL_MSUSPENDMUX_3 */
-        return s->msuspendmux[3];
-    case 0x2a0:        /* CONTROL_MSUSPENDMUX_4 */
-        return s->msuspendmux[4];
-    case 0x2a4:        /* CONTROL_MSUSPENDMUX_5 */
-        return 0;
-
-    case 0x2b8:        /* CONTROL_PSA_CTRL */
-        return s->psaconfig;
-    case 0x2bc:        /* CONTROL_PSA_CMD */
-    case 0x2c0:        /* CONTROL_PSA_VALUE */
-        return 0;
-
-    case 0x2b0:        /* CONTROL_SEC_CTRL */
-        return 0x800000f1;
-    case 0x2d0:        /* CONTROL_SEC_EMU */
-        return 0x80000015;
-    case 0x2d4:        /* CONTROL_SEC_TAP */
-        return 0x8000007f;
-    case 0x2b4:        /* CONTROL_SEC_TEST */
-    case 0x2f0:        /* CONTROL_SEC_STATUS */
-    case 0x2f4:        /* CONTROL_SEC_ERR_STATUS */
-        /* Secure mode is not present on general-pusrpose device.  Outside
-         * secure mode these values cannot be read or written.  */
-        return 0;
-
-    case 0x2d8:        /* CONTROL_OCM_RAM_PERM */
-        return 0xff;
-    case 0x2dc:        /* CONTROL_OCM_PUB_RAM_ADD */
-    case 0x2e0:        /* CONTROL_EXT_SEC_RAM_START_ADD */
-    case 0x2e4:        /* CONTROL_EXT_SEC_RAM_STOP_ADD */
-        /* No secure mode so no Extended Secure RAM present.  */
-        return 0;
-
-    case 0x2f8:        /* CONTROL_STATUS */
-        /* Device Type => General-purpose */
-        return 0x0300;
-    case 0x2fc:        /* CONTROL_GENERAL_PURPOSE_STATUS */
-
-    case 0x300:        /* CONTROL_RPUB_KEY_H_0 */
-    case 0x304:        /* CONTROL_RPUB_KEY_H_1 */
-    case 0x308:        /* CONTROL_RPUB_KEY_H_2 */
-    case 0x30c:        /* CONTROL_RPUB_KEY_H_3 */
-        return 0xdecafbad;
-
-    case 0x310:        /* CONTROL_RAND_KEY_0 */
-    case 0x314:        /* CONTROL_RAND_KEY_1 */
-    case 0x318:        /* CONTROL_RAND_KEY_2 */
-    case 0x31c:        /* CONTROL_RAND_KEY_3 */
-    case 0x320:        /* CONTROL_CUST_KEY_0 */
-    case 0x324:        /* CONTROL_CUST_KEY_1 */
-    case 0x330:        /* CONTROL_TEST_KEY_0 */
-    case 0x334:        /* CONTROL_TEST_KEY_1 */
-    case 0x338:        /* CONTROL_TEST_KEY_2 */
-    case 0x33c:        /* CONTROL_TEST_KEY_3 */
-    case 0x340:        /* CONTROL_TEST_KEY_4 */
-    case 0x344:        /* CONTROL_TEST_KEY_5 */
-    case 0x348:        /* CONTROL_TEST_KEY_6 */
-    case 0x34c:        /* CONTROL_TEST_KEY_7 */
-    case 0x350:        /* CONTROL_TEST_KEY_8 */
-    case 0x354:        /* CONTROL_TEST_KEY_9 */
-        /* Can only be accessed in secure mode and when C_FieldAccEnable
-         * bit is set in CONTROL_SEC_CTRL.
-         * TODO: otherwise an interconnect access error is generated.  */
-        return 0;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_sysctl_write8(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
-    int pad_offset, byte_offset;
-    int prev_value;
-
-    switch (addr) {
-    case 0x030 ... 0x140:      /* CONTROL_PADCONF - only used in the POP */
-        pad_offset = (addr - 0x30) >> 2;
-        byte_offset = (addr - 0x30) & (4 - 1);
-
-        prev_value = s->padconf[pad_offset];
-        prev_value &= ~(0xff << (byte_offset * 8));
-        prev_value |= ((value & 0x1f1f1f1f) << (byte_offset * 8)) & 0x1f1f1f1f;
-        s->padconf[pad_offset] = prev_value;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        break;
-    }
-}
-
-static void omap_sysctl_write(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
-
-    switch (addr) {
-    case 0x000:        /* CONTROL_REVISION */
-    case 0x2a4:        /* CONTROL_MSUSPENDMUX_5 */
-    case 0x2c0:        /* CONTROL_PSA_VALUE */
-    case 0x2f8:        /* CONTROL_STATUS */
-    case 0x2fc:        /* CONTROL_GENERAL_PURPOSE_STATUS */
-    case 0x300:        /* CONTROL_RPUB_KEY_H_0 */
-    case 0x304:        /* CONTROL_RPUB_KEY_H_1 */
-    case 0x308:        /* CONTROL_RPUB_KEY_H_2 */
-    case 0x30c:        /* CONTROL_RPUB_KEY_H_3 */
-    case 0x310:        /* CONTROL_RAND_KEY_0 */
-    case 0x314:        /* CONTROL_RAND_KEY_1 */
-    case 0x318:        /* CONTROL_RAND_KEY_2 */
-    case 0x31c:        /* CONTROL_RAND_KEY_3 */
-    case 0x320:        /* CONTROL_CUST_KEY_0 */
-    case 0x324:        /* CONTROL_CUST_KEY_1 */
-    case 0x330:        /* CONTROL_TEST_KEY_0 */
-    case 0x334:        /* CONTROL_TEST_KEY_1 */
-    case 0x338:        /* CONTROL_TEST_KEY_2 */
-    case 0x33c:        /* CONTROL_TEST_KEY_3 */
-    case 0x340:        /* CONTROL_TEST_KEY_4 */
-    case 0x344:        /* CONTROL_TEST_KEY_5 */
-    case 0x348:        /* CONTROL_TEST_KEY_6 */
-    case 0x34c:        /* CONTROL_TEST_KEY_7 */
-    case 0x350:        /* CONTROL_TEST_KEY_8 */
-    case 0x354:        /* CONTROL_TEST_KEY_9 */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x010:        /* CONTROL_SYSCONFIG */
-        s->sysconfig = value & 0x1e;
-        break;
-
-    case 0x030 ... 0x140:      /* CONTROL_PADCONF - only used in the POP */
-        /* XXX: should check constant bits */
-        s->padconf[(addr - 0x30) >> 2] = value & 0x1f1f1f1f;
-        break;
-
-    case 0x270:        /* CONTROL_DEBOBS */
-        s->obs = value & 0xff;
-        break;
-
-    case 0x274:        /* CONTROL_DEVCONF */
-        s->devconfig = value & 0xffffc7ff;
-        break;
-
-    case 0x28c:        /* CONTROL_EMU_SUPPORT */
-        break;
-
-    case 0x290:        /* CONTROL_MSUSPENDMUX_0 */
-        s->msuspendmux[0] = value & 0x3fffffff;
-        break;
-    case 0x294:        /* CONTROL_MSUSPENDMUX_1 */
-        s->msuspendmux[1] = value & 0x3fffffff;
-        break;
-    case 0x298:        /* CONTROL_MSUSPENDMUX_2 */
-        s->msuspendmux[2] = value & 0x3fffffff;
-        break;
-    case 0x29c:        /* CONTROL_MSUSPENDMUX_3 */
-        s->msuspendmux[3] = value & 0x3fffffff;
-        break;
-    case 0x2a0:        /* CONTROL_MSUSPENDMUX_4 */
-        s->msuspendmux[4] = value & 0x3fffffff;
-        break;
-
-    case 0x2b8:        /* CONTROL_PSA_CTRL */
-        s->psaconfig = value & 0x1c;
-        s->psaconfig |= (value & 0x20) ? 2 : 1;
-        break;
-    case 0x2bc:        /* CONTROL_PSA_CMD */
-        break;
-
-    case 0x2b0:        /* CONTROL_SEC_CTRL */
-    case 0x2b4:        /* CONTROL_SEC_TEST */
-    case 0x2d0:        /* CONTROL_SEC_EMU */
-    case 0x2d4:        /* CONTROL_SEC_TAP */
-    case 0x2d8:        /* CONTROL_OCM_RAM_PERM */
-    case 0x2dc:        /* CONTROL_OCM_PUB_RAM_ADD */
-    case 0x2e0:        /* CONTROL_EXT_SEC_RAM_START_ADD */
-    case 0x2e4:        /* CONTROL_EXT_SEC_RAM_STOP_ADD */
-    case 0x2f0:        /* CONTROL_SEC_STATUS */
-    case 0x2f4:        /* CONTROL_SEC_ERR_STATUS */
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_sysctl_ops = {
-    .old_mmio = {
-        .read = {
-            omap_sysctl_read8,
-            omap_badwidth_read32,      /* TODO */
-            omap_sysctl_read,
-        },
-        .write = {
-            omap_sysctl_write8,
-            omap_badwidth_write32,     /* TODO */
-            omap_sysctl_write,
-        },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_sysctl_reset(struct omap_sysctl_s *s)
-{
-    /* (power-on reset) */
-    s->sysconfig = 0;
-    s->obs = 0;
-    s->devconfig = 0x0c000000;
-    s->msuspendmux[0] = 0x00000000;
-    s->msuspendmux[1] = 0x00000000;
-    s->msuspendmux[2] = 0x00000000;
-    s->msuspendmux[3] = 0x00000000;
-    s->msuspendmux[4] = 0x00000000;
-    s->psaconfig = 1;
-
-    s->padconf[0x00] = 0x000f0f0f;
-    s->padconf[0x01] = 0x00000000;
-    s->padconf[0x02] = 0x00000000;
-    s->padconf[0x03] = 0x00000000;
-    s->padconf[0x04] = 0x00000000;
-    s->padconf[0x05] = 0x00000000;
-    s->padconf[0x06] = 0x00000000;
-    s->padconf[0x07] = 0x00000000;
-    s->padconf[0x08] = 0x08080800;
-    s->padconf[0x09] = 0x08080808;
-    s->padconf[0x0a] = 0x08080808;
-    s->padconf[0x0b] = 0x08080808;
-    s->padconf[0x0c] = 0x08080808;
-    s->padconf[0x0d] = 0x08080800;
-    s->padconf[0x0e] = 0x08080808;
-    s->padconf[0x0f] = 0x08080808;
-    s->padconf[0x10] = 0x18181808;     /* | 0x07070700 if SBoot3 */
-    s->padconf[0x11] = 0x18181818;     /* | 0x07070707 if SBoot3 */
-    s->padconf[0x12] = 0x18181818;     /* | 0x07070707 if SBoot3 */
-    s->padconf[0x13] = 0x18181818;     /* | 0x07070707 if SBoot3 */
-    s->padconf[0x14] = 0x18181818;     /* | 0x00070707 if SBoot3 */
-    s->padconf[0x15] = 0x18181818;
-    s->padconf[0x16] = 0x18181818;     /* | 0x07000000 if SBoot3 */
-    s->padconf[0x17] = 0x1f001f00;
-    s->padconf[0x18] = 0x1f1f1f1f;
-    s->padconf[0x19] = 0x00000000;
-    s->padconf[0x1a] = 0x1f180000;
-    s->padconf[0x1b] = 0x00001f1f;
-    s->padconf[0x1c] = 0x1f001f00;
-    s->padconf[0x1d] = 0x00000000;
-    s->padconf[0x1e] = 0x00000000;
-    s->padconf[0x1f] = 0x08000000;
-    s->padconf[0x20] = 0x08080808;
-    s->padconf[0x21] = 0x08080808;
-    s->padconf[0x22] = 0x0f080808;
-    s->padconf[0x23] = 0x0f0f0f0f;
-    s->padconf[0x24] = 0x000f0f0f;
-    s->padconf[0x25] = 0x1f1f1f0f;
-    s->padconf[0x26] = 0x080f0f1f;
-    s->padconf[0x27] = 0x070f1808;
-    s->padconf[0x28] = 0x0f070707;
-    s->padconf[0x29] = 0x000f0f1f;
-    s->padconf[0x2a] = 0x0f0f0f1f;
-    s->padconf[0x2b] = 0x08000000;
-    s->padconf[0x2c] = 0x0000001f;
-    s->padconf[0x2d] = 0x0f0f1f00;
-    s->padconf[0x2e] = 0x1f1f0f0f;
-    s->padconf[0x2f] = 0x0f1f1f1f;
-    s->padconf[0x30] = 0x0f0f0f0f;
-    s->padconf[0x31] = 0x0f1f0f1f;
-    s->padconf[0x32] = 0x0f0f0f0f;
-    s->padconf[0x33] = 0x0f1f0f1f;
-    s->padconf[0x34] = 0x1f1f0f0f;
-    s->padconf[0x35] = 0x0f0f1f1f;
-    s->padconf[0x36] = 0x0f0f1f0f;
-    s->padconf[0x37] = 0x0f0f0f0f;
-    s->padconf[0x38] = 0x1f18180f;
-    s->padconf[0x39] = 0x1f1f1f1f;
-    s->padconf[0x3a] = 0x00001f1f;
-    s->padconf[0x3b] = 0x00000000;
-    s->padconf[0x3c] = 0x00000000;
-    s->padconf[0x3d] = 0x0f0f0f0f;
-    s->padconf[0x3e] = 0x18000f0f;
-    s->padconf[0x3f] = 0x00070000;
-    s->padconf[0x40] = 0x00000707;
-    s->padconf[0x41] = 0x0f1f0700;
-    s->padconf[0x42] = 0x1f1f070f;
-    s->padconf[0x43] = 0x0008081f;
-    s->padconf[0x44] = 0x00000800;
-}
-
-static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
-                omap_clk iclk, struct omap_mpu_state_s *mpu)
-{
-    struct omap_sysctl_s *s = (struct omap_sysctl_s *)
-            g_malloc0(sizeof(struct omap_sysctl_s));
-
-    s->mpu = mpu;
-    omap_sysctl_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_sysctl_ops, s, "omap.sysctl",
-                          omap_l4_region_size(ta, 0));
-    omap_l4_attach(ta, 0, &s->iomem);
-
-    return s;
-}
-
-/* General chip reset */
-static void omap2_mpu_reset(void *opaque)
-{
-    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
-
-    omap_dma_reset(mpu->dma);
-    omap_prcm_reset(mpu->prcm);
-    omap_sysctl_reset(mpu->sysc);
-    omap_gp_timer_reset(mpu->gptimer[0]);
-    omap_gp_timer_reset(mpu->gptimer[1]);
-    omap_gp_timer_reset(mpu->gptimer[2]);
-    omap_gp_timer_reset(mpu->gptimer[3]);
-    omap_gp_timer_reset(mpu->gptimer[4]);
-    omap_gp_timer_reset(mpu->gptimer[5]);
-    omap_gp_timer_reset(mpu->gptimer[6]);
-    omap_gp_timer_reset(mpu->gptimer[7]);
-    omap_gp_timer_reset(mpu->gptimer[8]);
-    omap_gp_timer_reset(mpu->gptimer[9]);
-    omap_gp_timer_reset(mpu->gptimer[10]);
-    omap_gp_timer_reset(mpu->gptimer[11]);
-    omap_synctimer_reset(mpu->synctimer);
-    omap_sdrc_reset(mpu->sdrc);
-    omap_gpmc_reset(mpu->gpmc);
-    omap_dss_reset(mpu->dss);
-    omap_uart_reset(mpu->uart[0]);
-    omap_uart_reset(mpu->uart[1]);
-    omap_uart_reset(mpu->uart[2]);
-    omap_mmc_reset(mpu->mmc);
-    omap_mcspi_reset(mpu->mcspi[0]);
-    omap_mcspi_reset(mpu->mcspi[1]);
-    cpu_reset(CPU(mpu->cpu));
-}
-
-static int omap2_validate_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return 1;
-}
-
-static const struct dma_irq_map omap2_dma_irq_map[] = {
-    { 0, OMAP_INT_24XX_SDMA_IRQ0 },
-    { 0, OMAP_INT_24XX_SDMA_IRQ1 },
-    { 0, OMAP_INT_24XX_SDMA_IRQ2 },
-    { 0, OMAP_INT_24XX_SDMA_IRQ3 },
-};
-
-struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
-                unsigned long sdram_size,
-                const char *core)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
-            g_malloc0(sizeof(struct omap_mpu_state_s));
-    qemu_irq *cpu_irq;
-    qemu_irq dma_irqs[4];
-    DriveInfo *dinfo;
-    int i;
-    SysBusDevice *busdev;
-    struct omap_target_agent_s *ta;
-
-    /* Core */
-    s->mpu_model = omap2420;
-    s->cpu = cpu_arm_init(core ?: "arm1136-r2");
-    if (s->cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    s->sdram_size = sdram_size;
-    s->sram_size = OMAP242X_SRAM_SIZE;
-
-    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
-
-    /* Clocks */
-    omap_clk_init(s);
-
-    /* Memory-mapped stuff */
-    memory_region_init_ram(&s->sdram, "omap2.dram", s->sdram_size);
-    vmstate_register_ram_global(&s->sdram);
-    memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
-    memory_region_init_ram(&s->sram, "omap2.sram", s->sram_size);
-    vmstate_register_ram_global(&s->sram);
-    memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
-
-    s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
-
-    /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
-    cpu_irq = arm_pic_init_cpu(s->cpu);
-    s->ih[0] = qdev_create(NULL, "omap2-intc");
-    qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
-    qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
-    qdev_prop_set_ptr(s->ih[0], "iclk", omap_findclk(s, "mpu_intc_iclk"));
-    qdev_init_nofail(s->ih[0]);
-    busdev = SYS_BUS_DEVICE(s->ih[0]);
-    sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
-    sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
-    sysbus_mmio_map(busdev, 0, 0x480fe000);
-    s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
-                             qdev_get_gpio_in(s->ih[0],
-                                              OMAP_INT_24XX_PRCM_MPU_IRQ),
-                             NULL, NULL, s);
-
-    s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1),
-                    omap_findclk(s, "omapctrl_iclk"), s);
-
-    for (i = 0; i < 4; i++) {
-        dma_irqs[i] = qdev_get_gpio_in(s->ih[omap2_dma_irq_map[i].ih],
-                                       omap2_dma_irq_map[i].intr);
-    }
-    s->dma = omap_dma4_init(0x48056000, dma_irqs, sysmem, s, 256, 32,
-                    omap_findclk(s, "sdma_iclk"),
-                    omap_findclk(s, "sdma_fclk"));
-    s->port->addr_valid = omap2_validate_addr;
-
-    /* Register SDRAM and SRAM ports for fast DMA transfers.  */
-    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram),
-                         OMAP2_Q2_BASE, s->sdram_size);
-    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
-                         OMAP2_SRAM_BASE, s->sram_size);
-
-    s->uart[0] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 19),
-                                 qdev_get_gpio_in(s->ih[0],
-                                                  OMAP_INT_24XX_UART1_IRQ),
-                    omap_findclk(s, "uart1_fclk"),
-                    omap_findclk(s, "uart1_iclk"),
-                    s->drq[OMAP24XX_DMA_UART1_TX],
-                    s->drq[OMAP24XX_DMA_UART1_RX],
-                    "uart1",
-                    serial_hds[0]);
-    s->uart[1] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 20),
-                                 qdev_get_gpio_in(s->ih[0],
-                                                  OMAP_INT_24XX_UART2_IRQ),
-                    omap_findclk(s, "uart2_fclk"),
-                    omap_findclk(s, "uart2_iclk"),
-                    s->drq[OMAP24XX_DMA_UART2_TX],
-                    s->drq[OMAP24XX_DMA_UART2_RX],
-                    "uart2",
-                    serial_hds[0] ? serial_hds[1] : NULL);
-    s->uart[2] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 21),
-                                 qdev_get_gpio_in(s->ih[0],
-                                                  OMAP_INT_24XX_UART3_IRQ),
-                    omap_findclk(s, "uart3_fclk"),
-                    omap_findclk(s, "uart3_iclk"),
-                    s->drq[OMAP24XX_DMA_UART3_TX],
-                    s->drq[OMAP24XX_DMA_UART3_RX],
-                    "uart3",
-                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
-
-    s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER1),
-                    omap_findclk(s, "wu_gpt1_clk"),
-                    omap_findclk(s, "wu_l4_iclk"));
-    s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER2),
-                    omap_findclk(s, "core_gpt2_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER3),
-                    omap_findclk(s, "core_gpt3_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER4),
-                    omap_findclk(s, "core_gpt4_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER5),
-                    omap_findclk(s, "core_gpt5_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER6),
-                    omap_findclk(s, "core_gpt6_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER7),
-                    omap_findclk(s, "core_gpt7_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER8),
-                    omap_findclk(s, "core_gpt8_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER9),
-                    omap_findclk(s, "core_gpt9_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER10),
-                    omap_findclk(s, "core_gpt10_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER11),
-                    omap_findclk(s, "core_gpt11_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER12),
-                    omap_findclk(s, "core_gpt12_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-
-    omap_tap_init(omap_l4ta(s->l4, 2), s);
-
-    s->synctimer = omap_synctimer_init(omap_l4tao(s->l4, 2), s,
-                    omap_findclk(s, "clk32-kHz"),
-                    omap_findclk(s, "core_l4_iclk"));
-
-    s->i2c[0] = qdev_create(NULL, "omap_i2c");
-    qdev_prop_set_uint8(s->i2c[0], "revision", 0x34);
-    qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk"));
-    qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk"));
-    qdev_init_nofail(s->i2c[0]);
-    busdev = SYS_BUS_DEVICE(s->i2c[0]);
-    sysbus_connect_irq(busdev, 0,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ));
-    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]);
-    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C1_RX]);
-    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 5), 0));
-
-    s->i2c[1] = qdev_create(NULL, "omap_i2c");
-    qdev_prop_set_uint8(s->i2c[1], "revision", 0x34);
-    qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk"));
-    qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk"));
-    qdev_init_nofail(s->i2c[1]);
-    busdev = SYS_BUS_DEVICE(s->i2c[1]);
-    sysbus_connect_irq(busdev, 0,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ));
-    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]);
-    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C2_RX]);
-    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 6), 0));
-
-    s->gpio = qdev_create(NULL, "omap2-gpio");
-    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
-    qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk"));
-    qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk"));
-    qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk"));
-    qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk"));
-    qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk"));
-    if (s->mpu_model == omap2430) {
-        qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
-    }
-    qdev_init_nofail(s->gpio);
-    busdev = SYS_BUS_DEVICE(s->gpio);
-    sysbus_connect_irq(busdev, 0,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK1));
-    sysbus_connect_irq(busdev, 3,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK2));
-    sysbus_connect_irq(busdev, 6,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK3));
-    sysbus_connect_irq(busdev, 9,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK4));
-    if (s->mpu_model == omap2430) {
-        sysbus_connect_irq(busdev, 12,
-                           qdev_get_gpio_in(s->ih[0],
-                                            OMAP_INT_243X_GPIO_BANK5));
-    }
-    ta = omap_l4ta(s->l4, 3);
-    sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
-    sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
-    sysbus_mmio_map(busdev, 2, omap_l4_region_base(ta, 2));
-    sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
-    sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
-
-    s->sdrc = omap_sdrc_init(sysmem, 0x68009000);
-    s->gpmc = omap_gpmc_init(s, 0x6800a000,
-                             qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPMC_IRQ),
-                             s->drq[OMAP24XX_DMA_GPMC]);
-
-    dinfo = drive_get(IF_SD, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "qemu: missing SecureDigital device\n");
-        exit(1);
-    }
-    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), dinfo->bdrv,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
-                    &s->drq[OMAP24XX_DMA_MMC1_TX],
-                    omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
-
-    s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI1_IRQ),
-                    &s->drq[OMAP24XX_DMA_SPI1_TX0],
-                    omap_findclk(s, "spi1_fclk"),
-                    omap_findclk(s, "spi1_iclk"));
-    s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI2_IRQ),
-                    &s->drq[OMAP24XX_DMA_SPI2_TX0],
-                    omap_findclk(s, "spi2_fclk"),
-                    omap_findclk(s, "spi2_iclk"));
-
-    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), sysmem, 0x68000800,
-                    /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_DSS_IRQ),
-                           s->drq[OMAP24XX_DMA_DSS],
-                    omap_findclk(s, "dss_clk1"), omap_findclk(s, "dss_clk2"),
-                    omap_findclk(s, "dss_54m_clk"),
-                    omap_findclk(s, "dss_l3_iclk"),
-                    omap_findclk(s, "dss_l4_iclk"));
-
-    omap_sti_init(omap_l4ta(s->l4, 18), sysmem, 0x54000000,
-                  qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_STI),
-                  omap_findclk(s, "emul_ck"),
-                    serial_hds[0] && serial_hds[1] && serial_hds[2] ?
-                    serial_hds[3] : NULL);
-
-    s->eac = omap_eac_init(omap_l4ta(s->l4, 32),
-                           qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_EAC_IRQ),
-                    /* Ten consecutive lines */
-                    &s->drq[OMAP24XX_DMA_EAC_AC_RD],
-                    omap_findclk(s, "func_96m_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-
-    /* All register mappings (includin those not currenlty implemented):
-     * SystemControlMod        48000000 - 48000fff
-     * SystemControlL4 48001000 - 48001fff
-     * 32kHz Timer Mod 48004000 - 48004fff
-     * 32kHz Timer L4  48005000 - 48005fff
-     * PRCM ModA       48008000 - 480087ff
-     * PRCM ModB       48008800 - 48008fff
-     * PRCM L4         48009000 - 48009fff
-     * TEST-BCM Mod    48012000 - 48012fff
-     * TEST-BCM L4     48013000 - 48013fff
-     * TEST-TAP Mod    48014000 - 48014fff
-     * TEST-TAP L4     48015000 - 48015fff
-     * GPIO1 Mod       48018000 - 48018fff
-     * GPIO Top                48019000 - 48019fff
-     * GPIO2 Mod       4801a000 - 4801afff
-     * GPIO L4         4801b000 - 4801bfff
-     * GPIO3 Mod       4801c000 - 4801cfff
-     * GPIO4 Mod       4801e000 - 4801efff
-     * WDTIMER1 Mod    48020000 - 48010fff
-     * WDTIMER Top     48021000 - 48011fff
-     * WDTIMER2 Mod    48022000 - 48012fff
-     * WDTIMER L4      48023000 - 48013fff
-     * WDTIMER3 Mod    48024000 - 48014fff
-     * WDTIMER3 L4     48025000 - 48015fff
-     * WDTIMER4 Mod    48026000 - 48016fff
-     * WDTIMER4 L4     48027000 - 48017fff
-     * GPTIMER1 Mod    48028000 - 48018fff
-     * GPTIMER1 L4     48029000 - 48019fff
-     * GPTIMER2 Mod    4802a000 - 4801afff
-     * GPTIMER2 L4     4802b000 - 4801bfff
-     * L4-Config AP    48040000 - 480407ff
-     * L4-Config IP    48040800 - 48040fff
-     * L4-Config LA    48041000 - 48041fff
-     * ARM11ETB Mod    48048000 - 48049fff
-     * ARM11ETB L4     4804a000 - 4804afff
-     * DISPLAY Top     48050000 - 480503ff
-     * DISPLAY DISPC   48050400 - 480507ff
-     * DISPLAY RFBI    48050800 - 48050bff
-     * DISPLAY VENC    48050c00 - 48050fff
-     * DISPLAY L4      48051000 - 48051fff
-     * CAMERA Top      48052000 - 480523ff
-     * CAMERA core     48052400 - 480527ff
-     * CAMERA DMA      48052800 - 48052bff
-     * CAMERA MMU      48052c00 - 48052fff
-     * CAMERA L4       48053000 - 48053fff
-     * SDMA Mod                48056000 - 48056fff
-     * SDMA L4         48057000 - 48057fff
-     * SSI Top         48058000 - 48058fff
-     * SSI GDD         48059000 - 48059fff
-     * SSI Port1       4805a000 - 4805afff
-     * SSI Port2       4805b000 - 4805bfff
-     * SSI L4          4805c000 - 4805cfff
-     * USB Mod         4805e000 - 480fefff
-     * USB L4          4805f000 - 480fffff
-     * WIN_TRACER1 Mod 48060000 - 48060fff
-     * WIN_TRACER1 L4  48061000 - 48061fff
-     * WIN_TRACER2 Mod 48062000 - 48062fff
-     * WIN_TRACER2 L4  48063000 - 48063fff
-     * WIN_TRACER3 Mod 48064000 - 48064fff
-     * WIN_TRACER3 L4  48065000 - 48065fff
-     * WIN_TRACER4 Top 48066000 - 480660ff
-     * WIN_TRACER4 ETT 48066100 - 480661ff
-     * WIN_TRACER4 WT  48066200 - 480662ff
-     * WIN_TRACER4 L4  48067000 - 48067fff
-     * XTI Mod         48068000 - 48068fff
-     * XTI L4          48069000 - 48069fff
-     * UART1 Mod       4806a000 - 4806afff
-     * UART1 L4                4806b000 - 4806bfff
-     * UART2 Mod       4806c000 - 4806cfff
-     * UART2 L4                4806d000 - 4806dfff
-     * UART3 Mod       4806e000 - 4806efff
-     * UART3 L4                4806f000 - 4806ffff
-     * I2C1 Mod                48070000 - 48070fff
-     * I2C1 L4         48071000 - 48071fff
-     * I2C2 Mod                48072000 - 48072fff
-     * I2C2 L4         48073000 - 48073fff
-     * McBSP1 Mod      48074000 - 48074fff
-     * McBSP1 L4       48075000 - 48075fff
-     * McBSP2 Mod      48076000 - 48076fff
-     * McBSP2 L4       48077000 - 48077fff
-     * GPTIMER3 Mod    48078000 - 48078fff
-     * GPTIMER3 L4     48079000 - 48079fff
-     * GPTIMER4 Mod    4807a000 - 4807afff
-     * GPTIMER4 L4     4807b000 - 4807bfff
-     * GPTIMER5 Mod    4807c000 - 4807cfff
-     * GPTIMER5 L4     4807d000 - 4807dfff
-     * GPTIMER6 Mod    4807e000 - 4807efff
-     * GPTIMER6 L4     4807f000 - 4807ffff
-     * GPTIMER7 Mod    48080000 - 48080fff
-     * GPTIMER7 L4     48081000 - 48081fff
-     * GPTIMER8 Mod    48082000 - 48082fff
-     * GPTIMER8 L4     48083000 - 48083fff
-     * GPTIMER9 Mod    48084000 - 48084fff
-     * GPTIMER9 L4     48085000 - 48085fff
-     * GPTIMER10 Mod   48086000 - 48086fff
-     * GPTIMER10 L4    48087000 - 48087fff
-     * GPTIMER11 Mod   48088000 - 48088fff
-     * GPTIMER11 L4    48089000 - 48089fff
-     * GPTIMER12 Mod   4808a000 - 4808afff
-     * GPTIMER12 L4    4808b000 - 4808bfff
-     * EAC Mod         48090000 - 48090fff
-     * EAC L4          48091000 - 48091fff
-     * FAC Mod         48092000 - 48092fff
-     * FAC L4          48093000 - 48093fff
-     * MAILBOX Mod     48094000 - 48094fff
-     * MAILBOX L4      48095000 - 48095fff
-     * SPI1 Mod                48098000 - 48098fff
-     * SPI1 L4         48099000 - 48099fff
-     * SPI2 Mod                4809a000 - 4809afff
-     * SPI2 L4         4809b000 - 4809bfff
-     * MMC/SDIO Mod    4809c000 - 4809cfff
-     * MMC/SDIO L4     4809d000 - 4809dfff
-     * MS_PRO Mod      4809e000 - 4809efff
-     * MS_PRO L4       4809f000 - 4809ffff
-     * RNG Mod         480a0000 - 480a0fff
-     * RNG L4          480a1000 - 480a1fff
-     * DES3DES Mod     480a2000 - 480a2fff
-     * DES3DES L4      480a3000 - 480a3fff
-     * SHA1MD5 Mod     480a4000 - 480a4fff
-     * SHA1MD5 L4      480a5000 - 480a5fff
-     * AES Mod         480a6000 - 480a6fff
-     * AES L4          480a7000 - 480a7fff
-     * PKA Mod         480a8000 - 480a9fff
-     * PKA L4          480aa000 - 480aafff
-     * MG Mod          480b0000 - 480b0fff
-     * MG L4           480b1000 - 480b1fff
-     * HDQ/1-wire Mod  480b2000 - 480b2fff
-     * HDQ/1-wire L4   480b3000 - 480b3fff
-     * MPU interrupt   480fe000 - 480fefff
-     * STI channel base        54000000 - 5400ffff
-     * IVA RAM         5c000000 - 5c01ffff
-     * IVA ROM         5c020000 - 5c027fff
-     * IMG_BUF_A       5c040000 - 5c040fff
-     * IMG_BUF_B       5c042000 - 5c042fff
-     * VLCDS           5c048000 - 5c0487ff
-     * IMX_COEF                5c049000 - 5c04afff
-     * IMX_CMD         5c051000 - 5c051fff
-     * VLCDQ           5c053000 - 5c0533ff
-     * VLCDH           5c054000 - 5c054fff
-     * SEQ_CMD         5c055000 - 5c055fff
-     * IMX_REG         5c056000 - 5c0560ff
-     * VLCD_REG                5c056100 - 5c0561ff
-     * SEQ_REG         5c056200 - 5c0562ff
-     * IMG_BUF_REG     5c056300 - 5c0563ff
-     * SEQIRQ_REG      5c056400 - 5c0564ff
-     * OCP_REG         5c060000 - 5c060fff
-     * SYSC_REG                5c070000 - 5c070fff
-     * MMU_REG         5d000000 - 5d000fff
-     * sDMA R          68000400 - 680005ff
-     * sDMA W          68000600 - 680007ff
-     * Display Control 68000800 - 680009ff
-     * DSP subsystem   68000a00 - 68000bff
-     * MPU subsystem   68000c00 - 68000dff
-     * IVA subsystem   68001000 - 680011ff
-     * USB             68001200 - 680013ff
-     * Camera          68001400 - 680015ff
-     * VLYNQ (firewall)        68001800 - 68001bff
-     * VLYNQ           68001e00 - 68001fff
-     * SSI             68002000 - 680021ff
-     * L4              68002400 - 680025ff
-     * DSP (firewall)  68002800 - 68002bff
-     * DSP subsystem   68002e00 - 68002fff
-     * IVA (firewall)  68003000 - 680033ff
-     * IVA             68003600 - 680037ff
-     * GFX             68003a00 - 68003bff
-     * CMDWR emulation 68003c00 - 68003dff
-     * SMS             68004000 - 680041ff
-     * OCM             68004200 - 680043ff
-     * GPMC            68004400 - 680045ff
-     * RAM (firewall)  68005000 - 680053ff
-     * RAM (err login) 68005400 - 680057ff
-     * ROM (firewall)  68005800 - 68005bff
-     * ROM (err login) 68005c00 - 68005fff
-     * GPMC (firewall) 68006000 - 680063ff
-     * GPMC (err login)        68006400 - 680067ff
-     * SMS (err login) 68006c00 - 68006fff
-     * SMS registers   68008000 - 68008fff
-     * SDRC registers  68009000 - 68009fff
-     * GPMC registers  6800a000   6800afff
-     */
-
-    qemu_register_reset(omap2_mpu_reset, s);
-
-    return s;
-}
index 844800606766664ae5e2422c2f79f476bc9f684b..c7b5c11626e23e7a035b67da2b20b561ea148bb9 100644 (file)
@@ -18,8 +18,8 @@
  * 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 "hw.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
 
 struct clk {
     const char *name;
index 0c878b6ef2571a5a9c11acdaf22f53ce84b165e7..0c5902f6f9cad0dd9b1889108344c2bd21a685de 100644 (file)
@@ -19,9 +19,9 @@
  */
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "omap.h"
-#include "irq.h"
-#include "soc_dma.h"
+#include "hw/omap.h"
+#include "hw/irq.h"
+#include "hw/soc_dma.h"
 
 struct omap_dma_channel_s {
     /* transfer data */
index ae51bdfe4114de69177c95e99fc4a1428e416a50..948ad8fcc5fc2e1b6ba28a84742535951c3636fd 100644 (file)
@@ -17,9 +17,9 @@
  * 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 "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "omap.h"
+#include "hw/omap.h"
 
 struct omap_dss_s {
     qemu_irq irq;
index aadf1cc59f3ec8a6ab5a3b59629a8febe982c5c8..c79f61c2ba07911206a1d6e54b98bff3ec78e2f7 100644 (file)
@@ -18,9 +18,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "omap.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
+#include "hw/sysbus.h"
 
 struct omap_gpio_s {
     qemu_irq irq;
index 02ab0ab568627583dc67944463a96e949102ce5d..ebb259c283333a04624686aaf4b66ae3428da08c 100644 (file)
@@ -18,9 +18,9 @@
  * 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 "hw.h"
-#include "flash.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
+#include "hw/omap.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
 
index a5db710dcb9577c051006ac2bcaa56b0fafa956b..8485ee84f532efaf15adc97fd847ac78759950a7 100644 (file)
@@ -17,9 +17,9 @@
  * 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 "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "omap.h"
+#include "hw/omap.h"
 
 /* GP timers */
 struct omap_gp_timer_s {
index 143b198f1d8a01a33679cb75526810a4f879fb3f..92f7b371eaf216af25b32a0e618b7d684d26722e 100644 (file)
  * 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 "hw.h"
-#include "i2c.h"
-#include "omap.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
+#include "hw/omap.h"
+#include "hw/sysbus.h"
 
 
 typedef struct OMAPI2CState {
index 4b0acd0f3324521d397c37a9d2846834d00092be..7da9c3548cda494953b448986d94a5eacd1a5233 100644 (file)
@@ -17,9 +17,9 @@
  * 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 "hw.h"
-#include "omap.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
+#include "hw/sysbus.h"
 
 /* Interrupt Handlers */
 struct omap_intr_handler_bank_s {
index 09e983f319de84c6ef96e884f7acac15cffd4e05..cbe8a06033725ec7f5be5daf3e212737c709cc67 100644 (file)
@@ -17,8 +17,8 @@
  * 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 "hw.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
 
 struct omap_l4_s {
     MemoryRegion *address_space;
index 936850a6216ba6f3938d045795c168f4e8af45e1..c426f3a13af0ca7ff87067dfd7ab45e9dd5e7c5a 100644 (file)
  * 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 "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "omap.h"
-#include "framebuffer.h"
+#include "hw/omap.h"
+#include "hw/framebuffer.h"
 #include "ui/pixel_ops.h"
 
 struct omap_lcd_panel_s {
@@ -70,13 +70,13 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
 #define draw_line_func drawfn
 
 #define DEPTH 8
-#include "omap_lcd_template.h"
+#include "hw/omap_lcd_template.h"
 #define DEPTH 15
-#include "omap_lcd_template.h"
+#include "hw/omap_lcd_template.h"
 #define DEPTH 16
-#include "omap_lcd_template.h"
+#include "hw/omap_lcd_template.h"
 #define DEPTH 32
-#include "omap_lcd_template.h"
+#include "hw/omap_lcd_template.h"
 
 static draw_line_func draw_line_table2[33] = {
     [0 ... 32] = NULL,
index 7ecd9bd4caa10da71eaedeb2f9045ef8adcb21fc..6e48110c9eef0e739f030aea5eeaf2ee6e85bf0d 100644 (file)
@@ -16,9 +16,9 @@
  * 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 "hw.h"
-#include "omap.h"
-#include "sd.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
+#include "hw/sd.h"
 
 struct omap_mmc_s {
     qemu_irq irq;
index b0f3b8e675657962eecb341b4d13985999b4c42e..510e6cc5808bfa3c0c4a574affcdf9ed1fbc485d 100644 (file)
@@ -17,8 +17,8 @@
  * 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 "hw.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
 
 /* SDRAM Controller Subsystem */
 struct omap_sdrc_s {
index 8ff01ed99d0e07826f8e5e760553aca4f6ccb866..1cbd98d338f6e4af033af60b0e5cfa41a701ed41 100644 (file)
@@ -19,8 +19,8 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
-#include "hw.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
 
 /* Multichannel SPI */
 struct omap_mcspi_s {
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
deleted file mode 100644 (file)
index 30998c5..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/* omap_sx1.c Support for the Siemens SX1 smartphone emulation.
- *
- *   Copyright (C) 2008
- *     Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *   Copyright (C) 2007 Vladimir Ananiev <vovan888@gmail.com>
- *
- *   based on PalmOne's (TM) PDAs support (palm.c)
- */
-
-/*
- * PalmOne's (TM) PDAs.
- *
- * Copyright (C) 2006-2007 Andrzej Zaborowski <balrog@zabor.org>
- *
- * 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 "hw.h"
-#include "ui/console.h"
-#include "omap.h"
-#include "boards.h"
-#include "arm-misc.h"
-#include "flash.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-/*****************************************************************************/
-/* Siemens SX1 Cellphone V1 */
-/* - ARM OMAP310 processor
- * - SRAM                192 kB
- * - SDRAM                32 MB at 0x10000000
- * - Boot flash           16 MB at 0x00000000
- * - Application flash     8 MB at 0x04000000
- * - 3 serial ports
- * - 1 SecureDigital
- * - 1 LCD display
- * - 1 RTC
- */
-
-/*****************************************************************************/
-/* Siemens SX1 Cellphone V2 */
-/* - ARM OMAP310 processor
- * - SRAM                192 kB
- * - SDRAM                32 MB at 0x10000000
- * - Boot flash           32 MB at 0x00000000
- * - 3 serial ports
- * - 1 SecureDigital
- * - 1 LCD display
- * - 1 RTC
- */
-
-static uint64_t static_read(void *opaque, hwaddr offset,
-                            unsigned size)
-{
-    uint32_t *val = (uint32_t *) opaque;
-    uint32_t mask = (4 / size) - 1;
-
-    return *val >> ((offset & mask) << 3);
-}
-
-static void static_write(void *opaque, hwaddr offset,
-                         uint64_t value, unsigned size)
-{
-#ifdef SPY
-    printf("%s: value %" PRIx64 " %u bytes written at 0x%x\n",
-                    __func__, value, size, (int)offset);
-#endif
-}
-
-static const MemoryRegionOps static_ops = {
-    .read = static_read,
-    .write = static_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-#define sdram_size     0x02000000
-#define sector_size    (128 * 1024)
-#define flash0_size    (16 * 1024 * 1024)
-#define flash1_size    ( 8 * 1024 * 1024)
-#define flash2_size    (32 * 1024 * 1024)
-#define total_ram_v1   (sdram_size + flash0_size + flash1_size + OMAP15XX_SRAM_SIZE)
-#define total_ram_v2   (sdram_size + flash2_size + OMAP15XX_SRAM_SIZE)
-
-static struct arm_boot_info sx1_binfo = {
-    .loader_start = OMAP_EMIFF_BASE,
-    .ram_size = sdram_size,
-    .board_id = 0x265,
-};
-
-static void sx1_init(QEMUMachineInitArgs *args, const int version)
-{
-    struct omap_mpu_state_s *mpu;
-    MemoryRegion *address_space = get_system_memory();
-    MemoryRegion *flash = g_new(MemoryRegion, 1);
-    MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
-    MemoryRegion *cs = g_new(MemoryRegion, 4);
-    static uint32_t cs0val = 0x00213090;
-    static uint32_t cs1val = 0x00215070;
-    static uint32_t cs2val = 0x00001139;
-    static uint32_t cs3val = 0x00001139;
-    DriveInfo *dinfo;
-    int fl_idx;
-    uint32_t flash_size = flash0_size;
-    int be;
-
-    if (version == 2) {
-        flash_size = flash2_size;
-    }
-
-    mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, args->cpu_model);
-
-    /* External Flash (EMIFS) */
-    memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size);
-    vmstate_register_ram_global(flash);
-    memory_region_set_readonly(flash, true);
-    memory_region_add_subregion(address_space, OMAP_CS0_BASE, flash);
-
-    memory_region_init_io(&cs[0], &static_ops, &cs0val,
-                          "sx1.cs0", OMAP_CS0_SIZE - flash_size);
-    memory_region_add_subregion(address_space,
-                                OMAP_CS0_BASE + flash_size, &cs[0]);
-
-
-    memory_region_init_io(&cs[2], &static_ops, &cs2val,
-                          "sx1.cs2", OMAP_CS2_SIZE);
-    memory_region_add_subregion(address_space,
-                                OMAP_CS2_BASE, &cs[2]);
-
-    memory_region_init_io(&cs[3], &static_ops, &cs3val,
-                          "sx1.cs3", OMAP_CS3_SIZE);
-    memory_region_add_subregion(address_space,
-                                OMAP_CS2_BASE, &cs[3]);
-
-    fl_idx = 0;
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-
-    if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL,
-                                   "omap_sx1.flash0-1", flash_size,
-                                   dinfo->bdrv, sector_size,
-                                   flash_size / sector_size,
-                                   4, 0, 0, 0, 0, be)) {
-            fprintf(stderr, "qemu: Error registering flash memory %d.\n",
-                           fl_idx);
-        }
-        fl_idx++;
-    }
-
-    if ((version == 1) &&
-            (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        memory_region_init_ram(flash_1, "omap_sx1.flash1-0", flash1_size);
-        vmstate_register_ram_global(flash_1);
-        memory_region_set_readonly(flash_1, true);
-        memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1);
-
-        memory_region_init_io(&cs[1], &static_ops, &cs1val,
-                              "sx1.cs1", OMAP_CS1_SIZE - flash1_size);
-        memory_region_add_subregion(address_space,
-                                OMAP_CS1_BASE + flash1_size, &cs[1]);
-
-        if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
-                                   "omap_sx1.flash1-1", flash1_size,
-                                   dinfo->bdrv, sector_size,
-                                   flash1_size / sector_size,
-                                   4, 0, 0, 0, 0, be)) {
-            fprintf(stderr, "qemu: Error registering flash memory %d.\n",
-                           fl_idx);
-        }
-        fl_idx++;
-    } else {
-        memory_region_init_io(&cs[1], &static_ops, &cs1val,
-                              "sx1.cs1", OMAP_CS1_SIZE);
-        memory_region_add_subregion(address_space,
-                                OMAP_CS1_BASE, &cs[1]);
-    }
-
-    if (!args->kernel_filename && !fl_idx) {
-        fprintf(stderr, "Kernel or Flash image must be specified\n");
-        exit(1);
-    }
-
-    /* Load the kernel.  */
-    if (args->kernel_filename) {
-        sx1_binfo.kernel_filename = args->kernel_filename;
-        sx1_binfo.kernel_cmdline = args->kernel_cmdline;
-        sx1_binfo.initrd_filename = args->initrd_filename;
-        arm_load_kernel(mpu->cpu, &sx1_binfo);
-    }
-
-    /* TODO: fix next line */
-    //~ qemu_console_resize(ds, 640, 480);
-}
-
-static void sx1_init_v1(QEMUMachineInitArgs *args)
-{
-    sx1_init(args, 1);
-}
-
-static void sx1_init_v2(QEMUMachineInitArgs *args)
-{
-    sx1_init(args, 2);
-}
-
-static QEMUMachine sx1_machine_v2 = {
-    .name = "sx1",
-    .desc = "Siemens SX1 (OMAP310) V2",
-    .init = sx1_init_v2,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine sx1_machine_v1 = {
-    .name = "sx1-v1",
-    .desc = "Siemens SX1 (OMAP310) V1",
-    .init = sx1_init_v1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void sx1_machine_init(void)
-{
-    qemu_register_machine(&sx1_machine_v2);
-    qemu_register_machine(&sx1_machine_v1);
-}
-
-machine_init(sx1_machine_init);
index 945711eff56e0d7af122fdce20ae31f91ed9ba5c..13e7280e6939857d439c14c1dd4a5a4f500e3d15 100644 (file)
@@ -17,9 +17,9 @@
  * 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 "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "omap.h"
+#include "hw/omap.h"
 struct omap_synctimer_s {
     MemoryRegion iomem;
     uint32_t val;
index e273e971ed422d14e16b872116c46d5f1f0c3a8e..181ecee1a5d115125f66a8b08d24abe4d222969c 100644 (file)
@@ -18,8 +18,8 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
 
 /* TEST-Chip-level TAP */
 static uint64_t omap_tap_read(void *opaque, hwaddr addr,
index 0ebfbf8caec5c7cf8aa4ce85dc2be7f1ded3d49a..af51ce753491a900e03a7380c9cfd13730f2e463 100644 (file)
@@ -18,9 +18,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "char/char.h"
-#include "hw.h"
-#include "omap.h"
-#include "serial.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
+#include "hw/serial.h"
 #include "exec/address-spaces.h"
 
 /* UARTs */
index 00a8738caf5b8cbc0e9af0f09fe0e7b58bf4e0f7..ddba366ef5ba60460499a2f285ad3660a40e55af 100644 (file)
  */
 
 #include "qemu-common.h"
-#include "hw.h"
-#include "flash.h"
-#include "irq.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
+#include "hw/irq.h"
 #include "sysemu/blockdev.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/error-report.h"
 
 /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
index f9ba5eeabae72404a7b543bb178013b51749fad3..be64bf2a68ac018da65a333e60446742942b9fc1 100644 (file)
@@ -31,8 +31,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
index 20a479c794f2aa42c0515fe8fd767cc5453523cc..03a7075c39c9ddd8c77e5a9a95872837d425132d 100644 (file)
  * Serial interrupts, as implemented in Raven chipset are not supported yet.
  *
  */
-#include "hw.h"
-#include "ppc/mac.h"
-#include "pci/pci.h"
-#include "openpic.h"
-#include "sysbus.h"
-#include "pci/msi.h"
+#include "hw/hw.h"
+#include "hw/ppc/mac.h"
+#include "hw/pci/pci.h"
+#include "hw/openpic.h"
+#include "hw/sysbus.h"
+#include "hw/pci/msi.h"
 #include "qemu/bitops.h"
-#include "ppc.h"
+#include "hw/ppc.h"
 
 //#define DEBUG_OPENPIC
 
index 38ff8f5d6d2fc50e9881ef14585f72f2b4caefb9..61246b149b7ed733d5756eea2bdf93029a57ea09 100644 (file)
@@ -1,3 +1,2 @@
-obj-y = openrisc_pic.o openrisc_sim.o openrisc_timer.o
-
-obj-y := $(addprefix ../,$(obj-y))
+obj-y = pic_cpu.o cputimer.o
+obj-y += openrisc_sim.o 
diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
new file mode 100644 (file)
index 0000000..f6c877f
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * QEMU OpenRISC timer support
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *                         Zhizhou Zhang <etouzh@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "hw/hw.h"
+#include "qemu/timer.h"
+
+#define TIMER_FREQ    (20 * 1000 * 1000)    /* 20MHz */
+
+/* The time when TTCR changes */
+static uint64_t last_clk;
+static int is_counting;
+
+void cpu_openrisc_count_update(OpenRISCCPU *cpu)
+{
+    uint64_t now, next;
+    uint32_t wait;
+
+    now = qemu_get_clock_ns(vm_clock);
+    if (!is_counting) {
+        qemu_del_timer(cpu->env.timer);
+        last_clk = now;
+        return;
+    }
+
+    cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
+                                        get_ticks_per_sec());
+    last_clk = now;
+
+    if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
+        wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
+        wait += cpu->env.ttmr & TTMR_TP;
+    } else {
+        wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
+    }
+
+    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
+    qemu_mod_timer(cpu->env.timer, next);
+}
+
+void cpu_openrisc_count_start(OpenRISCCPU *cpu)
+{
+    is_counting = 1;
+    cpu_openrisc_count_update(cpu);
+}
+
+void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
+{
+    is_counting = 0;
+    cpu_openrisc_count_update(cpu);
+}
+
+static void openrisc_timer_cb(void *opaque)
+{
+    OpenRISCCPU *cpu = opaque;
+
+    if ((cpu->env.ttmr & TTMR_IE) &&
+         qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
+        cpu->env.ttmr |= TTMR_IP;
+        cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
+    }
+
+    switch (cpu->env.ttmr & TTMR_M) {
+    case TIMER_NONE:
+        break;
+    case TIMER_INTR:
+        cpu->env.ttcr = 0;
+        cpu_openrisc_count_start(cpu);
+        break;
+    case TIMER_SHOT:
+        cpu_openrisc_count_stop(cpu);
+        break;
+    case TIMER_CONT:
+        cpu_openrisc_count_start(cpu);
+        break;
+    }
+}
+
+void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
+{
+    cpu->env.timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, cpu);
+    cpu->env.ttmr = 0x00000000;
+    cpu->env.ttcr = 0x00000000;
+}
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
new file mode 100644 (file)
index 0000000..db2aac8
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * OpenRISC simulator for use as an IIS.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *                         Feng Gao <gf91597@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "elf.h"
+#include "hw/serial.h"
+#include "net/net.h"
+#include "hw/loader.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "sysemu/qtest.h"
+
+#define KERNEL_LOAD_ADDR 0x100
+
+static void main_cpu_reset(void *opaque)
+{
+    OpenRISCCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+static void openrisc_sim_net_init(MemoryRegion *address_space,
+                                  hwaddr base,
+                                  hwaddr descriptors,
+                                  qemu_irq irq, NICInfo *nd)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "open_eth");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, irq);
+    memory_region_add_subregion(address_space, base,
+                                sysbus_mmio_get_region(s, 0));
+    memory_region_add_subregion(address_space, descriptors,
+                                sysbus_mmio_get_region(s, 1));
+}
+
+static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
+                                     const char *kernel_filename,
+                                     OpenRISCCPU *cpu)
+{
+    long kernel_size;
+    uint64_t elf_entry;
+    hwaddr entry;
+
+    if (kernel_filename && !qtest_enabled()) {
+        kernel_size = load_elf(kernel_filename, NULL, NULL,
+                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
+        entry = elf_entry;
+        if (kernel_size < 0) {
+            kernel_size = load_uimage(kernel_filename,
+                                      &entry, NULL, NULL);
+        }
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename,
+                                              KERNEL_LOAD_ADDR,
+                                              ram_size - KERNEL_LOAD_ADDR);
+            entry = KERNEL_LOAD_ADDR;
+        }
+
+        if (kernel_size < 0) {
+            qemu_log("QEMU: couldn't load the kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    cpu->env.pc = entry;
+}
+
+static void openrisc_sim_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+   OpenRISCCPU *cpu = NULL;
+    MemoryRegion *ram;
+    int n;
+
+    if (!cpu_model) {
+        cpu_model = "or1200";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        cpu = cpu_openrisc_init(cpu_model);
+        if (cpu == NULL) {
+            qemu_log("Unable to find CPU definition!\n");
+            exit(1);
+        }
+        qemu_register_reset(main_cpu_reset, cpu);
+        main_cpu_reset(cpu);
+    }
+
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, "openrisc.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(get_system_memory(), 0, ram);
+
+    cpu_openrisc_pic_init(cpu);
+    cpu_openrisc_clock_init(cpu);
+
+    serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
+                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+    if (nd_table[0].used) {
+        openrisc_sim_net_init(get_system_memory(), 0x92000000,
+                              0x92000400, cpu->env.irq[4], nd_table);
+    }
+
+    cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu);
+}
+
+static QEMUMachine openrisc_sim_machine = {
+    .name = "or32-sim",
+    .desc = "or32 simulation",
+    .init = openrisc_sim_init,
+    .max_cpus = 1,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void openrisc_sim_machine_init(void)
+{
+    qemu_register_machine(&openrisc_sim_machine);
+}
+
+machine_init(openrisc_sim_machine_init);
diff --git a/hw/openrisc/pic_cpu.c b/hw/openrisc/pic_cpu.c
new file mode 100644 (file)
index 0000000..931511e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * OpenRISC Programmable Interrupt Controller support.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *                         Feng Gao <gf91597@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/hw.h"
+#include "cpu.h"
+
+/* OpenRISC pic handler */
+static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
+    int i;
+    uint32_t irq_bit = 1 << irq;
+
+    if (irq > 31 || irq < 0) {
+        return;
+    }
+
+    if (level) {
+        cpu->env.picsr |= irq_bit;
+    } else {
+        cpu->env.picsr &= ~irq_bit;
+    }
+
+    for (i = 0; i < 32; i++) {
+        if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
+            cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
+        } else {
+            cpu_reset_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
+            cpu->env.picsr &= ~(1 << i);
+        }
+    }
+}
+
+void cpu_openrisc_pic_init(OpenRISCCPU *cpu)
+{
+    int i;
+    qemu_irq *qi;
+    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, cpu, NR_IRQS);
+
+    for (i = 0; i < NR_IRQS; i++) {
+        cpu->env.irq[i] = qi[i];
+    }
+}
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
deleted file mode 100644 (file)
index aaeb9a9..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * OpenRISC Programmable Interrupt Controller support.
- *
- * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
- *                         Feng Gao <gf91597@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "hw.h"
-#include "cpu.h"
-
-/* OpenRISC pic handler */
-static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
-{
-    OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
-    int i;
-    uint32_t irq_bit = 1 << irq;
-
-    if (irq > 31 || irq < 0) {
-        return;
-    }
-
-    if (level) {
-        cpu->env.picsr |= irq_bit;
-    } else {
-        cpu->env.picsr &= ~irq_bit;
-    }
-
-    for (i = 0; i < 32; i++) {
-        if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
-            cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
-        } else {
-            cpu_reset_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
-            cpu->env.picsr &= ~(1 << i);
-        }
-    }
-}
-
-void cpu_openrisc_pic_init(OpenRISCCPU *cpu)
-{
-    int i;
-    qemu_irq *qi;
-    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, cpu, NR_IRQS);
-
-    for (i = 0; i < NR_IRQS; i++) {
-        cpu->env.irq[i] = qi[i];
-    }
-}
diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c
deleted file mode 100644 (file)
index 30947de..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * OpenRISC simulator for use as an IIS.
- *
- * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
- *                         Feng Gao <gf91597@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "hw.h"
-#include "boards.h"
-#include "elf.h"
-#include "serial.h"
-#include "net/net.h"
-#include "loader.h"
-#include "exec/address-spaces.h"
-#include "sysemu/sysemu.h"
-#include "sysbus.h"
-#include "sysemu/qtest.h"
-
-#define KERNEL_LOAD_ADDR 0x100
-
-static void main_cpu_reset(void *opaque)
-{
-    OpenRISCCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-static void openrisc_sim_net_init(MemoryRegion *address_space,
-                                  hwaddr base,
-                                  hwaddr descriptors,
-                                  qemu_irq irq, NICInfo *nd)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "open_eth");
-    qdev_set_nic_properties(dev, nd);
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, irq);
-    memory_region_add_subregion(address_space, base,
-                                sysbus_mmio_get_region(s, 0));
-    memory_region_add_subregion(address_space, descriptors,
-                                sysbus_mmio_get_region(s, 1));
-}
-
-static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
-                                     const char *kernel_filename,
-                                     OpenRISCCPU *cpu)
-{
-    long kernel_size;
-    uint64_t elf_entry;
-    hwaddr entry;
-
-    if (kernel_filename && !qtest_enabled()) {
-        kernel_size = load_elf(kernel_filename, NULL, NULL,
-                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
-        entry = elf_entry;
-        if (kernel_size < 0) {
-            kernel_size = load_uimage(kernel_filename,
-                                      &entry, NULL, NULL);
-        }
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename,
-                                              KERNEL_LOAD_ADDR,
-                                              ram_size - KERNEL_LOAD_ADDR);
-            entry = KERNEL_LOAD_ADDR;
-        }
-
-        if (kernel_size < 0) {
-            qemu_log("QEMU: couldn't load the kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-    }
-
-    cpu->env.pc = entry;
-}
-
-static void openrisc_sim_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-   OpenRISCCPU *cpu = NULL;
-    MemoryRegion *ram;
-    int n;
-
-    if (!cpu_model) {
-        cpu_model = "or1200";
-    }
-
-    for (n = 0; n < smp_cpus; n++) {
-        cpu = cpu_openrisc_init(cpu_model);
-        if (cpu == NULL) {
-            qemu_log("Unable to find CPU definition!\n");
-            exit(1);
-        }
-        qemu_register_reset(main_cpu_reset, cpu);
-        main_cpu_reset(cpu);
-    }
-
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "openrisc.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(get_system_memory(), 0, ram);
-
-    cpu_openrisc_pic_init(cpu);
-    cpu_openrisc_clock_init(cpu);
-
-    serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
-                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
-
-    if (nd_table[0].used) {
-        openrisc_sim_net_init(get_system_memory(), 0x92000000,
-                              0x92000400, cpu->env.irq[4], nd_table);
-    }
-
-    cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu);
-}
-
-static QEMUMachine openrisc_sim_machine = {
-    .name = "or32-sim",
-    .desc = "or32 simulation",
-    .init = openrisc_sim_init,
-    .max_cpus = 1,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void openrisc_sim_machine_init(void)
-{
-    qemu_register_machine(&openrisc_sim_machine);
-}
-
-machine_init(openrisc_sim_machine_init);
diff --git a/hw/openrisc_timer.c b/hw/openrisc_timer.c
deleted file mode 100644 (file)
index d965be7..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * QEMU OpenRISC timer support
- *
- * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
- *                         Zhizhou Zhang <etouzh@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "cpu.h"
-#include "hw.h"
-#include "qemu/timer.h"
-
-#define TIMER_FREQ    (20 * 1000 * 1000)    /* 20MHz */
-
-/* The time when TTCR changes */
-static uint64_t last_clk;
-static int is_counting;
-
-void cpu_openrisc_count_update(OpenRISCCPU *cpu)
-{
-    uint64_t now, next;
-    uint32_t wait;
-
-    now = qemu_get_clock_ns(vm_clock);
-    if (!is_counting) {
-        qemu_del_timer(cpu->env.timer);
-        last_clk = now;
-        return;
-    }
-
-    cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
-                                        get_ticks_per_sec());
-    last_clk = now;
-
-    if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
-        wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
-        wait += cpu->env.ttmr & TTMR_TP;
-    } else {
-        wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
-    }
-
-    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
-    qemu_mod_timer(cpu->env.timer, next);
-}
-
-void cpu_openrisc_count_start(OpenRISCCPU *cpu)
-{
-    is_counting = 1;
-    cpu_openrisc_count_update(cpu);
-}
-
-void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
-{
-    is_counting = 0;
-    cpu_openrisc_count_update(cpu);
-}
-
-static void openrisc_timer_cb(void *opaque)
-{
-    OpenRISCCPU *cpu = opaque;
-
-    if ((cpu->env.ttmr & TTMR_IE) &&
-         qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
-        cpu->env.ttmr |= TTMR_IP;
-        cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
-    }
-
-    switch (cpu->env.ttmr & TTMR_M) {
-    case TIMER_NONE:
-        break;
-    case TIMER_INTR:
-        cpu->env.ttcr = 0;
-        cpu_openrisc_count_start(cpu);
-        break;
-    case TIMER_SHOT:
-        cpu_openrisc_count_stop(cpu);
-        break;
-    case TIMER_CONT:
-        cpu_openrisc_count_start(cpu);
-        break;
-    }
-}
-
-void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
-{
-    cpu->env.timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, cpu);
-    cpu->env.ttmr = 0x00000000;
-    cpu->env.ttcr = 0x00000000;
-}
diff --git a/hw/palm.c b/hw/palm.c
deleted file mode 100644 (file)
index a633dfc..0000000
--- a/hw/palm.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * PalmOne's (TM) PDAs.
- *
- * Copyright (C) 2006-2007 Andrzej Zaborowski  <balrog@zabor.org>
- *
- * 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 or
- * (at your option) version 3 of the License.
- *
- * 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 "hw.h"
-#include "audio/audio.h"
-#include "sysemu/sysemu.h"
-#include "ui/console.h"
-#include "omap.h"
-#include "boards.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "loader.h"
-#include "exec/address-spaces.h"
-
-static uint32_t static_readb(void *opaque, hwaddr offset)
-{
-    uint32_t *val = (uint32_t *) opaque;
-    return *val >> ((offset & 3) << 3);
-}
-
-static uint32_t static_readh(void *opaque, hwaddr offset)
-{
-    uint32_t *val = (uint32_t *) opaque;
-    return *val >> ((offset & 1) << 3);
-}
-
-static uint32_t static_readw(void *opaque, hwaddr offset)
-{
-    uint32_t *val = (uint32_t *) opaque;
-    return *val >> ((offset & 0) << 3);
-}
-
-static void static_write(void *opaque, hwaddr offset,
-                uint32_t value)
-{
-#ifdef SPY
-    printf("%s: value %08lx written at " PA_FMT "\n",
-                    __FUNCTION__, value, offset);
-#endif
-}
-
-static const MemoryRegionOps static_ops = {
-    .old_mmio = {
-        .read = { static_readb, static_readh, static_readw, },
-        .write = { static_write, static_write, static_write, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-/* Palm Tunsgten|E support */
-
-/* Shared GPIOs */
-#define PALMTE_USBDETECT_GPIO  0
-#define PALMTE_USB_OR_DC_GPIO  1
-#define PALMTE_TSC_GPIO                4
-#define PALMTE_PINTDAV_GPIO    6
-#define PALMTE_MMC_WP_GPIO     8
-#define PALMTE_MMC_POWER_GPIO  9
-#define PALMTE_HDQ_GPIO                11
-#define PALMTE_HEADPHONES_GPIO 14
-#define PALMTE_SPEAKER_GPIO    15
-/* MPU private GPIOs */
-#define PALMTE_DC_GPIO         2
-#define PALMTE_MMC_SWITCH_GPIO 4
-#define PALMTE_MMC1_GPIO       6
-#define PALMTE_MMC2_GPIO       7
-#define PALMTE_MMC3_GPIO       11
-
-static MouseTransformInfo palmte_pointercal = {
-    .x = 320,
-    .y = 320,
-    .a = { -5909, 8, 22465308, 104, 7644, -1219972, 65536 },
-};
-
-static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
-{
-    uWireSlave *tsc;
-
-    tsc = tsc2102_init(qdev_get_gpio_in(cpu->gpio, PALMTE_PINTDAV_GPIO));
-
-    omap_uwire_attach(cpu->microwire, tsc, 0);
-    omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
-
-    tsc210x_set_transform(tsc, &palmte_pointercal);
-}
-
-static struct {
-    int row;
-    int column;
-} palmte_keymap[0x80] = {
-    [0 ... 0x7f] = { -1, -1 },
-    [0x3b] = { 0, 0 }, /* F1   -> Calendar */
-    [0x3c] = { 1, 0 }, /* F2   -> Contacts */
-    [0x3d] = { 2, 0 }, /* F3   -> Tasks List */
-    [0x3e] = { 3, 0 }, /* F4   -> Note Pad */
-    [0x01] = { 4, 0 }, /* Esc  -> Power */
-    [0x4b] = { 0, 1 }, /*         Left */
-    [0x50] = { 1, 1 }, /*         Down */
-    [0x48] = { 2, 1 }, /*         Up */
-    [0x4d] = { 3, 1 }, /*         Right */
-    [0x4c] = { 4, 1 }, /*         Centre */
-    [0x39] = { 4, 1 }, /* Spc  -> Centre */
-};
-
-static void palmte_button_event(void *opaque, int keycode)
-{
-    struct omap_mpu_state_s *cpu = (struct omap_mpu_state_s *) opaque;
-
-    if (palmte_keymap[keycode & 0x7f].row != -1)
-        omap_mpuio_key(cpu->mpuio,
-                        palmte_keymap[keycode & 0x7f].row,
-                        palmte_keymap[keycode & 0x7f].column,
-                        !(keycode & 0x80));
-}
-
-static void palmte_onoff_gpios(void *opaque, int line, int level)
-{
-    switch (line) {
-    case 0:
-        printf("%s: current to MMC/SD card %sabled.\n",
-                        __FUNCTION__, level ? "dis" : "en");
-        break;
-    case 1:
-        printf("%s: internal speaker amplifier %s.\n",
-                        __FUNCTION__, level ? "down" : "on");
-        break;
-
-    /* These LCD & Audio output signals have not been identified yet.  */
-    case 2:
-    case 3:
-    case 4:
-        printf("%s: LCD GPIO%i %s.\n",
-                        __FUNCTION__, line - 1, level ? "high" : "low");
-        break;
-    case 5:
-    case 6:
-        printf("%s: Audio GPIO%i %s.\n",
-                        __FUNCTION__, line - 4, level ? "high" : "low");
-        break;
-    }
-}
-
-static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
-{
-    qemu_irq *misc_gpio;
-
-    omap_mmc_handlers(cpu->mmc,
-                    qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO),
-                    qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
-                            [PALMTE_MMC_SWITCH_GPIO]));
-
-    misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
-    qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO,    misc_gpio[0]);
-    qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,      misc_gpio[1]);
-    qdev_connect_gpio_out(cpu->gpio, 11,                       misc_gpio[2]);
-    qdev_connect_gpio_out(cpu->gpio, 12,                       misc_gpio[3]);
-    qdev_connect_gpio_out(cpu->gpio, 13,                       misc_gpio[4]);
-    omap_mpuio_out_set(cpu->mpuio, 1,                          misc_gpio[5]);
-    omap_mpuio_out_set(cpu->mpuio, 3,                          misc_gpio[6]);
-
-    /* Reset some inputs to initial state.  */
-    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
-    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USB_OR_DC_GPIO));
-    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, 4));
-    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_HEADPHONES_GPIO));
-    qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]);
-    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]);
-    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]);
-    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[11]);
-}
-
-static struct arm_boot_info palmte_binfo = {
-    .loader_start = OMAP_EMIFF_BASE,
-    .ram_size = 0x02000000,
-    .board_id = 0x331,
-};
-
-static void palmte_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    struct omap_mpu_state_s *mpu;
-    int flash_size = 0x00800000;
-    int sdram_size = palmte_binfo.ram_size;
-    static uint32_t cs0val = 0xffffffff;
-    static uint32_t cs1val = 0x0000e1a0;
-    static uint32_t cs2val = 0x0000e1a0;
-    static uint32_t cs3val = 0xe1a0e1a0;
-    int rom_size, rom_loaded = 0;
-    DisplayState *ds = get_displaystate();
-    MemoryRegion *flash = g_new(MemoryRegion, 1);
-    MemoryRegion *cs = g_new(MemoryRegion, 4);
-
-    mpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model);
-
-    /* External Flash (EMIFS) */
-    memory_region_init_ram(flash, "palmte.flash", flash_size);
-    vmstate_register_ram_global(flash);
-    memory_region_set_readonly(flash, true);
-    memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash);
-
-    memory_region_init_io(&cs[0], &static_ops, &cs0val, "palmte-cs0",
-                          OMAP_CS0_SIZE - flash_size);
-    memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE + flash_size,
-                                &cs[0]);
-    memory_region_init_io(&cs[1], &static_ops, &cs1val, "palmte-cs1",
-                          OMAP_CS1_SIZE);
-    memory_region_add_subregion(address_space_mem, OMAP_CS1_BASE, &cs[1]);
-    memory_region_init_io(&cs[2], &static_ops, &cs2val, "palmte-cs2",
-                          OMAP_CS2_SIZE);
-    memory_region_add_subregion(address_space_mem, OMAP_CS2_BASE, &cs[2]);
-    memory_region_init_io(&cs[3], &static_ops, &cs3val, "palmte-cs3",
-                          OMAP_CS3_SIZE);
-    memory_region_add_subregion(address_space_mem, OMAP_CS3_BASE, &cs[3]);
-
-    palmte_microwire_setup(mpu);
-
-    qemu_add_kbd_event_handler(palmte_button_event, mpu);
-
-    palmte_gpio_setup(mpu);
-
-    /* Setup initial (reset) machine state */
-    if (nb_option_roms) {
-        rom_size = get_image_size(option_rom[0].name);
-        if (rom_size > flash_size) {
-            fprintf(stderr, "%s: ROM image too big (%x > %x)\n",
-                            __FUNCTION__, rom_size, flash_size);
-            rom_size = 0;
-        }
-        if (rom_size > 0) {
-            rom_size = load_image_targphys(option_rom[0].name, OMAP_CS0_BASE,
-                                           flash_size);
-            rom_loaded = 1;
-        }
-        if (rom_size < 0) {
-            fprintf(stderr, "%s: error loading '%s'\n",
-                            __FUNCTION__, option_rom[0].name);
-        }
-    }
-
-    if (!rom_loaded && !kernel_filename) {
-        fprintf(stderr, "Kernel or ROM image must be specified\n");
-        exit(1);
-    }
-
-    /* Load the kernel.  */
-    if (kernel_filename) {
-        palmte_binfo.kernel_filename = kernel_filename;
-        palmte_binfo.kernel_cmdline = kernel_cmdline;
-        palmte_binfo.initrd_filename = initrd_filename;
-        arm_load_kernel(mpu->cpu, &palmte_binfo);
-    }
-
-    /* FIXME: We shouldn't really be doing this here.  The LCD controller
-       will set the size once configured, so this just sets an initial
-       size until the guest activates the display.  */
-    ds->surface = qemu_resize_displaysurface(ds, 320, 320);
-    dpy_gfx_resize(ds);
-}
-
-static QEMUMachine palmte_machine = {
-    .name = "cheetah",
-    .desc = "Palm Tungsten|E aka. Cheetah PDA (OMAP310)",
-    .init = palmte_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void palmte_machine_init(void)
-{
-    qemu_register_machine(&palmte_machine);
-}
-
-machine_init(palmte_machine_init);
index 1d72e88e626dec22754692c7c5dc35aa14a4fb2e..6c0061e06edc2903114c69d1aaacf8d5239c107b 100644 (file)
--- a/hw/pam.c
+++ b/hw/pam.c
@@ -27,7 +27,7 @@
  * THE SOFTWARE.
  */
 #include "sysemu/sysemu.h"
-#include "pam.h"
+#include "hw/pam.h"
 
 void smram_update(MemoryRegion *smram_region, uint8_t smram,
                   uint8_t smm_enabled)
index 3a4e06bab0c986a462302d001f6a715b4d77ed54..0b9af43d8b36425e088a65b35896b5db3ffac345 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "char/char.h"
-#include "isa.h"
-#include "pc.h"
+#include "hw/isa.h"
+#include "hw/pc.h"
 #include "sysemu/sysemu.h"
 
 //#define DEBUG_PARALLEL
index cf64a1f20356ac6fc7985c516195097585093b07..8236bce0c79b1a891744708c1fe83861ae3b62d7 100644 (file)
@@ -39,9 +39,9 @@
 #if defined(CONFIG_POSIX)
 #include <sys/mman.h>
 #endif
-#include "hw.h"
-#include "qdev.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/qdev.h"
+#include "hw/isa.h"
 
 #define IOMEM_LEN    0x10000
 
diff --git a/hw/pc.c b/hw/pc.c
deleted file mode 100644 (file)
index 07caba7..0000000
--- a/hw/pc.c
+++ /dev/null
@@ -1,1161 +0,0 @@
-/*
- * QEMU PC System Emulator
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "pc.h"
-#include "serial.h"
-#include "apic.h"
-#include "fdc.h"
-#include "ide.h"
-#include "pci/pci.h"
-#include "monitor/monitor.h"
-#include "fw_cfg.h"
-#include "hpet_emul.h"
-#include "smbios.h"
-#include "loader.h"
-#include "elf.h"
-#include "multiboot.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
-#include "pcspk.h"
-#include "pci/msi.h"
-#include "sysbus.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/kvm.h"
-#include "kvm_i386.h"
-#include "xen.h"
-#include "sysemu/blockdev.h"
-#include "hw/block-common.h"
-#include "ui/qemu-spice.h"
-#include "exec/memory.h"
-#include "exec/address-spaces.h"
-#include "sysemu/arch_init.h"
-#include "qemu/bitmap.h"
-
-/* debug PC/ISA interrupts */
-//#define DEBUG_IRQ
-
-#ifdef DEBUG_IRQ
-#define DPRINTF(fmt, ...)                                       \
-    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...)
-#endif
-
-/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables.  */
-#define ACPI_DATA_SIZE       0x10000
-#define BIOS_CFG_IOPORT 0x510
-#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
-#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
-#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
-#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
-#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
-
-#define E820_NR_ENTRIES                16
-
-struct e820_entry {
-    uint64_t address;
-    uint64_t length;
-    uint32_t type;
-} QEMU_PACKED __attribute((__aligned__(4)));
-
-struct e820_table {
-    uint32_t count;
-    struct e820_entry entry[E820_NR_ENTRIES];
-} QEMU_PACKED __attribute((__aligned__(4)));
-
-static struct e820_table e820_table;
-struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
-
-void gsi_handler(void *opaque, int n, int level)
-{
-    GSIState *s = opaque;
-
-    DPRINTF("pc: %s GSI %d\n", level ? "raising" : "lowering", n);
-    if (n < ISA_NUM_IRQS) {
-        qemu_set_irq(s->i8259_irq[n], level);
-    }
-    qemu_set_irq(s->ioapic_irq[n], level);
-}
-
-static void ioport80_write(void *opaque, hwaddr addr, uint64_t data,
-                           unsigned size)
-{
-}
-
-static uint64_t ioport80_read(void *opaque, hwaddr addr, unsigned size)
-{
-    return 0xffffffffffffffffULL;
-}
-
-/* MSDOS compatibility mode FPU exception support */
-static qemu_irq ferr_irq;
-
-void pc_register_ferr_irq(qemu_irq irq)
-{
-    ferr_irq = irq;
-}
-
-/* XXX: add IGNNE support */
-void cpu_set_ferr(CPUX86State *s)
-{
-    qemu_irq_raise(ferr_irq);
-}
-
-static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
-                           unsigned size)
-{
-    qemu_irq_lower(ferr_irq);
-}
-
-static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size)
-{
-    return 0xffffffffffffffffULL;
-}
-
-/* TSC handling */
-uint64_t cpu_get_tsc(CPUX86State *env)
-{
-    return cpu_get_ticks();
-}
-
-/* SMM support */
-
-static cpu_set_smm_t smm_set;
-static void *smm_arg;
-
-void cpu_smm_register(cpu_set_smm_t callback, void *arg)
-{
-    assert(smm_set == NULL);
-    assert(smm_arg == NULL);
-    smm_set = callback;
-    smm_arg = arg;
-}
-
-void cpu_smm_update(CPUX86State *env)
-{
-    if (smm_set && smm_arg && env == first_cpu)
-        smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
-}
-
-
-/* IRQ handling */
-int cpu_get_pic_interrupt(CPUX86State *env)
-{
-    int intno;
-
-    intno = apic_get_interrupt(env->apic_state);
-    if (intno >= 0) {
-        return intno;
-    }
-    /* read the irq from the PIC */
-    if (!apic_accept_pic_intr(env->apic_state)) {
-        return -1;
-    }
-
-    intno = pic_read_irq(isa_pic);
-    return intno;
-}
-
-static void pic_irq_request(void *opaque, int irq, int level)
-{
-    CPUX86State *env = first_cpu;
-
-    DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
-    if (env->apic_state) {
-        while (env) {
-            if (apic_accept_pic_intr(env->apic_state)) {
-                apic_deliver_pic_intr(env->apic_state, level);
-            }
-            env = env->next_cpu;
-        }
-    } else {
-        if (level)
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-/* PC cmos mappings */
-
-#define REG_EQUIPMENT_BYTE          0x14
-
-static int cmos_get_fd_drive_type(FDriveType fd0)
-{
-    int val;
-
-    switch (fd0) {
-    case FDRIVE_DRV_144:
-        /* 1.44 Mb 3"5 drive */
-        val = 4;
-        break;
-    case FDRIVE_DRV_288:
-        /* 2.88 Mb 3"5 drive */
-        val = 5;
-        break;
-    case FDRIVE_DRV_120:
-        /* 1.2 Mb 5"5 drive */
-        val = 2;
-        break;
-    case FDRIVE_DRV_NONE:
-    default:
-        val = 0;
-        break;
-    }
-    return val;
-}
-
-static void cmos_init_hd(ISADevice *s, int type_ofs, int info_ofs,
-                         int16_t cylinders, int8_t heads, int8_t sectors)
-{
-    rtc_set_memory(s, type_ofs, 47);
-    rtc_set_memory(s, info_ofs, cylinders);
-    rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
-    rtc_set_memory(s, info_ofs + 2, heads);
-    rtc_set_memory(s, info_ofs + 3, 0xff);
-    rtc_set_memory(s, info_ofs + 4, 0xff);
-    rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3));
-    rtc_set_memory(s, info_ofs + 6, cylinders);
-    rtc_set_memory(s, info_ofs + 7, cylinders >> 8);
-    rtc_set_memory(s, info_ofs + 8, sectors);
-}
-
-/* convert boot_device letter to something recognizable by the bios */
-static int boot_device2nibble(char boot_device)
-{
-    switch(boot_device) {
-    case 'a':
-    case 'b':
-        return 0x01; /* floppy boot */
-    case 'c':
-        return 0x02; /* hard drive boot */
-    case 'd':
-        return 0x03; /* CD-ROM boot */
-    case 'n':
-        return 0x04; /* Network boot */
-    }
-    return 0;
-}
-
-static int set_boot_dev(ISADevice *s, const char *boot_device, int fd_bootchk)
-{
-#define PC_MAX_BOOT_DEVICES 3
-    int nbds, bds[3] = { 0, };
-    int i;
-
-    nbds = strlen(boot_device);
-    if (nbds > PC_MAX_BOOT_DEVICES) {
-        error_report("Too many boot devices for PC");
-        return(1);
-    }
-    for (i = 0; i < nbds; i++) {
-        bds[i] = boot_device2nibble(boot_device[i]);
-        if (bds[i] == 0) {
-            error_report("Invalid boot device for PC: '%c'",
-                         boot_device[i]);
-            return(1);
-        }
-    }
-    rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
-    rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1));
-    return(0);
-}
-
-static int pc_boot_set(void *opaque, const char *boot_device)
-{
-    return set_boot_dev(opaque, boot_device, 0);
-}
-
-typedef struct pc_cmos_init_late_arg {
-    ISADevice *rtc_state;
-    BusState *idebus[2];
-} pc_cmos_init_late_arg;
-
-static void pc_cmos_init_late(void *opaque)
-{
-    pc_cmos_init_late_arg *arg = opaque;
-    ISADevice *s = arg->rtc_state;
-    int16_t cylinders;
-    int8_t heads, sectors;
-    int val;
-    int i, trans;
-
-    val = 0;
-    if (ide_get_geometry(arg->idebus[0], 0,
-                         &cylinders, &heads, &sectors) >= 0) {
-        cmos_init_hd(s, 0x19, 0x1b, cylinders, heads, sectors);
-        val |= 0xf0;
-    }
-    if (ide_get_geometry(arg->idebus[0], 1,
-                         &cylinders, &heads, &sectors) >= 0) {
-        cmos_init_hd(s, 0x1a, 0x24, cylinders, heads, sectors);
-        val |= 0x0f;
-    }
-    rtc_set_memory(s, 0x12, val);
-
-    val = 0;
-    for (i = 0; i < 4; i++) {
-        /* NOTE: ide_get_geometry() returns the physical
-           geometry.  It is always such that: 1 <= sects <= 63, 1
-           <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
-           geometry can be different if a translation is done. */
-        if (ide_get_geometry(arg->idebus[i / 2], i % 2,
-                             &cylinders, &heads, &sectors) >= 0) {
-            trans = ide_get_bios_chs_trans(arg->idebus[i / 2], i % 2) - 1;
-            assert((trans & ~3) == 0);
-            val |= trans << (i * 2);
-        }
-    }
-    rtc_set_memory(s, 0x39, val);
-
-    qemu_unregister_reset(pc_cmos_init_late, opaque);
-}
-
-void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
-                  const char *boot_device,
-                  ISADevice *floppy, BusState *idebus0, BusState *idebus1,
-                  ISADevice *s)
-{
-    int val, nb, i;
-    FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
-    static pc_cmos_init_late_arg arg;
-
-    /* various important CMOS locations needed by PC/Bochs bios */
-
-    /* memory size */
-    /* base memory (first MiB) */
-    val = MIN(ram_size / 1024, 640);
-    rtc_set_memory(s, 0x15, val);
-    rtc_set_memory(s, 0x16, val >> 8);
-    /* extended memory (next 64MiB) */
-    if (ram_size > 1024 * 1024) {
-        val = (ram_size - 1024 * 1024) / 1024;
-    } else {
-        val = 0;
-    }
-    if (val > 65535)
-        val = 65535;
-    rtc_set_memory(s, 0x17, val);
-    rtc_set_memory(s, 0x18, val >> 8);
-    rtc_set_memory(s, 0x30, val);
-    rtc_set_memory(s, 0x31, val >> 8);
-    /* memory between 16MiB and 4GiB */
-    if (ram_size > 16 * 1024 * 1024) {
-        val = (ram_size - 16 * 1024 * 1024) / 65536;
-    } else {
-        val = 0;
-    }
-    if (val > 65535)
-        val = 65535;
-    rtc_set_memory(s, 0x34, val);
-    rtc_set_memory(s, 0x35, val >> 8);
-    /* memory above 4GiB */
-    val = above_4g_mem_size / 65536;
-    rtc_set_memory(s, 0x5b, val);
-    rtc_set_memory(s, 0x5c, val >> 8);
-    rtc_set_memory(s, 0x5d, val >> 16);
-
-    /* set the number of CPU */
-    rtc_set_memory(s, 0x5f, smp_cpus - 1);
-
-    /* set boot devices, and disable floppy signature check if requested */
-    if (set_boot_dev(s, boot_device, fd_bootchk)) {
-        exit(1);
-    }
-
-    /* floppy type */
-    if (floppy) {
-        for (i = 0; i < 2; i++) {
-            fd_type[i] = isa_fdc_get_drive_type(floppy, i);
-        }
-    }
-    val = (cmos_get_fd_drive_type(fd_type[0]) << 4) |
-        cmos_get_fd_drive_type(fd_type[1]);
-    rtc_set_memory(s, 0x10, val);
-
-    val = 0;
-    nb = 0;
-    if (fd_type[0] < FDRIVE_DRV_NONE) {
-        nb++;
-    }
-    if (fd_type[1] < FDRIVE_DRV_NONE) {
-        nb++;
-    }
-    switch (nb) {
-    case 0:
-        break;
-    case 1:
-        val |= 0x01; /* 1 drive, ready for boot */
-        break;
-    case 2:
-        val |= 0x41; /* 2 drives, ready for boot */
-        break;
-    }
-    val |= 0x02; /* FPU is there */
-    val |= 0x04; /* PS/2 mouse installed */
-    rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
-
-    /* hard drives */
-    arg.rtc_state = s;
-    arg.idebus[0] = idebus0;
-    arg.idebus[1] = idebus1;
-    qemu_register_reset(pc_cmos_init_late, &arg);
-}
-
-/* port 92 stuff: could be split off */
-typedef struct Port92State {
-    ISADevice dev;
-    MemoryRegion io;
-    uint8_t outport;
-    qemu_irq *a20_out;
-} Port92State;
-
-static void port92_write(void *opaque, hwaddr addr, uint64_t val,
-                         unsigned size)
-{
-    Port92State *s = opaque;
-
-    DPRINTF("port92: write 0x%02x\n", val);
-    s->outport = val;
-    qemu_set_irq(*s->a20_out, (val >> 1) & 1);
-    if (val & 1) {
-        qemu_system_reset_request();
-    }
-}
-
-static uint64_t port92_read(void *opaque, hwaddr addr,
-                            unsigned size)
-{
-    Port92State *s = opaque;
-    uint32_t ret;
-
-    ret = s->outport;
-    DPRINTF("port92: read 0x%02x\n", ret);
-    return ret;
-}
-
-static void port92_init(ISADevice *dev, qemu_irq *a20_out)
-{
-    Port92State *s = DO_UPCAST(Port92State, dev, dev);
-
-    s->a20_out = a20_out;
-}
-
-static const VMStateDescription vmstate_port92_isa = {
-    .name = "port92",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_UINT8(outport, Port92State),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void port92_reset(DeviceState *d)
-{
-    Port92State *s = container_of(d, Port92State, dev.qdev);
-
-    s->outport &= ~1;
-}
-
-static const MemoryRegionOps port92_ops = {
-    .read = port92_read,
-    .write = port92_write,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 1,
-    },
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static int port92_initfn(ISADevice *dev)
-{
-    Port92State *s = DO_UPCAST(Port92State, dev, dev);
-
-    memory_region_init_io(&s->io, &port92_ops, s, "port92", 1);
-    isa_register_ioport(dev, &s->io, 0x92);
-
-    s->outport = 0;
-    return 0;
-}
-
-static void port92_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
-    ic->init = port92_initfn;
-    dc->no_user = 1;
-    dc->reset = port92_reset;
-    dc->vmsd = &vmstate_port92_isa;
-}
-
-static const TypeInfo port92_info = {
-    .name          = "port92",
-    .parent        = TYPE_ISA_DEVICE,
-    .instance_size = sizeof(Port92State),
-    .class_init    = port92_class_initfn,
-};
-
-static void port92_register_types(void)
-{
-    type_register_static(&port92_info);
-}
-
-type_init(port92_register_types)
-
-static void handle_a20_line_change(void *opaque, int irq, int level)
-{
-    X86CPU *cpu = opaque;
-
-    /* XXX: send to all CPUs ? */
-    /* XXX: add logic to handle multiple A20 line sources */
-    x86_cpu_set_a20(cpu, level);
-}
-
-int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
-{
-    int index = le32_to_cpu(e820_table.count);
-    struct e820_entry *entry;
-
-    if (index >= E820_NR_ENTRIES)
-        return -EBUSY;
-    entry = &e820_table.entry[index++];
-
-    entry->address = cpu_to_le64(address);
-    entry->length = cpu_to_le64(length);
-    entry->type = cpu_to_le32(type);
-
-    e820_table.count = cpu_to_le32(index);
-    return index;
-}
-
-/* Calculates the limit to CPU APIC ID values
- *
- * This function returns the limit for the APIC ID value, so that all
- * CPU APIC IDs are < pc_apic_id_limit().
- *
- * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
- */
-static unsigned int pc_apic_id_limit(unsigned int max_cpus)
-{
-    return x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
-}
-
-static void *bochs_bios_init(void)
-{
-    void *fw_cfg;
-    uint8_t *smbios_table;
-    size_t smbios_len;
-    uint64_t *numa_fw_cfg;
-    int i, j;
-    unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
-
-    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
-    /* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86:
-     *
-     * SeaBIOS needs FW_CFG_MAX_CPUS for CPU hotplug, but the CPU hotplug
-     * QEMU<->SeaBIOS interface is not based on the "CPU index", but on the APIC
-     * ID of hotplugged CPUs[1]. This means that FW_CFG_MAX_CPUS is not the
-     * "maximum number of CPUs", but the "limit to the APIC ID values SeaBIOS
-     * may see".
-     *
-     * So, this means we must not use max_cpus, here, but the maximum possible
-     * APIC ID value, plus one.
-     *
-     * [1] The only kind of "CPU identifier" used between SeaBIOS and QEMU is
-     *     the APIC ID, not the "CPU index"
-     */
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)apic_id_limit);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
-                     acpi_tables, acpi_tables_len);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
-
-    smbios_table = smbios_get_table(&smbios_len);
-    if (smbios_table)
-        fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
-                         smbios_table, smbios_len);
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
-                     &e820_table, sizeof(e820_table));
-
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, &hpet_cfg, sizeof(hpet_cfg));
-    /* allocate memory for the NUMA channel: one (64bit) word for the number
-     * of nodes, one word for each VCPU->node and one word for each node to
-     * hold the amount of memory.
-     */
-    numa_fw_cfg = g_new0(uint64_t, 1 + apic_id_limit + nb_numa_nodes);
-    numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
-    for (i = 0; i < max_cpus; i++) {
-        unsigned int apic_id = x86_cpu_apic_id_from_index(i);
-        assert(apic_id < apic_id_limit);
-        for (j = 0; j < nb_numa_nodes; j++) {
-            if (test_bit(i, node_cpumask[j])) {
-                numa_fw_cfg[apic_id + 1] = cpu_to_le64(j);
-                break;
-            }
-        }
-    }
-    for (i = 0; i < nb_numa_nodes; i++) {
-        numa_fw_cfg[apic_id_limit + 1 + i] = cpu_to_le64(node_mem[i]);
-    }
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg,
-                     (1 + apic_id_limit + nb_numa_nodes) *
-                     sizeof(*numa_fw_cfg));
-
-    return fw_cfg;
-}
-
-static long get_file_size(FILE *f)
-{
-    long where, size;
-
-    /* XXX: on Unix systems, using fstat() probably makes more sense */
-
-    where = ftell(f);
-    fseek(f, 0, SEEK_END);
-    size = ftell(f);
-    fseek(f, where, SEEK_SET);
-
-    return size;
-}
-
-static void load_linux(void *fw_cfg,
-                       const char *kernel_filename,
-                      const char *initrd_filename,
-                      const char *kernel_cmdline,
-                       hwaddr max_ram_size)
-{
-    uint16_t protocol;
-    int setup_size, kernel_size, initrd_size = 0, cmdline_size;
-    uint32_t initrd_max;
-    uint8_t header[8192], *setup, *kernel, *initrd_data;
-    hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
-    FILE *f;
-    char *vmode;
-
-    /* Align to 16 bytes as a paranoia measure */
-    cmdline_size = (strlen(kernel_cmdline)+16) & ~15;
-
-    /* load the kernel header */
-    f = fopen(kernel_filename, "rb");
-    if (!f || !(kernel_size = get_file_size(f)) ||
-       fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
-       MIN(ARRAY_SIZE(header), kernel_size)) {
-       fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
-               kernel_filename, strerror(errno));
-       exit(1);
-    }
-
-    /* kernel protocol version */
-#if 0
-    fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));
-#endif
-    if (ldl_p(header+0x202) == 0x53726448)
-       protocol = lduw_p(header+0x206);
-    else {
-       /* This looks like a multiboot kernel. If it is, let's stop
-          treating it like a Linux kernel. */
-        if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
-                           kernel_cmdline, kernel_size, header))
-            return;
-       protocol = 0;
-    }
-
-    if (protocol < 0x200 || !(header[0x211] & 0x01)) {
-       /* Low kernel */
-       real_addr    = 0x90000;
-       cmdline_addr = 0x9a000 - cmdline_size;
-       prot_addr    = 0x10000;
-    } else if (protocol < 0x202) {
-       /* High but ancient kernel */
-       real_addr    = 0x90000;
-       cmdline_addr = 0x9a000 - cmdline_size;
-       prot_addr    = 0x100000;
-    } else {
-       /* High and recent kernel */
-       real_addr    = 0x10000;
-       cmdline_addr = 0x20000;
-       prot_addr    = 0x100000;
-    }
-
-#if 0
-    fprintf(stderr,
-           "qemu: real_addr     = 0x" TARGET_FMT_plx "\n"
-           "qemu: cmdline_addr  = 0x" TARGET_FMT_plx "\n"
-           "qemu: prot_addr     = 0x" TARGET_FMT_plx "\n",
-           real_addr,
-           cmdline_addr,
-           prot_addr);
-#endif
-
-    /* highest address for loading the initrd */
-    if (protocol >= 0x203)
-       initrd_max = ldl_p(header+0x22c);
-    else
-       initrd_max = 0x37ffffff;
-
-    if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)
-       initrd_max = max_ram_size-ACPI_DATA_SIZE-1;
-
-    fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline)+1);
-    fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
-
-    if (protocol >= 0x202) {
-       stl_p(header+0x228, cmdline_addr);
-    } else {
-       stw_p(header+0x20, 0xA33F);
-       stw_p(header+0x22, cmdline_addr-real_addr);
-    }
-
-    /* handle vga= parameter */
-    vmode = strstr(kernel_cmdline, "vga=");
-    if (vmode) {
-        unsigned int video_mode;
-        /* skip "vga=" */
-        vmode += 4;
-        if (!strncmp(vmode, "normal", 6)) {
-            video_mode = 0xffff;
-        } else if (!strncmp(vmode, "ext", 3)) {
-            video_mode = 0xfffe;
-        } else if (!strncmp(vmode, "ask", 3)) {
-            video_mode = 0xfffd;
-        } else {
-            video_mode = strtol(vmode, NULL, 0);
-        }
-        stw_p(header+0x1fa, video_mode);
-    }
-
-    /* loader type */
-    /* High nybble = B reserved for QEMU; low nybble is revision number.
-       If this code is substantially changed, you may want to consider
-       incrementing the revision. */
-    if (protocol >= 0x200)
-       header[0x210] = 0xB0;
-
-    /* heap */
-    if (protocol >= 0x201) {
-       header[0x211] |= 0x80;  /* CAN_USE_HEAP */
-       stw_p(header+0x224, cmdline_addr-real_addr-0x200);
-    }
-
-    /* load initrd */
-    if (initrd_filename) {
-       if (protocol < 0x200) {
-           fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
-           exit(1);
-       }
-
-       initrd_size = get_image_size(initrd_filename);
-        if (initrd_size < 0) {
-            fprintf(stderr, "qemu: error reading initrd %s\n",
-                    initrd_filename);
-            exit(1);
-        }
-
-        initrd_addr = (initrd_max-initrd_size) & ~4095;
-
-        initrd_data = g_malloc(initrd_size);
-        load_image(initrd_filename, initrd_data);
-
-        fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
-        fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
-        fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size);
-
-       stl_p(header+0x218, initrd_addr);
-       stl_p(header+0x21c, initrd_size);
-    }
-
-    /* load kernel and setup */
-    setup_size = header[0x1f1];
-    if (setup_size == 0)
-       setup_size = 4;
-    setup_size = (setup_size+1)*512;
-    kernel_size -= setup_size;
-
-    setup  = g_malloc(setup_size);
-    kernel = g_malloc(kernel_size);
-    fseek(f, 0, SEEK_SET);
-    if (fread(setup, 1, setup_size, f) != setup_size) {
-        fprintf(stderr, "fread() failed\n");
-        exit(1);
-    }
-    if (fread(kernel, 1, kernel_size, f) != kernel_size) {
-        fprintf(stderr, "fread() failed\n");
-        exit(1);
-    }
-    fclose(f);
-    memcpy(setup, header, MIN(sizeof(header), setup_size));
-
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
-
-    fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
-
-    option_rom[nb_option_roms].name = "linuxboot.bin";
-    option_rom[nb_option_roms].bootindex = 0;
-    nb_option_roms++;
-}
-
-#define NE2000_NB_MAX 6
-
-static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
-                                              0x280, 0x380 };
-static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
-
-static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
-static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
-
-void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
-{
-    static int nb_ne2k = 0;
-
-    if (nb_ne2k == NE2000_NB_MAX)
-        return;
-    isa_ne2000_init(bus, ne2000_io[nb_ne2k],
-                    ne2000_irq[nb_ne2k], nd);
-    nb_ne2k++;
-}
-
-DeviceState *cpu_get_current_apic(void)
-{
-    if (cpu_single_env) {
-        return cpu_single_env->apic_state;
-    } else {
-        return NULL;
-    }
-}
-
-void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
-{
-    CPUX86State *s = opaque;
-
-    if (level) {
-        cpu_interrupt(s, CPU_INTERRUPT_SMI);
-    }
-}
-
-void pc_cpus_init(const char *cpu_model)
-{
-    int i;
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-#ifdef TARGET_X86_64
-        cpu_model = "qemu64";
-#else
-        cpu_model = "qemu32";
-#endif
-    }
-
-    for (i = 0; i < smp_cpus; i++) {
-        if (!cpu_x86_init(cpu_model)) {
-            exit(1);
-        }
-    }
-}
-
-void pc_acpi_init(const char *default_dsdt)
-{
-    char *filename = NULL, *arg = NULL;
-
-    if (acpi_tables != NULL) {
-        /* manually set via -acpitable, leave it alone */
-        return;
-    }
-
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt);
-    if (filename == NULL) {
-        fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt);
-        return;
-    }
-
-    arg = g_strdup_printf("file=%s", filename);
-    if (acpi_table_add(arg) != 0) {
-        fprintf(stderr, "WARNING: failed to load %s\n", filename);
-    }
-    g_free(arg);
-    g_free(filename);
-}
-
-void *pc_memory_init(MemoryRegion *system_memory,
-                    const char *kernel_filename,
-                    const char *kernel_cmdline,
-                    const char *initrd_filename,
-                    ram_addr_t below_4g_mem_size,
-                    ram_addr_t above_4g_mem_size,
-                    MemoryRegion *rom_memory,
-                    MemoryRegion **ram_memory)
-{
-    int linux_boot, i;
-    MemoryRegion *ram, *option_rom_mr;
-    MemoryRegion *ram_below_4g, *ram_above_4g;
-    void *fw_cfg;
-
-    linux_boot = (kernel_filename != NULL);
-
-    /* Allocate RAM.  We allocate it as a single memory region and use
-     * aliases to address portions of it, mostly for backwards compatibility
-     * with older qemus that used qemu_ram_alloc().
-     */
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "pc.ram",
-                           below_4g_mem_size + above_4g_mem_size);
-    vmstate_register_ram_global(ram);
-    *ram_memory = ram;
-    ram_below_4g = g_malloc(sizeof(*ram_below_4g));
-    memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
-                             0, below_4g_mem_size);
-    memory_region_add_subregion(system_memory, 0, ram_below_4g);
-    if (above_4g_mem_size > 0) {
-        ram_above_4g = g_malloc(sizeof(*ram_above_4g));
-        memory_region_init_alias(ram_above_4g, "ram-above-4g", ram,
-                                 below_4g_mem_size, above_4g_mem_size);
-        memory_region_add_subregion(system_memory, 0x100000000ULL,
-                                    ram_above_4g);
-    }
-
-
-    /* Initialize PC system firmware */
-    pc_system_firmware_init(rom_memory);
-
-    option_rom_mr = g_malloc(sizeof(*option_rom_mr));
-    memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE);
-    vmstate_register_ram_global(option_rom_mr);
-    memory_region_add_subregion_overlap(rom_memory,
-                                        PC_ROM_MIN_VGA,
-                                        option_rom_mr,
-                                        1);
-
-    fw_cfg = bochs_bios_init();
-    rom_set_fw(fw_cfg);
-
-    if (linux_boot) {
-        load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
-    }
-
-    for (i = 0; i < nb_option_roms; i++) {
-        rom_add_option(option_rom[i].name, option_rom[i].bootindex);
-    }
-    return fw_cfg;
-}
-
-qemu_irq *pc_allocate_cpu_irq(void)
-{
-    return qemu_allocate_irqs(pic_irq_request, NULL, 1);
-}
-
-DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
-{
-    DeviceState *dev = NULL;
-
-    if (pci_bus) {
-        PCIDevice *pcidev = pci_vga_init(pci_bus);
-        dev = pcidev ? &pcidev->qdev : NULL;
-    } else if (isa_bus) {
-        ISADevice *isadev = isa_vga_init(isa_bus);
-        dev = isadev ? &isadev->qdev : NULL;
-    }
-    return dev;
-}
-
-static void cpu_request_exit(void *opaque, int irq, int level)
-{
-    CPUX86State *env = cpu_single_env;
-
-    if (env && level) {
-        cpu_exit(env);
-    }
-}
-
-static const MemoryRegionOps ioport80_io_ops = {
-    .write = ioport80_write,
-    .read = ioport80_read,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 1,
-    },
-};
-
-static const MemoryRegionOps ioportF0_io_ops = {
-    .write = ioportF0_write,
-    .read = ioportF0_read,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 1,
-    },
-};
-
-void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
-                          ISADevice **rtc_state,
-                          ISADevice **floppy,
-                          bool no_vmport)
-{
-    int i;
-    DriveInfo *fd[MAX_FD];
-    DeviceState *hpet = NULL;
-    int pit_isa_irq = 0;
-    qemu_irq pit_alt_irq = NULL;
-    qemu_irq rtc_irq = NULL;
-    qemu_irq *a20_line;
-    ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
-    qemu_irq *cpu_exit_irq;
-    MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
-    MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
-
-    memory_region_init_io(ioport80_io, &ioport80_io_ops, NULL, "ioport80", 1);
-    memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io);
-
-    memory_region_init_io(ioportF0_io, &ioportF0_io_ops, NULL, "ioportF0", 1);
-    memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
-
-    /*
-     * Check if an HPET shall be created.
-     *
-     * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT
-     * when the HPET wants to take over. Thus we have to disable the latter.
-     */
-    if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {
-        hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
-
-        if (hpet) {
-            for (i = 0; i < GSI_NUM_PINS; i++) {
-                sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]);
-            }
-            pit_isa_irq = -1;
-            pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
-            rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);
-        }
-    }
-    *rtc_state = rtc_init(isa_bus, 2000, rtc_irq);
-
-    qemu_register_boot_set(pc_boot_set, *rtc_state);
-
-    if (!xen_enabled()) {
-        if (kvm_irqchip_in_kernel()) {
-            pit = kvm_pit_init(isa_bus, 0x40);
-        } else {
-            pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
-        }
-        if (hpet) {
-            /* connect PIT to output control line of the HPET */
-            qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
-        }
-        pcspk_init(isa_bus, pit);
-    }
-
-    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_hds[i]) {
-            serial_isa_init(isa_bus, i, serial_hds[i]);
-        }
-    }
-
-    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
-        if (parallel_hds[i]) {
-            parallel_init(isa_bus, i, parallel_hds[i]);
-        }
-    }
-
-    a20_line = qemu_allocate_irqs(handle_a20_line_change,
-                                  x86_env_get_cpu(first_cpu), 2);
-    i8042 = isa_create_simple(isa_bus, "i8042");
-    i8042_setup_a20_line(i8042, &a20_line[0]);
-    if (!no_vmport) {
-        vmport_init(isa_bus);
-        vmmouse = isa_try_create(isa_bus, "vmmouse");
-    } else {
-        vmmouse = NULL;
-    }
-    if (vmmouse) {
-        qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
-        qdev_init_nofail(&vmmouse->qdev);
-    }
-    port92 = isa_create_simple(isa_bus, "port92");
-    port92_init(port92, &a20_line[1]);
-
-    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
-    DMA_init(0, cpu_exit_irq);
-
-    for(i = 0; i < MAX_FD; i++) {
-        fd[i] = drive_get(IF_FLOPPY, 0, i);
-    }
-    *floppy = fdctrl_init_isa(isa_bus, fd);
-}
-
-void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus)
-{
-    int i;
-
-    for (i = 0; i < nb_nics; i++) {
-        NICInfo *nd = &nd_table[i];
-
-        if (!pci_bus || (nd->model && strcmp(nd->model, "ne2k_isa") == 0)) {
-            pc_init_ne2k_isa(isa_bus, nd);
-        } else {
-            pci_nic_init_nofail(nd, "e1000", NULL);
-        }
-    }
-}
-
-void pc_pci_device_init(PCIBus *pci_bus)
-{
-    int max_bus;
-    int bus;
-
-    max_bus = drive_get_max_bus(IF_SCSI);
-    for (bus = 0; bus <= max_bus; bus++) {
-        pci_create_simple(pci_bus, -1, "lsi53c895a");
-    }
-}
-
-void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
-{
-    DeviceState *dev;
-    SysBusDevice *d;
-    unsigned int i;
-
-    if (kvm_irqchip_in_kernel()) {
-        dev = qdev_create(NULL, "kvm-ioapic");
-    } else {
-        dev = qdev_create(NULL, "ioapic");
-    }
-    if (parent_name) {
-        object_property_add_child(object_resolve_path(parent_name, NULL),
-                                  "ioapic", OBJECT(dev), NULL);
-    }
-    qdev_init_nofail(dev);
-    d = SYS_BUS_DEVICE(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);
-    }
-}
diff --git a/hw/pc.h b/hw/pc.h
index f2c1b1c2a4a2d6265711f90c1934f1d4a7076f97..dbbd8cde9eff07769b121a31a734291fe316fd6d 100644 (file)
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -4,11 +4,11 @@
 #include "qemu-common.h"
 #include "exec/memory.h"
 #include "exec/ioport.h"
-#include "isa.h"
-#include "fdc.h"
+#include "hw/isa.h"
+#include "hw/fdc.h"
 #include "net/net.h"
 #include "exec/memory.h"
-#include "ioapic.h"
+#include "hw/ioapic.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
index 38af4c1d107c1731f3a70bb9bfbe7f7495820bc2..c4e4c6273bd3fa1855e921ccc0da4645e8e8de13 100644 (file)
@@ -23,7 +23,8 @@
  * THE SOFTWARE.
  */
 
-#include "pc87312.h"
+#include "hw/pc87312.h"
+#include "qemu/error-report.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
 #include "char/char.h"
index 7b9e6f613201eb374115c6c1683b4fd5153b47ab..ad087c73e5a8cbaecd96a92df6b4af1a81d5ba48 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef QEMU_PC87312_H
 #define QEMU_PC87312_H
 
-#include "isa.h"
+#include "hw/isa.h"
 
 
 #define TYPE_PC87312 "pc87312"
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
deleted file mode 100644 (file)
index a305e1f..0000000
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * QEMU PC System Emulator
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <glib.h>
-
-#include "hw.h"
-#include "pc.h"
-#include "apic.h"
-#include "pci/pci.h"
-#include "pci/pci_ids.h"
-#include "usb.h"
-#include "net/net.h"
-#include "boards.h"
-#include "ide.h"
-#include "sysemu/kvm.h"
-#include "kvm/clock.h"
-#include "sysemu/sysemu.h"
-#include "sysbus.h"
-#include "sysemu/arch_init.h"
-#include "sysemu/blockdev.h"
-#include "smbus.h"
-#include "xen.h"
-#include "exec/memory.h"
-#include "exec/address-spaces.h"
-#include "cpu.h"
-#ifdef CONFIG_XEN
-#  include <xen/hvm/hvm_info_table.h>
-#endif
-
-#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 };
-
-/* PC hardware initialisation */
-static void pc_init1(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);
-    pc_acpi_init("acpi-dsdt.aml");
-
-    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()) {
-        fw_cfg = pc_memory_init(system_memory,
-                       kernel_filename, kernel_cmdline, initrd_filename,
-                       below_4g_mem_size, above_4g_mem_size,
-                       rom_memory, &ram_memory);
-    }
-
-    gsi_state = g_malloc0(sizeof(*gsi_state));
-    if (kvm_irqchip_in_kernel()) {
-        kvm_pc_setup_irq_routing(pci_enabled);
-        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
-                                 GSI_NUM_PINS);
-    } else {
-        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
-    }
-
-    if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
-                              system_memory, system_io, ram_size,
-                              below_4g_mem_size,
-                              0x100000000ULL - below_4g_mem_size,
-                              0x100000000ULL + above_4g_mem_size,
-                              (sizeof(hwaddr) == 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(gsi_state, "i440fx");
-    }
-
-    pc_register_ferr_irq(gsi[13]);
-
-    pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
-    if (xen_enabled()) {
-        pci_create_simple(pci_bus, -1, "xen-platform");
-    }
-
-    /* init basic PC hardware */
-    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());
-
-    pc_nic_init(isa_bus, pci_bus);
-
-    ide_drive_get(hd, MAX_IDE_BUS);
-    if (pci_enabled) {
-        PCIDevice *dev;
-        if (xen_enabled()) {
-            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
-        } else {
-            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
-        }
-        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
-        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
-    } else {
-        for(i = 0; i < MAX_IDE_BUS; i++) {
-            ISADevice *dev;
-            dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
-                               ide_irq[i],
-                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
-            idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
-        }
-    }
-
-    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(false)) {
-        pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
-    }
-
-    if (pci_enabled && acpi_enabled) {
-        i2c_bus *smbus;
-
-        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
-        /* TODO: Populate SPD eeprom data.  */
-        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
-                              gsi[9], *smi_irq,
-                              kvm_enabled(), fw_cfg);
-        smbus_eeprom_init(smbus, 8, NULL, 0);
-    }
-
-    if (pci_enabled) {
-        pc_pci_device_init(pci_bus);
-    }
-}
-
-static void pc_init_pci(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    pc_init1(get_system_memory(),
-             get_system_io(),
-             ram_size, boot_device,
-             kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 1, 1);
-}
-
-static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
-{
-    enable_compat_apic_id_mode();
-    pc_init_pci(args);
-}
-
-/* PC machine init function for pc-0.14 to pc-1.2 */
-static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
-{
-    disable_kvm_pv_eoi();
-    pc_init_pci_1_3(args);
-}
-
-/* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
-static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    disable_kvm_pv_eoi();
-    enable_compat_apic_id_mode();
-    pc_init1(get_system_memory(),
-             get_system_io(),
-             ram_size, boot_device,
-             kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 1, 0);
-}
-
-static void pc_init_isa(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    if (cpu_model == NULL)
-        cpu_model = "486";
-    disable_kvm_pv_eoi();
-    enable_compat_apic_id_mode();
-    pc_init1(get_system_memory(),
-             get_system_io(),
-             ram_size, boot_device,
-             kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 0, 1);
-}
-
-#ifdef CONFIG_XEN
-static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
-{
-    if (xen_hvm_init() != 0) {
-        hw_error("xen hardware virtual machine initialisation failed");
-    }
-    pc_init_pci_no_kvmclock(args);
-    xen_vcpu_init();
-}
-#endif
-
-static QEMUMachine pc_i440fx_machine_v1_5 = {
-    .name = "pc-i440fx-1.5",
-    .alias = "pc",
-    .desc = "Standard PC (i440FX + PIIX, 1996)",
-    .init = pc_init_pci,
-    .max_cpus = 255,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine pc_i440fx_machine_v1_4 = {
-    .name = "pc-i440fx-1.4",
-    .desc = "Standard PC (i440FX + PIIX, 1996)",
-    .init = pc_init_pci,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_4,
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_1_3 \
-       PC_COMPAT_1_4, \
-        {\
-            .driver   = "usb-tablet",\
-            .property = "usb_version",\
-            .value    = stringify(1),\
-        },{\
-            .driver   = "virtio-net-pci",\
-            .property = "ctrl_mac_addr",\
-            .value    = "off",      \
-        },{ \
-            .driver   = "virtio-net-pci", \
-            .property = "mq", \
-            .value    = "off", \
-        }, {\
-            .driver   = "e1000",\
-            .property = "autonegotiation",\
-            .value    = "off",\
-        }
-
-static QEMUMachine pc_machine_v1_3 = {
-    .name = "pc-1.3",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_3,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_3,
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_1_2 \
-        PC_COMPAT_1_3,\
-        {\
-            .driver   = "nec-usb-xhci",\
-            .property = "msi",\
-            .value    = "off",\
-        },{\
-            .driver   = "nec-usb-xhci",\
-            .property = "msix",\
-            .value    = "off",\
-        },{\
-            .driver   = "ivshmem",\
-            .property = "use64",\
-            .value    = "0",\
-        },{\
-            .driver   = "qxl",\
-            .property = "revision",\
-            .value    = stringify(3),\
-        },{\
-            .driver   = "qxl-vga",\
-            .property = "revision",\
-            .value    = stringify(3),\
-        },{\
-            .driver   = "VGA",\
-            .property = "mmio",\
-            .value    = "off",\
-        }
-
-static QEMUMachine pc_machine_v1_2 = {
-    .name = "pc-1.2",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_2,
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_1_1 \
-        PC_COMPAT_1_2,\
-        {\
-            .driver   = "virtio-scsi-pci",\
-            .property = "hotplug",\
-            .value    = "off",\
-        },{\
-            .driver   = "virtio-scsi-pci",\
-            .property = "param_change",\
-            .value    = "off",\
-        },{\
-            .driver   = "VGA",\
-            .property = "vgamem_mb",\
-            .value    = stringify(8),\
-        },{\
-            .driver   = "vmware-svga",\
-            .property = "vgamem_mb",\
-            .value    = stringify(8),\
-        },{\
-            .driver   = "qxl-vga",\
-            .property = "vgamem_mb",\
-            .value    = stringify(8),\
-        },{\
-            .driver   = "qxl",\
-            .property = "vgamem_mb",\
-            .value    = stringify(8),\
-        },{\
-            .driver   = "virtio-blk-pci",\
-            .property = "config-wce",\
-            .value    = "off",\
-        }
-
-static QEMUMachine pc_machine_v1_1 = {
-    .name = "pc-1.1",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_1,
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_1_0 \
-        PC_COMPAT_1_1,\
-        {\
-            .driver   = "pc-sysfw",\
-            .property = "rom_only",\
-            .value    = stringify(1),\
-        }, {\
-            .driver   = "isa-fdc",\
-            .property = "check_media_rate",\
-            .value    = "off",\
-        }, {\
-            .driver   = "virtio-balloon-pci",\
-            .property = "class",\
-            .value    = stringify(PCI_CLASS_MEMORY_RAM),\
-        },{\
-            .driver   = "apic",\
-            .property = "vapic",\
-            .value    = "off",\
-        },{\
-            .driver   = TYPE_USB_DEVICE,\
-            .property = "full-path",\
-            .value    = "no",\
-        }
-
-static QEMUMachine pc_machine_v1_0 = {
-    .name = "pc-1.0",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_0,
-        { /* end of list */ }
-    },
-    .hw_version = "1.0",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_0_15 \
-        PC_COMPAT_1_0
-
-static QEMUMachine pc_machine_v0_15 = {
-    .name = "pc-0.15",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_15,
-        { /* end of list */ }
-    },
-    .hw_version = "0.15",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_0_14 \
-        PC_COMPAT_0_15,\
-        {\
-            .driver   = "virtio-blk-pci",\
-            .property = "event_idx",\
-            .value    = "off",\
-        },{\
-            .driver   = "virtio-serial-pci",\
-            .property = "event_idx",\
-            .value    = "off",\
-        },{\
-            .driver   = "virtio-net-pci",\
-            .property = "event_idx",\
-            .value    = "off",\
-        },{\
-            .driver   = "virtio-balloon-pci",\
-            .property = "event_idx",\
-            .value    = "off",\
-        }
-
-static QEMUMachine pc_machine_v0_14 = {
-    .name = "pc-0.14",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_14, 
-        {
-            .driver   = "qxl",
-            .property = "revision",
-            .value    = stringify(2),
-        },{
-            .driver   = "qxl-vga",
-            .property = "revision",
-            .value    = stringify(2),
-        },
-        { /* end of list */ }
-    },
-    .hw_version = "0.14",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_0_13 \
-        PC_COMPAT_0_14,\
-        {\
-            .driver   = TYPE_PCI_DEVICE,\
-            .property = "command_serr_enable",\
-            .value    = "off",\
-        },{\
-            .driver   = "AC97",\
-            .property = "use_broken_id",\
-            .value    = stringify(1),\
-        }
-
-static QEMUMachine pc_machine_v0_13 = {
-    .name = "pc-0.13",
-    .desc = "Standard PC",
-    .init = pc_init_pci_no_kvmclock,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_13,
-        {
-            .driver   = "virtio-9p-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
-            .driver   = "VGA",
-            .property = "rombar",
-            .value    = stringify(0),
-        },{
-            .driver   = "vmware-svga",
-            .property = "rombar",
-            .value    = stringify(0),
-        },
-        { /* end of list */ }
-    },
-    .hw_version = "0.13",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_0_12 \
-        PC_COMPAT_0_13,\
-        {\
-            .driver   = "virtio-serial-pci",\
-            .property = "max_ports",\
-            .value    = stringify(1),\
-        },{\
-            .driver   = "virtio-serial-pci",\
-            .property = "vectors",\
-            .value    = stringify(0),\
-        }
-
-static QEMUMachine pc_machine_v0_12 = {
-    .name = "pc-0.12",
-    .desc = "Standard PC",
-    .init = pc_init_pci_no_kvmclock,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_12,
-        {
-            .driver   = "VGA",
-            .property = "rombar",
-            .value    = stringify(0),
-        },{
-            .driver   = "vmware-svga",
-            .property = "rombar",
-            .value    = stringify(0),
-        },
-        { /* end of list */ }
-    },
-    .hw_version = "0.12",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_0_11 \
-        PC_COMPAT_0_12,\
-        {\
-            .driver   = "virtio-blk-pci",\
-            .property = "vectors",\
-            .value    = stringify(0),\
-        },{\
-            .driver   = TYPE_PCI_DEVICE,\
-            .property = "rombar",\
-            .value    = stringify(0),\
-        }
-
-static QEMUMachine pc_machine_v0_11 = {
-    .name = "pc-0.11",
-    .desc = "Standard PC, qemu 0.11",
-    .init = pc_init_pci_no_kvmclock,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_11,
-        {
-            .driver   = "ide-drive",
-            .property = "ver",
-            .value    = "0.11",
-        },{
-            .driver   = "scsi-disk",
-            .property = "ver",
-            .value    = "0.11",
-        },
-        { /* end of list */ }
-    },
-    .hw_version = "0.11",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine pc_machine_v0_10 = {
-    .name = "pc-0.10",
-    .desc = "Standard PC, qemu 0.10",
-    .init = pc_init_pci_no_kvmclock,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_11,
-        {
-            .driver   = "virtio-blk-pci",
-            .property = "class",
-            .value    = stringify(PCI_CLASS_STORAGE_OTHER),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "class",
-            .value    = stringify(PCI_CLASS_DISPLAY_OTHER),
-        },{
-            .driver   = "virtio-net-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
-            .driver   = "ide-drive",
-            .property = "ver",
-            .value    = "0.10",
-        },{
-            .driver   = "scsi-disk",
-            .property = "ver",
-            .value    = "0.10",
-        },
-        { /* end of list */ }
-    },
-    .hw_version = "0.10",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine isapc_machine = {
-    .name = "isapc",
-    .desc = "ISA-only PC",
-    .init = pc_init_isa,
-    .max_cpus = 1,
-    .compat_props = (GlobalProperty[]) {
-        {
-            .driver   = "pc-sysfw",
-            .property = "rom_only",
-            .value    = stringify(1),
-        },
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#ifdef CONFIG_XEN
-static QEMUMachine xenfv_machine = {
-    .name = "xenfv",
-    .desc = "Xen Fully-virtualized PC",
-    .init = pc_xen_hvm_init,
-    .max_cpus = HVM_MAX_VCPUS,
-    .default_machine_opts = "accel=xen",
-    DEFAULT_MACHINE_OPTIONS,
-};
-#endif
-
-static void pc_machine_init(void)
-{
-    qemu_register_machine(&pc_i440fx_machine_v1_5);
-    qemu_register_machine(&pc_i440fx_machine_v1_4);
-    qemu_register_machine(&pc_machine_v1_3);
-    qemu_register_machine(&pc_machine_v1_2);
-    qemu_register_machine(&pc_machine_v1_1);
-    qemu_register_machine(&pc_machine_v1_0);
-    qemu_register_machine(&pc_machine_v0_15);
-    qemu_register_machine(&pc_machine_v0_14);
-    qemu_register_machine(&pc_machine_v0_13);
-    qemu_register_machine(&pc_machine_v0_12);
-    qemu_register_machine(&pc_machine_v0_11);
-    qemu_register_machine(&pc_machine_v0_10);
-    qemu_register_machine(&isapc_machine);
-#ifdef CONFIG_XEN
-    qemu_register_machine(&xenfv_machine);
-#endif
-}
-
-machine_init(pc_machine_init);
diff --git a/hw/pc_q35.c b/hw/pc_q35.c
deleted file mode 100644 (file)
index e22fb98..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Q35 chipset based pc system emulator
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- * Copyright (c) 2009, 2010
- *               Isaku Yamahata <yamahata at valinux co jp>
- *               VA Linux Systems Japan K.K.
- * Copyright (C) 2012 Jason Baron <jbaron@redhat.com>
- *
- * This is based on pc.c, but heavily modified.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "sysemu/arch_init.h"
-#include "smbus.h"
-#include "boards.h"
-#include "mc146818rtc.h"
-#include "xen.h"
-#include "sysemu/kvm.h"
-#include "kvm/clock.h"
-#include "q35.h"
-#include "exec/address-spaces.h"
-#include "ich9.h"
-#include "hw/ide/pci.h"
-#include "hw/ide/ahci.h"
-#include "hw/usb.h"
-
-/* ICH9 AHCI has 6 ports */
-#define MAX_SATA_PORTS     6
-
-/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
- *    BIOS will read it and start S3 resume at POST Entry */
-static void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
-{
-    ISADevice *s = opaque;
-
-    if (level) {
-        rtc_set_memory(s, 0xF, 0xFE);
-    }
-}
-
-/* PC hardware initialisation */
-static void pc_q35_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    ram_addr_t below_4g_mem_size, above_4g_mem_size;
-    Q35PCIHost *q35_host;
-    PCIBus *host_bus;
-    PCIDevice *lpc;
-    BusState *idebus[MAX_SATA_PORTS];
-    ISADevice *rtc_state;
-    ISADevice *floppy;
-    MemoryRegion *pci_memory;
-    MemoryRegion *rom_memory;
-    MemoryRegion *ram_memory;
-    GSIState *gsi_state;
-    ISABus *isa_bus;
-    int pci_enabled = 1;
-    qemu_irq *cpu_irq;
-    qemu_irq *gsi;
-    qemu_irq *i8259;
-    int i;
-    ICH9LPCState *ich9_lpc;
-    PCIDevice *ahci;
-    qemu_irq *cmos_s3;
-
-    pc_cpus_init(cpu_model);
-    pc_acpi_init("q35-acpi-dsdt.aml");
-
-    kvmclock_create();
-
-    if (ram_size >= 0xb0000000) {
-        above_4g_mem_size = ram_size - 0xb0000000;
-        below_4g_mem_size = 0xb0000000;
-    } else {
-        above_4g_mem_size = 0;
-        below_4g_mem_size = ram_size;
-    }
-
-    /* pci enabled */
-    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 = get_system_memory();
-    }
-
-    /* allocate ram and load rom/bios */
-    if (!xen_enabled()) {
-        pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline,
-                       initrd_filename, below_4g_mem_size, above_4g_mem_size,
-                       rom_memory, &ram_memory);
-    }
-
-    /* irq lines */
-    gsi_state = g_malloc0(sizeof(*gsi_state));
-    if (kvm_irqchip_in_kernel()) {
-        kvm_pc_setup_irq_routing(pci_enabled);
-        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
-                                 GSI_NUM_PINS);
-    } else {
-        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
-    }
-
-    /* create pci host bus */
-    q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));
-
-    q35_host->mch.ram_memory = ram_memory;
-    q35_host->mch.pci_address_space = pci_memory;
-    q35_host->mch.system_memory = get_system_memory();
-    q35_host->mch.address_space_io = get_system_io();;
-    q35_host->mch.below_4g_mem_size = below_4g_mem_size;
-    q35_host->mch.above_4g_mem_size = above_4g_mem_size;
-    /* pci */
-    qdev_init_nofail(DEVICE(q35_host));
-    host_bus = q35_host->host.pci.bus;
-    /* create ISA bus */
-    lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
-                                          ICH9_LPC_FUNC), true,
-                                          TYPE_ICH9_LPC_DEVICE);
-    ich9_lpc = ICH9_LPC_DEVICE(lpc);
-    ich9_lpc->pic = gsi;
-    ich9_lpc->ioapic = gsi_state->ioapic_irq;
-    pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
-                 ICH9_LPC_NB_PIRQS);
-    pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
-    isa_bus = ich9_lpc->isa_bus;
-
-    /*end early*/
-    isa_bus_irqs(isa_bus, gsi);
-
-    if (kvm_irqchip_in_kernel()) {
-        i8259 = kvm_i8259_init(isa_bus);
-    } else if (xen_enabled()) {
-        i8259 = xen_interrupt_controller_init();
-    } else {
-        cpu_irq = pc_allocate_cpu_irq();
-        i8259 = i8259_init(isa_bus, cpu_irq[0]);
-    }
-
-    for (i = 0; i < ISA_NUM_IRQS; i++) {
-        gsi_state->i8259_irq[i] = i8259[i];
-    }
-    if (pci_enabled) {
-        ioapic_init_gsi(gsi_state, NULL);
-    }
-
-    pc_register_ferr_irq(gsi[13]);
-
-    /* init basic PC hardware */
-    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false);
-
-    /* connect pm stuff to lpc */
-    cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
-    ich9_lpc_pm_init(lpc, *cmos_s3);
-
-    /* ahci and SATA device, for q35 1 ahci controller is built-in */
-    ahci = pci_create_simple_multifunction(host_bus,
-                                           PCI_DEVFN(ICH9_SATA1_DEV,
-                                                     ICH9_SATA1_FUNC),
-                                           true, "ich9-ahci");
-    idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
-    idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");
-
-    if (usb_enabled(false)) {
-        /* Should we create 6 UHCI according to ich9 spec? */
-        ehci_create_ich9_with_companions(host_bus, 0x1d);
-    }
-
-    /* TODO: Populate SPD eeprom data.  */
-    smbus_eeprom_init(ich9_smb_init(host_bus,
-                                    PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
-                                    0xb100),
-                      8, NULL, 0);
-
-    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
-                 floppy, idebus[0], idebus[1], rtc_state);
-
-    /* the rest devices to which pci devfn is automatically assigned */
-    pc_vga_init(isa_bus, host_bus);
-    audio_init(isa_bus, host_bus);
-    pc_nic_init(isa_bus, host_bus);
-    if (pci_enabled) {
-        pc_pci_device_init(host_bus);
-    }
-}
-
-static QEMUMachine pc_q35_machine_v1_5 = {
-    .name = "pc-q35-1.5",
-    .alias = "q35",
-    .desc = "Standard PC (Q35 + ICH9, 2009)",
-    .init = pc_q35_init,
-    .max_cpus = 255,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine pc_q35_machine_v1_4 = {
-    .name = "pc-q35-1.4",
-    .desc = "Standard PC (Q35 + ICH9, 2009)",
-    .init = pc_q35_init,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_4,
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void pc_q35_machine_init(void)
-{
-    qemu_register_machine(&pc_q35_machine_v1_5);
-    qemu_register_machine(&pc_q35_machine_v1_4);
-}
-
-machine_init(pc_q35_machine_init);
index 7f6c12c8a86081e5310740392e5db1608b5077de..3e01528e786941867c28266b36f6734a08a5968f 100644 (file)
  */
 
 #include "sysemu/blockdev.h"
-#include "sysbus.h"
-#include "hw.h"
-#include "pc.h"
+#include "qemu/error-report.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
 #include "hw/boards.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "sysemu/sysemu.h"
-#include "flash.h"
+#include "hw/flash.h"
 #include "sysemu/kvm.h"
 
 #define BIOS_FILENAME "bios.bin"
index 1845d4dfd584a6a3ed6d8084c482e9bde633393e..236cd0f75cb946e49fb845727c5137720b7b799b 100644 (file)
@@ -40,7 +40,6 @@ struct PCIHostState {
     MemoryRegion conf_mem;
     MemoryRegion data_mem;
     MemoryRegion mmcfg;
-    MemoryRegion *address_space;
     uint32_t config_reg;
     PCIBus *bus;
 };
index f07266da66e1cdf50c64caff4c772749fb33b305..d35c2ee96545e5d00cda88d8fc1aae916924d033 100644 (file)
@@ -1,7 +1,8 @@
+#include "qemu-common.h"
 #include <strings.h>
 #include <stdint.h>
 #include "qemu/range.h"
-#include "qemu/range.h"
+#include "qemu/error-report.h"
 #include "hw/pci/shpc.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
index 99a30f429da65a9c5652dce2c6951fdc145a2c2d..62f7bae2f12b6f026769581357e27d8bcc472914 100644 (file)
@@ -1,5 +1,6 @@
 #include "hw/pci/slotid_cap.h"
 #include "hw/pci/pci.h"
+#include "qemu/error-report.h"
 
 #define SLOTID_CAP_LENGTH 4
 #define SLOTID_NSLOTS_SHIFT (ffs(PCI_SID_ESR_NSLOTS) - 1)
index 1124c53b8c0dc716fb45feffc1ad36d306540486..9cc6a4082df89d818dcb99521c7482be6bf58582 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci/pci_bridge.h"
-#include "pci/pci_ids.h"
-#include "pci/msi.h"
-#include "pci/shpc.h"
-#include "pci/slotid_cap.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/shpc.h"
+#include "hw/pci/slotid_cap.h"
 #include "exec/memory.h"
-#include "pci/pci_bus.h"
+#include "hw/pci/pci_bus.h"
 
 struct PCIBridgeDev {
     PCIBridge bridge;
index 3bad09baf28e830e5fd11ee7b8cc709e54fdd038..cc63df0570dcd910e8a219b93eac1d0138d07dcd 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "isa.h"
-#include "pc.h"
-#include "ps2.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
+#include "hw/pc.h"
+#include "hw/ps2.h"
 #include "sysemu/sysemu.h"
 
 /* debug PC keyboard */
index df63b2246319e4d9cc223816bf8a873dcd87ad88..55f80ca671dbaff610cf4bc4ccbc309337b56a8c 100644 (file)
  * AMD Publication# 19436  Rev:E  Amendment/0  Issue Date: June 2000
  */
 
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 #include "net/net.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "qemu/timer.h"
 #include "sysemu/dma.h"
 
-#include "pcnet.h"
+#include "hw/pcnet.h"
 
 //#define PCNET_DEBUG
 //#define PCNET_DEBUG_IO
index e0de1e3458fee83e7e0f89601b976d33aee029d7..b0b462b02e3151b62f6ee386ac5e3ee0e1cf9c1a 100644 (file)
  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt
  */
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "net/net.h"
 #include "qemu/timer.h"
 #include "qemu/sockets.h"
 #include "sysemu/sysemu.h"
 
-#include "pcnet.h"
+#include "hw/pcnet.h"
 
 //#define PCNET_DEBUG
 //#define PCNET_DEBUG_IO
index dfab9559ae92426c74fcad229855cc140cb5babf..d5334159502916f08e685ed81d35b03a96822170 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 #include "audio/audio.h"
 #include "qemu/timer.h"
-#include "i8254.h"
-#include "pcspk.h"
+#include "hw/i8254.h"
+#include "hw/pcspk.h"
 
 #define PCSPK_BUF_LEN 1792
 #define PCSPK_SAMPLE_RATE 32000
index 7f42bac1c8e035965a009ebd3d40b5e9c21425dc..f448d221dafbcfc43f9500bc4bca31be7f4580c8 100644 (file)
@@ -25,8 +25,8 @@
 #ifndef HW_PCSPK_H
 #define HW_PCSPK_H
 
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 
 static inline ISADevice *pcspk_init(ISABus *bus, ISADevice *pit)
 {
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
deleted file mode 100644 (file)
index fe7a932..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Model of Petalogix linux reference design targeting Xilinx Spartan ml605
- * board.
- *
- * Copyright (c) 2011 Michal Simek <monstr@monstr.eu>
- * Copyright (c) 2011 PetaLogix
- * Copyright (c) 2009 Edgar E. Iglesias.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "hw.h"
-#include "net/net.h"
-#include "flash.h"
-#include "sysemu/sysemu.h"
-#include "devices.h"
-#include "boards.h"
-#include "xilinx.h"
-#include "sysemu/blockdev.h"
-#include "serial.h"
-#include "exec/address-spaces.h"
-#include "ssi.h"
-
-#include "microblaze_boot.h"
-#include "microblaze_pic_cpu.h"
-
-#include "stream.h"
-
-#define LMB_BRAM_SIZE  (128 * 1024)
-#define FLASH_SIZE     (32 * 1024 * 1024)
-
-#define BINARY_DEVICE_TREE_FILE "petalogix-ml605.dtb"
-
-#define NUM_SPI_FLASHES 4
-
-#define MEMORY_BASEADDR 0x50000000
-#define FLASH_BASEADDR 0x86000000
-#define INTC_BASEADDR 0x81800000
-#define TIMER_BASEADDR 0x83c00000
-#define UART16550_BASEADDR 0x83e00000
-#define AXIENET_BASEADDR 0x82780000
-#define AXIDMA_BASEADDR 0x84600000
-
-static void machine_cpu_reset(MicroBlazeCPU *cpu)
-{
-    CPUMBState *env = &cpu->env;
-
-    env->pvr.regs[10] = 0x0e000000; /* virtex 6 */
-    /* setup pvr to match kernel setting */
-    env->pvr.regs[5] |= PVR5_DCACHE_WRITEBACK_MASK;
-    env->pvr.regs[0] |= PVR0_USE_FPU_MASK | PVR0_ENDI;
-    env->pvr.regs[0] = (env->pvr.regs[0] & ~PVR0_VERSION_MASK) | (0x14 << 8);
-    env->pvr.regs[2] ^= PVR2_USE_FPU2_MASK;
-    env->pvr.regs[4] = 0xc56b8000;
-    env->pvr.regs[5] = 0xc56be000;
-}
-
-static void
-petalogix_ml605_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    MemoryRegion *address_space_mem = get_system_memory();
-    DeviceState *dev, *dma, *eth0;
-    MicroBlazeCPU *cpu;
-    SysBusDevice *busdev;
-    CPUMBState *env;
-    DriveInfo *dinfo;
-    int i;
-    hwaddr ddr_base = MEMORY_BASEADDR;
-    MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq irq[32], *cpu_irq;
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = "microblaze";
-    }
-    cpu = cpu_mb_init(cpu_model);
-    env = &cpu->env;
-
-    /* Attach emulated BRAM through the LMB.  */
-    memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram",
-                           LMB_BRAM_SIZE);
-    vmstate_register_ram_global(phys_lmb_bram);
-    memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram);
-
-    memory_region_init_ram(phys_ram, "petalogix_ml605.ram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(address_space_mem, ddr_base, phys_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    /* 5th parameter 2 means bank-width
-     * 10th paremeter 0 means little-endian */
-    pflash_cfi01_register(FLASH_BASEADDR,
-                          NULL, "petalogix_ml605.flash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                          FLASH_SIZE >> 16,
-                          2, 0x89, 0x18, 0x0000, 0x0, 0);
-
-
-    cpu_irq = microblaze_pic_init_cpu(env);
-    dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 4);
-    for (i = 0; i < 32; i++) {
-        irq[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    serial_mm_init(address_space_mem, UART16550_BASEADDR + 0x1000, 2,
-                   irq[5], 115200, serial_hds[0], DEVICE_LITTLE_ENDIAN);
-
-    /* 2 timers at irq 2 @ 100 Mhz.  */
-    xilinx_timer_create(TIMER_BASEADDR, irq[2], 0, 100 * 1000000);
-
-    /* axi ethernet and dma initialization. */
-    qemu_check_nic_model(&nd_table[0], "xlnx.axi-ethernet");
-    eth0 = qdev_create(NULL, "xlnx.axi-ethernet");
-    dma = qdev_create(NULL, "xlnx.axi-dma");
-
-    /* FIXME: attach to the sysbus instead */
-    object_property_add_child(container_get(qdev_get_machine(), "/unattached"),
-                                  "xilinx-dma", OBJECT(dma), NULL);
-
-    xilinx_axiethernet_init(eth0, &nd_table[0], STREAM_SLAVE(dma),
-                                   0x82780000, irq[3], 0x1000, 0x1000);
-
-    xilinx_axidma_init(dma, STREAM_SLAVE(eth0), 0x84600000, irq[1], irq[0],
-                       100 * 1000000);
-
-    {
-        SSIBus *spi;
-
-        dev = qdev_create(NULL, "xlnx.xps-spi");
-        qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES);
-        qdev_init_nofail(dev);
-        busdev = SYS_BUS_DEVICE(dev);
-        sysbus_mmio_map(busdev, 0, 0x40a00000);
-        sysbus_connect_irq(busdev, 0, irq[4]);
-
-        spi = (SSIBus *)qdev_get_child_bus(dev, "spi");
-
-        for (i = 0; i < NUM_SPI_FLASHES; i++) {
-            qemu_irq cs_line;
-
-            dev = ssi_create_slave_no_init(spi, "n25q128");
-            qdev_init_nofail(dev);
-            cs_line = qdev_get_gpio_in(dev, 0);
-            sysbus_connect_irq(busdev, i+1, cs_line);
-        }
-    }
-
-    microblaze_load_kernel(cpu, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
-                                                            machine_cpu_reset);
-
-}
-
-static QEMUMachine petalogix_ml605_machine = {
-    .name = "petalogix-ml605",
-    .desc = "PetaLogix linux refdesign for xilinx ml605 little endian",
-    .init = petalogix_ml605_init,
-    .is_default = 0,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void petalogix_ml605_machine_init(void)
-{
-    qemu_register_machine(&petalogix_ml605_machine);
-}
-
-machine_init(petalogix_ml605_machine_init);
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
deleted file mode 100644 (file)
index 8605fb8..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Model of Petalogix linux reference design targeting Xilinx Spartan 3ADSP-1800
- * boards.
- *
- * Copyright (c) 2009 Edgar E. Iglesias.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "hw.h"
-#include "net/net.h"
-#include "flash.h"
-#include "sysemu/sysemu.h"
-#include "devices.h"
-#include "boards.h"
-#include "xilinx.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#include "microblaze_boot.h"
-#include "microblaze_pic_cpu.h"
-
-#define LMB_BRAM_SIZE  (128 * 1024)
-#define FLASH_SIZE     (16 * 1024 * 1024)
-
-#define BINARY_DEVICE_TREE_FILE "petalogix-s3adsp1800.dtb"
-
-#define MEMORY_BASEADDR 0x90000000
-#define FLASH_BASEADDR 0xa0000000
-#define INTC_BASEADDR 0x81800000
-#define TIMER_BASEADDR 0x83c00000
-#define UARTLITE_BASEADDR 0x84000000
-#define ETHLITE_BASEADDR 0x81000000
-
-static void machine_cpu_reset(MicroBlazeCPU *cpu)
-{
-    CPUMBState *env = &cpu->env;
-
-    env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family.  */
-}
-
-static void
-petalogix_s3adsp1800_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    DeviceState *dev;
-    MicroBlazeCPU *cpu;
-    CPUMBState *env;
-    DriveInfo *dinfo;
-    int i;
-    hwaddr ddr_base = MEMORY_BASEADDR;
-    MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq irq[32], *cpu_irq;
-    MemoryRegion *sysmem = get_system_memory();
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = "microblaze";
-    }
-    cpu = cpu_mb_init(cpu_model);
-    env = &cpu->env;
-
-    /* Attach emulated BRAM through the LMB.  */
-    memory_region_init_ram(phys_lmb_bram,
-                           "petalogix_s3adsp1800.lmb_bram", LMB_BRAM_SIZE);
-    vmstate_register_ram_global(phys_lmb_bram);
-    memory_region_add_subregion(sysmem, 0x00000000, phys_lmb_bram);
-
-    memory_region_init_ram(phys_ram, "petalogix_s3adsp1800.ram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(sysmem, ddr_base, phys_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(FLASH_BASEADDR,
-                          NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                          FLASH_SIZE >> 16,
-                          1, 0x89, 0x18, 0x0000, 0x0, 1);
-
-    cpu_irq = microblaze_pic_init_cpu(env);
-    dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 2);
-    for (i = 0; i < 32; i++) {
-        irq[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    sysbus_create_simple("xlnx.xps-uartlite", UARTLITE_BASEADDR, irq[3]);
-    /* 2 timers at irq 2 @ 62 Mhz.  */
-    xilinx_timer_create(TIMER_BASEADDR, irq[0], 0, 62 * 1000000);
-    xilinx_ethlite_create(&nd_table[0], ETHLITE_BASEADDR, irq[1], 0, 0);
-
-    microblaze_load_kernel(cpu, ddr_base, ram_size,
-                    BINARY_DEVICE_TREE_FILE, machine_cpu_reset);
-}
-
-static QEMUMachine petalogix_s3adsp1800_machine = {
-    .name = "petalogix-s3adsp1800",
-    .desc = "PetaLogix linux refdesign for xilinx Spartan 3ADSP1800",
-    .init = petalogix_s3adsp1800_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void petalogix_s3adsp1800_machine_init(void)
-{
-    qemu_register_machine(&petalogix_s3adsp1800_machine);
-}
-
-machine_init(petalogix_s3adsp1800_machine_init);
index 123b00653a80777f1533ea1fd1c60b45fdc21ee4..5d57babe078230b72694b470a6a45d008c075395 100644 (file)
  * It does not implement much more ...
  */
 
-#include "hw.h"
-#include "flash.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
 #include "block/block.h"
 #include "qemu/timer.h"
 #include "exec/address-spaces.h"
 #include "qemu/host-utils.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #define PFLASH_BUG(fmt, ...) \
 do { \
index 44bd4654f0f20e1517513a5df75a7c13ca59d816..37b4fcc234d56b5be9e7923d7814f562631c4b8c 100644 (file)
  * It does not implement multiple sectors erase
  */
 
-#include "hw.h"
-#include "flash.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
 #include "qemu/timer.h"
 #include "block/block.h"
 #include "exec/address-spaces.h"
 #include "qemu/host-utils.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 //#define PFLASH_DEBUG
 #ifdef PFLASH_DEBUG
index c1cb94d39f57c8860c4afd6c79e78277ad0dfaf5..0f5cd014e59815ccb5656529687c08a295d4d96d 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "pci/pci.h"
-#include "isa.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
 
 PCIDevice *piix4_dev;
 
index 6c77e493e469836fd4d3561f35502cc40e9364f3..e10bc1c6a0b8b0d6cd97638334cd79a84faf6c90 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
-#include "isa.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
 #include "qemu/range.h"
-#include "xen.h"
-#include "pam.h"
+#include "hw/xen.h"
+#include "hw/pam.h"
 #include "sysemu/sysemu.h"
 
 /*
@@ -244,7 +244,6 @@ static PCIBus *i440fx_common_init(const char *device_name,
 
     dev = qdev_create(NULL, "i440FX-pcihost");
     s = PCI_HOST_BRIDGE(dev);
-    s->address_space = address_space_mem;
     b = pci_bus_new(dev, NULL, pci_address_space,
                     address_space_io, 0);
     s->bus = b;
index 002a50e16a80e80462e7f2905ef822ce818a7d50..332d5b970c4de01a955f5fccec654e1dc4b3609b 100644 (file)
@@ -7,7 +7,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 
 typedef struct {
index c160e9061c58bfe2d4dbf1628b07fae9b636784b..536c2166fe137805b20ff8bc59e14fa1aaa4ac2b 100644 (file)
@@ -7,8 +7,8 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
-#include "ssi.h"
+#include "hw/sysbus.h"
+#include "hw/ssi.h"
 
 //#define DEBUG_PL022 1
 
index 757867ff7995b2c2d601042db14a40c7b0e2a5d5..764940be7eb4fcb63d8aac1202189adf966ca664 100644 (file)
@@ -11,7 +11,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 
index 0b71c45748348a9f7ba4658418e5123b8ba7a7fd..92dddc2923ab527a6524a29d15a8c63f4ae76a19 100644 (file)
  *
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
-#include "pl041.h"
-#include "lm4549.h"
+#include "hw/pl041.h"
+#include "hw/lm4549.h"
 
 #if 0
 #define PL041_DEBUG_LEVEL 1
index 5d06bc9a3fa10d1d764c253163d1eaa6d557e34c..bc31ab688585ba1f68541ef3030e091abb14fee7 100644 (file)
@@ -7,8 +7,8 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
-#include "ps2.h"
+#include "hw/sysbus.h"
+#include "hw/ps2.h"
 
 typedef struct {
     SysBusDevice busdev;
index a78e819d967e52880fa7e00a26b2cd321717958a..74bc109488a661de4f517e62d62d5316af45f56a 100644 (file)
@@ -8,7 +8,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 //#define DEBUG_PL061 1
 
index f6bbf98a7ee2cfb818c2d2b3ee1cb995fb87314a..00b66b45b097ea28193e840d9985573e54b45161 100644 (file)
@@ -7,7 +7,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #define PL080_MAX_CHANNELS 8
 #define PL080_CONF_E    0x1
index 3d0ac00ade83e1d8e10525dc7cfe2a13e291c814..924642d6977596ac2af05668cacc9796b4b9c221 100644 (file)
@@ -7,9 +7,9 @@
  * This code is licensed under the GNU LGPL
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "ui/console.h"
-#include "framebuffer.h"
+#include "hw/framebuffer.h"
 #include "ui/pixel_ops.h"
 
 #define PL110_CR_EN   0x001
@@ -111,15 +111,15 @@ static const unsigned char *idregs[] = {
 };
 
 #define BITS 8
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define BITS 15
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define BITS 16
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define BITS 24
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define BITS 32
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 
 static int pl110_enabled(pl110_state *s)
 {
index e738e4a241bf2eb268db26feb9f1edc7b17f356d..ec4bfd6f8ccf5bdb7481bcddda584429c1678aa2 100644 (file)
 #undef RGB
 #define BORDER bgr
 #define ORDER 0
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define ORDER 1
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define ORDER 2
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #undef BORDER
 #define RGB
 #define BORDER rgb
 #define ORDER 0
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define ORDER 1
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define ORDER 2
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #undef BORDER
 
 static drawfn glue(pl110_draw_fn_,BITS)[48] =
index 98529f78211bfee14f9c767dbd45c1df28854852..2527296776c32bc2dbc945f9100337ea64455cb8 100644 (file)
@@ -8,8 +8,8 @@
  */
 
 #include "sysemu/blockdev.h"
-#include "sysbus.h"
-#include "sd.h"
+#include "hw/sysbus.h"
+#include "hw/sd.h"
 
 //#define DEBUG_PL181 1
 
index 76ac159374ca87670938d922b93db157d0563e9a..9610673d946fd2d8240effef3645920b38c99c92 100644 (file)
@@ -7,7 +7,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* The number of virtual priority levels.  16 user vectors plus the
    unvectored IRQ.  Chained interrupts would require an additional level
index ea1380ca680d1b4dceae4a923b32ddad5e26bb94..790061065ce59ca6a074072b5c5d9000099499c2 100644 (file)
  * License along with this library; if not, see
  * <http://www.gnu.org/licenses/>.
  */
-#include "hw.h"
-#include "pc.h"
-#include "pm_smbus.h"
-#include "smbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pm_smbus.h"
+#include "hw/smbus.h"
 
 /* no save/load? */
 
diff --git a/hw/ppc.c b/hw/ppc.c
deleted file mode 100644 (file)
index 8cfb84f..0000000
--- a/hw/ppc.c
+++ /dev/null
@@ -1,1356 +0,0 @@
-/*
- * QEMU generic PowerPC hardware System Emulator
- *
- * Copyright (c) 2003-2007 Jocelyn Mayer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "ppc.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "nvram.h"
-#include "qemu/log.h"
-#include "loader.h"
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
-
-//#define PPC_DEBUG_IRQ
-//#define PPC_DEBUG_TB
-
-#ifdef PPC_DEBUG_IRQ
-#  define LOG_IRQ(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
-#else
-#  define LOG_IRQ(...) do { } while (0)
-#endif
-
-
-#ifdef PPC_DEBUG_TB
-#  define LOG_TB(...) qemu_log(__VA_ARGS__)
-#else
-#  define LOG_TB(...) do { } while (0)
-#endif
-
-static void cpu_ppc_tb_stop (CPUPPCState *env);
-static void cpu_ppc_tb_start (CPUPPCState *env);
-
-void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
-{
-    CPUPPCState *env = &cpu->env;
-    unsigned int old_pending = env->pending_interrupts;
-
-    if (level) {
-        env->pending_interrupts |= 1 << n_IRQ;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-        env->pending_interrupts &= ~(1 << n_IRQ);
-        if (env->pending_interrupts == 0)
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-
-    if (old_pending != env->pending_interrupts) {
-#ifdef CONFIG_KVM
-        kvmppc_set_interrupt(cpu, n_IRQ, level);
-#endif
-    }
-
-    LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
-                "req %08x\n", __func__, env, n_IRQ, level,
-                env->pending_interrupts, env->interrupt_request);
-}
-
-/* PowerPC 6xx / 7xx internal IRQ controller */
-static void ppc6xx_set_irq(void *opaque, int pin, int level)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    int cur_level;
-
-    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
-                env, pin, level);
-    cur_level = (env->irq_input_state >> pin) & 1;
-    /* Don't generate spurious events */
-    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
-        switch (pin) {
-        case PPC6xx_INPUT_TBEN:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: %s the time base\n",
-                        __func__, level ? "start" : "stop");
-            if (level) {
-                cpu_ppc_tb_start(env);
-            } else {
-                cpu_ppc_tb_stop(env);
-            }
-        case PPC6xx_INPUT_INT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the external IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
-            break;
-        case PPC6xx_INPUT_SMI:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the SMI IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_SMI, level);
-            break;
-        case PPC6xx_INPUT_MCP:
-            /* Negative edge sensitive */
-            /* XXX: TODO: actual reaction may depends on HID0 status
-             *            603/604/740/750: check HID0[EMCP]
-             */
-            if (cur_level == 1 && level == 0) {
-                LOG_IRQ("%s: raise machine check state\n",
-                            __func__);
-                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
-            }
-            break;
-        case PPC6xx_INPUT_CKSTP_IN:
-            /* Level sensitive - active low */
-            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
-            /* XXX: Note that the only way to restart the CPU is to reset it */
-            if (level) {
-                LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
-            }
-            break;
-        case PPC6xx_INPUT_HRESET:
-            /* Level sensitive - active low */
-            if (level) {
-                LOG_IRQ("%s: reset the CPU\n", __func__);
-                cpu_interrupt(env, CPU_INTERRUPT_RESET);
-            }
-            break;
-        case PPC6xx_INPUT_SRESET:
-            LOG_IRQ("%s: set the RESET IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
-            break;
-        default:
-            /* Unknown pin - do nothing */
-            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
-            return;
-        }
-        if (level)
-            env->irq_input_state |= 1 << pin;
-        else
-            env->irq_input_state &= ~(1 << pin);
-    }
-}
-
-void ppc6xx_irq_init(CPUPPCState *env)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, cpu,
-                                                  PPC6xx_INPUT_NB);
-}
-
-#if defined(TARGET_PPC64)
-/* PowerPC 970 internal IRQ controller */
-static void ppc970_set_irq(void *opaque, int pin, int level)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    int cur_level;
-
-    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
-                env, pin, level);
-    cur_level = (env->irq_input_state >> pin) & 1;
-    /* Don't generate spurious events */
-    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
-        switch (pin) {
-        case PPC970_INPUT_INT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the external IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
-            break;
-        case PPC970_INPUT_THINT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
-                        level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_THERM, level);
-            break;
-        case PPC970_INPUT_MCP:
-            /* Negative edge sensitive */
-            /* XXX: TODO: actual reaction may depends on HID0 status
-             *            603/604/740/750: check HID0[EMCP]
-             */
-            if (cur_level == 1 && level == 0) {
-                LOG_IRQ("%s: raise machine check state\n",
-                            __func__);
-                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
-            }
-            break;
-        case PPC970_INPUT_CKSTP:
-            /* Level sensitive - active low */
-            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
-            if (level) {
-                LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
-            } else {
-                LOG_IRQ("%s: restart the CPU\n", __func__);
-                env->halted = 0;
-                qemu_cpu_kick(CPU(cpu));
-            }
-            break;
-        case PPC970_INPUT_HRESET:
-            /* Level sensitive - active low */
-            if (level) {
-                cpu_interrupt(env, CPU_INTERRUPT_RESET);
-            }
-            break;
-        case PPC970_INPUT_SRESET:
-            LOG_IRQ("%s: set the RESET IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
-            break;
-        case PPC970_INPUT_TBEN:
-            LOG_IRQ("%s: set the TBEN state to %d\n", __func__,
-                        level);
-            /* XXX: TODO */
-            break;
-        default:
-            /* Unknown pin - do nothing */
-            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
-            return;
-        }
-        if (level)
-            env->irq_input_state |= 1 << pin;
-        else
-            env->irq_input_state &= ~(1 << pin);
-    }
-}
-
-void ppc970_irq_init(CPUPPCState *env)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, cpu,
-                                                  PPC970_INPUT_NB);
-}
-
-/* POWER7 internal IRQ controller */
-static void power7_set_irq(void *opaque, int pin, int level)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-
-    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
-                env, pin, level);
-
-    switch (pin) {
-    case POWER7_INPUT_INT:
-        /* Level sensitive - active high */
-        LOG_IRQ("%s: set the external IRQ state to %d\n",
-                __func__, level);
-        ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
-        break;
-    default:
-        /* Unknown pin - do nothing */
-        LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
-        return;
-    }
-    if (level) {
-        env->irq_input_state |= 1 << pin;
-    } else {
-        env->irq_input_state &= ~(1 << pin);
-    }
-}
-
-void ppcPOWER7_irq_init(CPUPPCState *env)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu,
-                                                  POWER7_INPUT_NB);
-}
-#endif /* defined(TARGET_PPC64) */
-
-/* PowerPC 40x internal IRQ controller */
-static void ppc40x_set_irq(void *opaque, int pin, int level)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    int cur_level;
-
-    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
-                env, pin, level);
-    cur_level = (env->irq_input_state >> pin) & 1;
-    /* Don't generate spurious events */
-    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
-        switch (pin) {
-        case PPC40x_INPUT_RESET_SYS:
-            if (level) {
-                LOG_IRQ("%s: reset the PowerPC system\n",
-                            __func__);
-                ppc40x_system_reset(cpu);
-            }
-            break;
-        case PPC40x_INPUT_RESET_CHIP:
-            if (level) {
-                LOG_IRQ("%s: reset the PowerPC chip\n", __func__);
-                ppc40x_chip_reset(cpu);
-            }
-            break;
-        case PPC40x_INPUT_RESET_CORE:
-            /* XXX: TODO: update DBSR[MRR] */
-            if (level) {
-                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
-                ppc40x_core_reset(cpu);
-            }
-            break;
-        case PPC40x_INPUT_CINT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the critical IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
-            break;
-        case PPC40x_INPUT_INT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the external IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
-            break;
-        case PPC40x_INPUT_HALT:
-            /* Level sensitive - active low */
-            if (level) {
-                LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
-            } else {
-                LOG_IRQ("%s: restart the CPU\n", __func__);
-                env->halted = 0;
-                qemu_cpu_kick(CPU(cpu));
-            }
-            break;
-        case PPC40x_INPUT_DEBUG:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the debug pin state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
-            break;
-        default:
-            /* Unknown pin - do nothing */
-            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
-            return;
-        }
-        if (level)
-            env->irq_input_state |= 1 << pin;
-        else
-            env->irq_input_state &= ~(1 << pin);
-    }
-}
-
-void ppc40x_irq_init(CPUPPCState *env)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
-                                                  cpu, PPC40x_INPUT_NB);
-}
-
-/* PowerPC E500 internal IRQ controller */
-static void ppce500_set_irq(void *opaque, int pin, int level)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    int cur_level;
-
-    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
-                env, pin, level);
-    cur_level = (env->irq_input_state >> pin) & 1;
-    /* Don't generate spurious events */
-    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
-        switch (pin) {
-        case PPCE500_INPUT_MCK:
-            if (level) {
-                LOG_IRQ("%s: reset the PowerPC system\n",
-                            __func__);
-                qemu_system_reset_request();
-            }
-            break;
-        case PPCE500_INPUT_RESET_CORE:
-            if (level) {
-                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
-                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, level);
-            }
-            break;
-        case PPCE500_INPUT_CINT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the critical IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
-            break;
-        case PPCE500_INPUT_INT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the core IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
-            break;
-        case PPCE500_INPUT_DEBUG:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the debug pin state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
-            break;
-        default:
-            /* Unknown pin - do nothing */
-            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
-            return;
-        }
-        if (level)
-            env->irq_input_state |= 1 << pin;
-        else
-            env->irq_input_state &= ~(1 << pin);
-    }
-}
-
-void ppce500_irq_init(CPUPPCState *env)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
-                                                  cpu, PPCE500_INPUT_NB);
-}
-
-/* Enable or Disable the E500 EPR capability */
-void ppce500_set_mpic_proxy(bool enabled)
-{
-    CPUPPCState *env;
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        PowerPCCPU *cpu = ppc_env_get_cpu(env);
-        CPUState *cs = CPU(cpu);
-
-        env->mpic_proxy = enabled;
-        if (kvm_enabled()) {
-            kvmppc_set_mpic_proxy(POWERPC_CPU(cs), enabled);
-        }
-    }
-}
-
-/*****************************************************************************/
-/* PowerPC time base and decrementer emulation */
-
-uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset)
-{
-    /* TB time in tb periods */
-    return muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec()) + tb_offset;
-}
-
-uint64_t cpu_ppc_load_tbl (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    if (kvm_enabled()) {
-        return env->spr[SPR_TBL];
-    }
-
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
-    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
-
-    return tb;
-}
-
-static inline uint32_t _cpu_ppc_load_tbu(CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
-    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
-
-    return tb >> 32;
-}
-
-uint32_t cpu_ppc_load_tbu (CPUPPCState *env)
-{
-    if (kvm_enabled()) {
-        return env->spr[SPR_TBU];
-    }
-
-    return _cpu_ppc_load_tbu(env);
-}
-
-static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
-                                    int64_t *tb_offsetp, uint64_t value)
-{
-    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec());
-    LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
-                __func__, value, *tb_offsetp);
-}
-
-void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
-    tb &= 0xFFFFFFFF00000000ULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
-                     &tb_env->tb_offset, tb | (uint64_t)value);
-}
-
-static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
-    tb &= 0x00000000FFFFFFFFULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
-                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
-}
-
-void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value)
-{
-    _cpu_ppc_store_tbu(env, value);
-}
-
-uint64_t cpu_ppc_load_atbl (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
-    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
-
-    return tb;
-}
-
-uint32_t cpu_ppc_load_atbu (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
-    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
-
-    return tb >> 32;
-}
-
-void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
-    tb &= 0xFFFFFFFF00000000ULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
-                     &tb_env->atb_offset, tb | (uint64_t)value);
-}
-
-void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
-    tb &= 0x00000000FFFFFFFFULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
-                     &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
-}
-
-static void cpu_ppc_tb_stop (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb, atb, vmclk;
-
-    /* If the time base is already frozen, do nothing */
-    if (tb_env->tb_freq != 0) {
-        vmclk = qemu_get_clock_ns(vm_clock);
-        /* Get the time base */
-        tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
-        /* Get the alternate time base */
-        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
-        /* Store the time base value (ie compute the current offset) */
-        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
-        /* Store the alternate time base value (compute the current offset) */
-        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
-        /* Set the time base frequency to zero */
-        tb_env->tb_freq = 0;
-        /* Now, the time bases are frozen to tb_offset / atb_offset value */
-    }
-}
-
-static void cpu_ppc_tb_start (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb, atb, vmclk;
-
-    /* If the time base is not frozen, do nothing */
-    if (tb_env->tb_freq == 0) {
-        vmclk = qemu_get_clock_ns(vm_clock);
-        /* Get the time base from tb_offset */
-        tb = tb_env->tb_offset;
-        /* Get the alternate time base from atb_offset */
-        atb = tb_env->atb_offset;
-        /* Restore the tb frequency from the decrementer frequency */
-        tb_env->tb_freq = tb_env->decr_freq;
-        /* Store the time base value */
-        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
-        /* Store the alternate time base value */
-        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
-    }
-}
-
-static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint32_t decr;
-    int64_t diff;
-
-    diff = next - qemu_get_clock_ns(vm_clock);
-    if (diff >= 0) {
-        decr = muldiv64(diff, tb_env->decr_freq, get_ticks_per_sec());
-    } else if (tb_env->flags & PPC_TIMER_BOOKE) {
-        decr = 0;
-    }  else {
-        decr = -muldiv64(-diff, tb_env->decr_freq, get_ticks_per_sec());
-    }
-    LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
-
-    return decr;
-}
-
-uint32_t cpu_ppc_load_decr (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-
-    if (kvm_enabled()) {
-        return env->spr[SPR_DECR];
-    }
-
-    return _cpu_ppc_load_decr(env, tb_env->decr_next);
-}
-
-uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-
-    return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
-}
-
-uint64_t cpu_ppc_load_purr (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t diff;
-
-    diff = qemu_get_clock_ns(vm_clock) - tb_env->purr_start;
-
-    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, get_ticks_per_sec());
-}
-
-/* When decrementer expires,
- * all we need to do is generate or queue a CPU exception
- */
-static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu)
-{
-    /* Raise it */
-    LOG_TB("raise decrementer exception\n");
-    ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1);
-}
-
-static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
-{
-    /* Raise it */
-    LOG_TB("raise decrementer exception\n");
-    ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
-}
-
-static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
-                                 struct QEMUTimer *timer,
-                                 void (*raise_excp)(PowerPCCPU *),
-                                 uint32_t decr, uint32_t value,
-                                 int is_excp)
-{
-    CPUPPCState *env = &cpu->env;
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t now, next;
-
-    LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
-                decr, value);
-
-    if (kvm_enabled()) {
-        /* KVM handles decrementer exceptions, we don't need our own timer */
-        return;
-    }
-
-    now = qemu_get_clock_ns(vm_clock);
-    next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
-    if (is_excp) {
-        next += *nextp - now;
-    }
-    if (next == now) {
-        next++;
-    }
-    *nextp = next;
-    /* Adjust timer */
-    qemu_mod_timer(timer, next);
-
-    /* If we set a negative value and the decrementer was positive, raise an
-     * exception.
-     */
-    if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
-        && (value & 0x80000000)
-        && !(decr & 0x80000000)) {
-        (*raise_excp)(cpu);
-    }
-}
-
-static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
-                                       uint32_t value, int is_excp)
-{
-    ppc_tb_t *tb_env = cpu->env.tb_env;
-
-    __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
-                         &cpu_ppc_decr_excp, decr, value, is_excp);
-}
-
-void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0);
-}
-
-static void cpu_ppc_decr_cb(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-
-    _cpu_ppc_store_decr(cpu, 0x00000000, 0xFFFFFFFF, 1);
-}
-
-static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
-                                        uint32_t value, int is_excp)
-{
-    ppc_tb_t *tb_env = cpu->env.tb_env;
-
-    if (tb_env->hdecr_timer != NULL) {
-        __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
-                             &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
-    }
-}
-
-void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, 0);
-}
-
-static void cpu_ppc_hdecr_cb(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-
-    _cpu_ppc_store_hdecr(cpu, 0x00000000, 0xFFFFFFFF, 1);
-}
-
-static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
-{
-    ppc_tb_t *tb_env = cpu->env.tb_env;
-
-    tb_env->purr_load = value;
-    tb_env->purr_start = qemu_get_clock_ns(vm_clock);
-}
-
-static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
-{
-    CPUPPCState *env = opaque;
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-    ppc_tb_t *tb_env = env->tb_env;
-
-    tb_env->tb_freq = freq;
-    tb_env->decr_freq = freq;
-    /* There is a bug in Linux 2.4 kernels:
-     * if a decrementer exception is pending when it enables msr_ee at startup,
-     * it's not ready to handle it...
-     */
-    _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
-    _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
-    cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
-}
-
-/* Set up (once) timebase frequency (in Hz) */
-clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-    ppc_tb_t *tb_env;
-
-    tb_env = g_malloc0(sizeof(ppc_tb_t));
-    env->tb_env = tb_env;
-    tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
-    /* Create new timer */
-    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, cpu);
-    if (0) {
-        /* XXX: find a suitable condition to enable the hypervisor decrementer
-         */
-        tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb,
-                                                cpu);
-    } else {
-        tb_env->hdecr_timer = NULL;
-    }
-    cpu_ppc_set_tb_clk(env, freq);
-
-    return &cpu_ppc_set_tb_clk;
-}
-
-/* Specific helpers for POWER & PowerPC 601 RTC */
-#if 0
-static clk_setup_cb cpu_ppc601_rtc_init (CPUPPCState *env)
-{
-    return cpu_ppc_tb_init(env, 7812500);
-}
-#endif
-
-void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value)
-{
-    _cpu_ppc_store_tbu(env, value);
-}
-
-uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env)
-{
-    return _cpu_ppc_load_tbu(env);
-}
-
-void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value)
-{
-    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
-}
-
-uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env)
-{
-    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
-}
-
-/*****************************************************************************/
-/* PowerPC 40x timers */
-
-/* PIT, FIT & WDT */
-typedef struct ppc40x_timer_t ppc40x_timer_t;
-struct ppc40x_timer_t {
-    uint64_t pit_reload;  /* PIT auto-reload value        */
-    uint64_t fit_next;    /* Tick for next FIT interrupt  */
-    struct QEMUTimer *fit_timer;
-    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
-    struct QEMUTimer *wdt_timer;
-
-    /* 405 have the PIT, 440 have a DECR.  */
-    unsigned int decr_excp;
-};
-
-/* Fixed interval timer */
-static void cpu_4xx_fit_cb (void *opaque)
-{
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    ppc_tb_t *tb_env;
-    ppc40x_timer_t *ppc40x_timer;
-    uint64_t now, next;
-
-    env = opaque;
-    cpu = ppc_env_get_cpu(env);
-    tb_env = env->tb_env;
-    ppc40x_timer = tb_env->opaque;
-    now = qemu_get_clock_ns(vm_clock);
-    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
-    case 0:
-        next = 1 << 9;
-        break;
-    case 1:
-        next = 1 << 13;
-        break;
-    case 2:
-        next = 1 << 17;
-        break;
-    case 3:
-        next = 1 << 21;
-        break;
-    default:
-        /* Cannot occur, but makes gcc happy */
-        return;
-    }
-    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->tb_freq);
-    if (next == now)
-        next++;
-    qemu_mod_timer(ppc40x_timer->fit_timer, next);
-    env->spr[SPR_40x_TSR] |= 1 << 26;
-    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) {
-        ppc_set_irq(cpu, PPC_INTERRUPT_FIT, 1);
-    }
-    LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
-           (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
-           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
-}
-
-/* Programmable interval timer */
-static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp)
-{
-    ppc40x_timer_t *ppc40x_timer;
-    uint64_t now, next;
-
-    ppc40x_timer = tb_env->opaque;
-    if (ppc40x_timer->pit_reload <= 1 ||
-        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
-        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
-        /* Stop PIT */
-        LOG_TB("%s: stop PIT\n", __func__);
-        qemu_del_timer(tb_env->decr_timer);
-    } else {
-        LOG_TB("%s: start PIT %016" PRIx64 "\n",
-                    __func__, ppc40x_timer->pit_reload);
-        now = qemu_get_clock_ns(vm_clock);
-        next = now + muldiv64(ppc40x_timer->pit_reload,
-                              get_ticks_per_sec(), tb_env->decr_freq);
-        if (is_excp)
-            next += tb_env->decr_next - now;
-        if (next == now)
-            next++;
-        qemu_mod_timer(tb_env->decr_timer, next);
-        tb_env->decr_next = next;
-    }
-}
-
-static void cpu_4xx_pit_cb (void *opaque)
-{
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    ppc_tb_t *tb_env;
-    ppc40x_timer_t *ppc40x_timer;
-
-    env = opaque;
-    cpu = ppc_env_get_cpu(env);
-    tb_env = env->tb_env;
-    ppc40x_timer = tb_env->opaque;
-    env->spr[SPR_40x_TSR] |= 1 << 27;
-    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) {
-        ppc_set_irq(cpu, ppc40x_timer->decr_excp, 1);
-    }
-    start_stop_pit(env, tb_env, 1);
-    LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
-           "%016" PRIx64 "\n", __func__,
-           (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
-           (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
-           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
-           ppc40x_timer->pit_reload);
-}
-
-/* Watchdog timer */
-static void cpu_4xx_wdt_cb (void *opaque)
-{
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    ppc_tb_t *tb_env;
-    ppc40x_timer_t *ppc40x_timer;
-    uint64_t now, next;
-
-    env = opaque;
-    cpu = ppc_env_get_cpu(env);
-    tb_env = env->tb_env;
-    ppc40x_timer = tb_env->opaque;
-    now = qemu_get_clock_ns(vm_clock);
-    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
-    case 0:
-        next = 1 << 17;
-        break;
-    case 1:
-        next = 1 << 21;
-        break;
-    case 2:
-        next = 1 << 25;
-        break;
-    case 3:
-        next = 1 << 29;
-        break;
-    default:
-        /* Cannot occur, but makes gcc happy */
-        return;
-    }
-    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->decr_freq);
-    if (next == now)
-        next++;
-    LOG_TB("%s: TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
-           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
-    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
-    case 0x0:
-    case 0x1:
-        qemu_mod_timer(ppc40x_timer->wdt_timer, next);
-        ppc40x_timer->wdt_next = next;
-        env->spr[SPR_40x_TSR] |= 1 << 31;
-        break;
-    case 0x2:
-        qemu_mod_timer(ppc40x_timer->wdt_timer, next);
-        ppc40x_timer->wdt_next = next;
-        env->spr[SPR_40x_TSR] |= 1 << 30;
-        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) {
-            ppc_set_irq(cpu, PPC_INTERRUPT_WDT, 1);
-        }
-        break;
-    case 0x3:
-        env->spr[SPR_40x_TSR] &= ~0x30000000;
-        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
-        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
-        case 0x0:
-            /* No reset */
-            break;
-        case 0x1: /* Core reset */
-            ppc40x_core_reset(cpu);
-            break;
-        case 0x2: /* Chip reset */
-            ppc40x_chip_reset(cpu);
-            break;
-        case 0x3: /* System reset */
-            ppc40x_system_reset(cpu);
-            break;
-        }
-    }
-}
-
-void store_40x_pit (CPUPPCState *env, target_ulong val)
-{
-    ppc_tb_t *tb_env;
-    ppc40x_timer_t *ppc40x_timer;
-
-    tb_env = env->tb_env;
-    ppc40x_timer = tb_env->opaque;
-    LOG_TB("%s val" TARGET_FMT_lx "\n", __func__, val);
-    ppc40x_timer->pit_reload = val;
-    start_stop_pit(env, tb_env, 0);
-}
-
-target_ulong load_40x_pit (CPUPPCState *env)
-{
-    return cpu_ppc_load_decr(env);
-}
-
-static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq)
-{
-    CPUPPCState *env = opaque;
-    ppc_tb_t *tb_env = env->tb_env;
-
-    LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__,
-                freq);
-    tb_env->tb_freq = freq;
-    tb_env->decr_freq = freq;
-    /* XXX: we should also update all timers */
-}
-
-clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq,
-                                  unsigned int decr_excp)
-{
-    ppc_tb_t *tb_env;
-    ppc40x_timer_t *ppc40x_timer;
-
-    tb_env = g_malloc0(sizeof(ppc_tb_t));
-    env->tb_env = tb_env;
-    tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
-    ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t));
-    tb_env->tb_freq = freq;
-    tb_env->decr_freq = freq;
-    tb_env->opaque = ppc40x_timer;
-    LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
-    if (ppc40x_timer != NULL) {
-        /* We use decr timer for PIT */
-        tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_4xx_pit_cb, env);
-        ppc40x_timer->fit_timer =
-            qemu_new_timer_ns(vm_clock, &cpu_4xx_fit_cb, env);
-        ppc40x_timer->wdt_timer =
-            qemu_new_timer_ns(vm_clock, &cpu_4xx_wdt_cb, env);
-        ppc40x_timer->decr_excp = decr_excp;
-    }
-
-    return &ppc_40x_set_tb_clk;
-}
-
-/*****************************************************************************/
-/* Embedded PowerPC Device Control Registers */
-typedef struct ppc_dcrn_t ppc_dcrn_t;
-struct ppc_dcrn_t {
-    dcr_read_cb dcr_read;
-    dcr_write_cb dcr_write;
-    void *opaque;
-};
-
-/* XXX: on 460, DCR addresses are 32 bits wide,
- *      using DCRIPR to get the 22 upper bits of the DCR address
- */
-#define DCRN_NB 1024
-struct ppc_dcr_t {
-    ppc_dcrn_t dcrn[DCRN_NB];
-    int (*read_error)(int dcrn);
-    int (*write_error)(int dcrn);
-};
-
-int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
-{
-    ppc_dcrn_t *dcr;
-
-    if (dcrn < 0 || dcrn >= DCRN_NB)
-        goto error;
-    dcr = &dcr_env->dcrn[dcrn];
-    if (dcr->dcr_read == NULL)
-        goto error;
-    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
-
-    return 0;
-
- error:
-    if (dcr_env->read_error != NULL)
-        return (*dcr_env->read_error)(dcrn);
-
-    return -1;
-}
-
-int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
-{
-    ppc_dcrn_t *dcr;
-
-    if (dcrn < 0 || dcrn >= DCRN_NB)
-        goto error;
-    dcr = &dcr_env->dcrn[dcrn];
-    if (dcr->dcr_write == NULL)
-        goto error;
-    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
-
-    return 0;
-
- error:
-    if (dcr_env->write_error != NULL)
-        return (*dcr_env->write_error)(dcrn);
-
-    return -1;
-}
-
-int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque,
-                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
-{
-    ppc_dcr_t *dcr_env;
-    ppc_dcrn_t *dcr;
-
-    dcr_env = env->dcr_env;
-    if (dcr_env == NULL)
-        return -1;
-    if (dcrn < 0 || dcrn >= DCRN_NB)
-        return -1;
-    dcr = &dcr_env->dcrn[dcrn];
-    if (dcr->opaque != NULL ||
-        dcr->dcr_read != NULL ||
-        dcr->dcr_write != NULL)
-        return -1;
-    dcr->opaque = opaque;
-    dcr->dcr_read = dcr_read;
-    dcr->dcr_write = dcr_write;
-
-    return 0;
-}
-
-int ppc_dcr_init (CPUPPCState *env, int (*read_error)(int dcrn),
-                  int (*write_error)(int dcrn))
-{
-    ppc_dcr_t *dcr_env;
-
-    dcr_env = g_malloc0(sizeof(ppc_dcr_t));
-    dcr_env->read_error = read_error;
-    dcr_env->write_error = write_error;
-    env->dcr_env = dcr_env;
-
-    return 0;
-}
-
-/*****************************************************************************/
-/* Debug port */
-void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
-{
-    addr &= 0xF;
-    switch (addr) {
-    case 0:
-        printf("%c", val);
-        break;
-    case 1:
-        printf("\n");
-        fflush(stdout);
-        break;
-    case 2:
-        printf("Set loglevel to %04" PRIx32 "\n", val);
-        qemu_set_log(val | 0x100);
-        break;
-    }
-}
-
-/*****************************************************************************/
-/* NVRAM helpers */
-static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
-{
-    return (*nvram->read_fn)(nvram->opaque, addr);
-}
-
-static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
-{
-    (*nvram->write_fn)(nvram->opaque, addr, val);
-}
-
-static void NVRAM_set_byte(nvram_t *nvram, uint32_t addr, uint8_t value)
-{
-    nvram_write(nvram, addr, value);
-}
-
-static uint8_t NVRAM_get_byte(nvram_t *nvram, uint32_t addr)
-{
-    return nvram_read(nvram, addr);
-}
-
-static void NVRAM_set_word(nvram_t *nvram, uint32_t addr, uint16_t value)
-{
-    nvram_write(nvram, addr, value >> 8);
-    nvram_write(nvram, addr + 1, value & 0xFF);
-}
-
-static uint16_t NVRAM_get_word(nvram_t *nvram, uint32_t addr)
-{
-    uint16_t tmp;
-
-    tmp = nvram_read(nvram, addr) << 8;
-    tmp |= nvram_read(nvram, addr + 1);
-
-    return tmp;
-}
-
-static void NVRAM_set_lword(nvram_t *nvram, uint32_t addr, uint32_t value)
-{
-    nvram_write(nvram, addr, value >> 24);
-    nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
-    nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
-    nvram_write(nvram, addr + 3, value & 0xFF);
-}
-
-uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
-{
-    uint32_t tmp;
-
-    tmp = nvram_read(nvram, addr) << 24;
-    tmp |= nvram_read(nvram, addr + 1) << 16;
-    tmp |= nvram_read(nvram, addr + 2) << 8;
-    tmp |= nvram_read(nvram, addr + 3);
-
-    return tmp;
-}
-
-static void NVRAM_set_string(nvram_t *nvram, uint32_t addr, const char *str,
-                             uint32_t max)
-{
-    int i;
-
-    for (i = 0; i < max && str[i] != '\0'; i++) {
-        nvram_write(nvram, addr + i, str[i]);
-    }
-    nvram_write(nvram, addr + i, str[i]);
-    nvram_write(nvram, addr + max - 1, '\0');
-}
-
-int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
-{
-    int i;
-
-    memset(dst, 0, max);
-    for (i = 0; i < max; i++) {
-        dst[i] = NVRAM_get_byte(nvram, addr + i);
-        if (dst[i] == '\0')
-            break;
-    }
-
-    return i;
-}
-
-static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
-{
-    uint16_t tmp;
-    uint16_t pd, pd1, pd2;
-
-    tmp = prev >> 8;
-    pd = prev ^ value;
-    pd1 = pd & 0x000F;
-    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
-    tmp ^= (pd1 << 3) | (pd1 << 8);
-    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
-
-    return tmp;
-}
-
-static uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
-{
-    uint32_t i;
-    uint16_t crc = 0xFFFF;
-    int odd;
-
-    odd = count & 1;
-    count &= ~1;
-    for (i = 0; i != count; i++) {
-        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
-    }
-    if (odd) {
-        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
-    }
-
-    return crc;
-}
-
-#define CMDLINE_ADDR 0x017ff000
-
-int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
-                          const char *arch,
-                          uint32_t RAM_size, int boot_device,
-                          uint32_t kernel_image, uint32_t kernel_size,
-                          const char *cmdline,
-                          uint32_t initrd_image, uint32_t initrd_size,
-                          uint32_t NVRAM_image,
-                          int width, int height, int depth)
-{
-    uint16_t crc;
-
-    /* Set parameters for Open Hack'Ware BIOS */
-    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
-    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
-    NVRAM_set_word(nvram,   0x14, NVRAM_size);
-    NVRAM_set_string(nvram, 0x20, arch, 16);
-    NVRAM_set_lword(nvram,  0x30, RAM_size);
-    NVRAM_set_byte(nvram,   0x34, boot_device);
-    NVRAM_set_lword(nvram,  0x38, kernel_image);
-    NVRAM_set_lword(nvram,  0x3C, kernel_size);
-    if (cmdline) {
-        /* XXX: put the cmdline in NVRAM too ? */
-        pstrcpy_targphys("cmdline", CMDLINE_ADDR, RAM_size - CMDLINE_ADDR, cmdline);
-        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
-        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
-    } else {
-        NVRAM_set_lword(nvram,  0x40, 0);
-        NVRAM_set_lword(nvram,  0x44, 0);
-    }
-    NVRAM_set_lword(nvram,  0x48, initrd_image);
-    NVRAM_set_lword(nvram,  0x4C, initrd_size);
-    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
-
-    NVRAM_set_word(nvram,   0x54, width);
-    NVRAM_set_word(nvram,   0x56, height);
-    NVRAM_set_word(nvram,   0x58, depth);
-    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
-    NVRAM_set_word(nvram,   0xFC, crc);
-
-    return 0;
-}
index f7620509a9951f92fd9f01481e9556951dfe71ee..4de02098e2a85618c32109c3042b86c3263ab6d7 100644 (file)
@@ -1,28 +1,26 @@
-# shared objects
-obj-y = ppc.o ppc_booke.o
 # PREP target
 obj-y += mc146818rtc.o
 # IBM pSeries (sPAPR)
-obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
-obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
-obj-$(CONFIG_PSERIES) += spapr_pci.o pci/pci-hotplug.o spapr_iommu.o
-obj-$(CONFIG_PSERIES) += spapr_events.o spapr_nvram.o
+obj-$(CONFIG_PSERIES) += spapr_vty.o spapr_llan.o spapr_vscsi.o
+obj-$(CONFIG_PSERIES) += spapr_pci.o pci/pci-hotplug.o
+obj-$(CONFIG_PSERIES) += spapr_nvram.o
 # PowerPC 4xx boards
-obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
-obj-y += ppc440_bamboo.o
-# PowerPC E500 boards
-obj-$(CONFIG_FDT) += mpc8544_guts.o ppce500_spin.o
-# PowerPC 440 Xilinx ML507 reference board.
-obj-y += virtex_ml507.o
+obj-y += ppc4xx_pci.o
 # PowerPC OpenPIC
 obj-y += openpic.o
-obj-$(CONFIG_FDT) += ../device_tree.o
 
 # Xilinx PPC peripherals
 obj-y += xilinx_ethlite.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
+# shared objects
+obj-y += ppc.o ppc_booke.o
+# IBM pSeries (sPAPR)
+obj-$(CONFIG_PSERIES) += spapr.o xics.o spapr_vio.o spapr_events.o
+obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
+# PowerPC 4xx boards
+obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 # PReP
 obj-y += prep.o
 # OldWorld PowerMac
@@ -30,4 +28,7 @@ obj-y += mac_oldworld.o
 # NewWorld PowerMac
 obj-y += mac_newworld.o
 # e500
-obj-$(CONFIG_FDT) += e500.o mpc8544ds.o e500plat.o
+obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o
+obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o
+# PowerPC 440 Xilinx ML507 reference board.
+obj-y += virtex_ml507.o
index f20f51bcd28fca2a4cccfe6e24e51721bb863679..12a2ba4b97826b67408fffaf72ce3788cd4796d1 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef E500_CCSR_H
 #define E500_CCSR_H
 
-#include "../sysbus.h"
+#include "hw/sysbus.h"
 
 typedef struct PPCE500CCSRState {
     /*< private >*/
index 25ac4b1daebf6b6599b1200afd211548c0898f15..4b3057528c69ff80e700d4e13d343e49f5117de1 100644 (file)
@@ -12,7 +12,7 @@
 #include "config.h"
 #include "qemu-common.h"
 #include "e500.h"
-#include "../boards.h"
+#include "hw/boards.h"
 #include "sysemu/device_tree.h"
 #include "hw/pci/pci.h"
 #include "hw/openpic.h"
diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c
new file mode 100644 (file)
index 0000000..193beab
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * QEMU PowerPC MPC8544 global util pseudo-device
+ *
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Alexander Graf, <alex@csgraf.de>
+ *
+ * This 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.
+ *
+ * *****************************************************************
+ *
+ * The documentation for this device is noted in the MPC8544 documentation,
+ * file name "MPC8544ERM.pdf". You can easily find it on the web.
+ *
+ */
+
+#include "hw/hw.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+
+#define MPC8544_GUTS_MMIO_SIZE        0x1000
+#define MPC8544_GUTS_RSTCR_RESET      0x02
+
+#define MPC8544_GUTS_ADDR_PORPLLSR    0x00
+#define MPC8544_GUTS_ADDR_PORBMSR     0x04
+#define MPC8544_GUTS_ADDR_PORIMPSCR   0x08
+#define MPC8544_GUTS_ADDR_PORDEVSR    0x0C
+#define MPC8544_GUTS_ADDR_PORDBGMSR   0x10
+#define MPC8544_GUTS_ADDR_PORDEVSR2   0x14
+#define MPC8544_GUTS_ADDR_GPPORCR     0x20
+#define MPC8544_GUTS_ADDR_GPIOCR      0x30
+#define MPC8544_GUTS_ADDR_GPOUTDR     0x40
+#define MPC8544_GUTS_ADDR_GPINDR      0x50
+#define MPC8544_GUTS_ADDR_PMUXCR      0x60
+#define MPC8544_GUTS_ADDR_DEVDISR     0x70
+#define MPC8544_GUTS_ADDR_POWMGTCSR   0x80
+#define MPC8544_GUTS_ADDR_MCPSUMR     0x90
+#define MPC8544_GUTS_ADDR_RSTRSCR     0x94
+#define MPC8544_GUTS_ADDR_PVR         0xA0
+#define MPC8544_GUTS_ADDR_SVR         0xA4
+#define MPC8544_GUTS_ADDR_RSTCR       0xB0
+#define MPC8544_GUTS_ADDR_IOVSELSR    0xC0
+#define MPC8544_GUTS_ADDR_DDRCSR      0xB20
+#define MPC8544_GUTS_ADDR_DDRCDR      0xB24
+#define MPC8544_GUTS_ADDR_DDRCLKDR    0xB28
+#define MPC8544_GUTS_ADDR_CLKOCR      0xE00
+#define MPC8544_GUTS_ADDR_SRDS1CR1    0xF04
+#define MPC8544_GUTS_ADDR_SRDS2CR1    0xF10
+#define MPC8544_GUTS_ADDR_SRDS2CR3    0xF18
+
+struct GutsState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+};
+
+typedef struct GutsState GutsState;
+
+static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    uint32_t value = 0;
+    CPUPPCState *env = cpu_single_env;
+
+    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
+    switch (addr) {
+    case MPC8544_GUTS_ADDR_PVR:
+        value = env->spr[SPR_PVR];
+        break;
+    case MPC8544_GUTS_ADDR_SVR:
+        value = env->spr[SPR_E500_SVR];
+        break;
+    default:
+        fprintf(stderr, "guts: Unknown register read: %x\n", (int)addr);
+        break;
+    }
+
+    return value;
+}
+
+static void mpc8544_guts_write(void *opaque, hwaddr addr,
+                               uint64_t value, unsigned size)
+{
+    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
+
+    switch (addr) {
+    case MPC8544_GUTS_ADDR_RSTCR:
+        if (value & MPC8544_GUTS_RSTCR_RESET) {
+            qemu_system_reset_request();
+        }
+        break;
+    default:
+        fprintf(stderr, "guts: Unknown register write: %x = %x\n",
+                (int)addr, (unsigned)value);
+        break;
+    }
+}
+
+static const MemoryRegionOps mpc8544_guts_ops = {
+    .read = mpc8544_guts_read,
+    .write = mpc8544_guts_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static int mpc8544_guts_initfn(SysBusDevice *dev)
+{
+    GutsState *s;
+
+    s = FROM_SYSBUS(GutsState, SYS_BUS_DEVICE(dev));
+
+    memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s,
+                          "mpc6544.guts", MPC8544_GUTS_MMIO_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    return 0;
+}
+
+static void mpc8544_guts_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mpc8544_guts_initfn;
+}
+
+static const TypeInfo mpc8544_guts_info = {
+    .name          = "mpc8544-guts",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(GutsState),
+    .class_init    = mpc8544_guts_class_init,
+};
+
+static void mpc8544_guts_register_types(void)
+{
+    type_register_static(&mpc8544_guts_info);
+}
+
+type_init(mpc8544_guts_register_types)
index e25c70b1f3117ef4cd5627180c43c3ab71c5e9c3..cf29788c4da8d9dd1b93d800a0af5e6b6cadc11a 100644 (file)
@@ -12,7 +12,7 @@
 #include "config.h"
 #include "qemu-common.h"
 #include "e500.h"
-#include "../boards.h"
+#include "hw/boards.h"
 #include "sysemu/device_tree.h"
 #include "hw/openpic.h"
 
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
new file mode 100644 (file)
index 0000000..c9437fc
--- /dev/null
@@ -0,0 +1,1356 @@
+/*
+ * QEMU generic PowerPC hardware System Emulator
+ *
+ * Copyright (c) 2003-2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "hw/ppc.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "hw/nvram.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+
+//#define PPC_DEBUG_IRQ
+//#define PPC_DEBUG_TB
+
+#ifdef PPC_DEBUG_IRQ
+#  define LOG_IRQ(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
+#else
+#  define LOG_IRQ(...) do { } while (0)
+#endif
+
+
+#ifdef PPC_DEBUG_TB
+#  define LOG_TB(...) qemu_log(__VA_ARGS__)
+#else
+#  define LOG_TB(...) do { } while (0)
+#endif
+
+static void cpu_ppc_tb_stop (CPUPPCState *env);
+static void cpu_ppc_tb_start (CPUPPCState *env);
+
+void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
+{
+    CPUPPCState *env = &cpu->env;
+    unsigned int old_pending = env->pending_interrupts;
+
+    if (level) {
+        env->pending_interrupts |= 1 << n_IRQ;
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        env->pending_interrupts &= ~(1 << n_IRQ);
+        if (env->pending_interrupts == 0)
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+
+    if (old_pending != env->pending_interrupts) {
+#ifdef CONFIG_KVM
+        kvmppc_set_interrupt(cpu, n_IRQ, level);
+#endif
+    }
+
+    LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
+                "req %08x\n", __func__, env, n_IRQ, level,
+                env->pending_interrupts, env->interrupt_request);
+}
+
+/* PowerPC 6xx / 7xx internal IRQ controller */
+static void ppc6xx_set_irq(void *opaque, int pin, int level)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    int cur_level;
+
+    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC6xx_INPUT_TBEN:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: %s the time base\n",
+                        __func__, level ? "start" : "stop");
+            if (level) {
+                cpu_ppc_tb_start(env);
+            } else {
+                cpu_ppc_tb_stop(env);
+            }
+        case PPC6xx_INPUT_INT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC6xx_INPUT_SMI:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the SMI IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_SMI, level);
+            break;
+        case PPC6xx_INPUT_MCP:
+            /* Negative edge sensitive */
+            /* XXX: TODO: actual reaction may depends on HID0 status
+             *            603/604/740/750: check HID0[EMCP]
+             */
+            if (cur_level == 1 && level == 0) {
+                LOG_IRQ("%s: raise machine check state\n",
+                            __func__);
+                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
+            }
+            break;
+        case PPC6xx_INPUT_CKSTP_IN:
+            /* Level sensitive - active low */
+            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
+            /* XXX: Note that the only way to restart the CPU is to reset it */
+            if (level) {
+                LOG_IRQ("%s: stop the CPU\n", __func__);
+                env->halted = 1;
+            }
+            break;
+        case PPC6xx_INPUT_HRESET:
+            /* Level sensitive - active low */
+            if (level) {
+                LOG_IRQ("%s: reset the CPU\n", __func__);
+                cpu_interrupt(env, CPU_INTERRUPT_RESET);
+            }
+            break;
+        case PPC6xx_INPUT_SRESET:
+            LOG_IRQ("%s: set the RESET IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
+            break;
+        default:
+            /* Unknown pin - do nothing */
+            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppc6xx_irq_init(CPUPPCState *env)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, cpu,
+                                                  PPC6xx_INPUT_NB);
+}
+
+#if defined(TARGET_PPC64)
+/* PowerPC 970 internal IRQ controller */
+static void ppc970_set_irq(void *opaque, int pin, int level)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    int cur_level;
+
+    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC970_INPUT_INT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC970_INPUT_THINT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
+                        level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_THERM, level);
+            break;
+        case PPC970_INPUT_MCP:
+            /* Negative edge sensitive */
+            /* XXX: TODO: actual reaction may depends on HID0 status
+             *            603/604/740/750: check HID0[EMCP]
+             */
+            if (cur_level == 1 && level == 0) {
+                LOG_IRQ("%s: raise machine check state\n",
+                            __func__);
+                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
+            }
+            break;
+        case PPC970_INPUT_CKSTP:
+            /* Level sensitive - active low */
+            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
+            if (level) {
+                LOG_IRQ("%s: stop the CPU\n", __func__);
+                env->halted = 1;
+            } else {
+                LOG_IRQ("%s: restart the CPU\n", __func__);
+                env->halted = 0;
+                qemu_cpu_kick(CPU(cpu));
+            }
+            break;
+        case PPC970_INPUT_HRESET:
+            /* Level sensitive - active low */
+            if (level) {
+                cpu_interrupt(env, CPU_INTERRUPT_RESET);
+            }
+            break;
+        case PPC970_INPUT_SRESET:
+            LOG_IRQ("%s: set the RESET IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
+            break;
+        case PPC970_INPUT_TBEN:
+            LOG_IRQ("%s: set the TBEN state to %d\n", __func__,
+                        level);
+            /* XXX: TODO */
+            break;
+        default:
+            /* Unknown pin - do nothing */
+            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppc970_irq_init(CPUPPCState *env)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, cpu,
+                                                  PPC970_INPUT_NB);
+}
+
+/* POWER7 internal IRQ controller */
+static void power7_set_irq(void *opaque, int pin, int level)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+
+    switch (pin) {
+    case POWER7_INPUT_INT:
+        /* Level sensitive - active high */
+        LOG_IRQ("%s: set the external IRQ state to %d\n",
+                __func__, level);
+        ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
+        break;
+    default:
+        /* Unknown pin - do nothing */
+        LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
+        return;
+    }
+    if (level) {
+        env->irq_input_state |= 1 << pin;
+    } else {
+        env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppcPOWER7_irq_init(CPUPPCState *env)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu,
+                                                  POWER7_INPUT_NB);
+}
+#endif /* defined(TARGET_PPC64) */
+
+/* PowerPC 40x internal IRQ controller */
+static void ppc40x_set_irq(void *opaque, int pin, int level)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    int cur_level;
+
+    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC40x_INPUT_RESET_SYS:
+            if (level) {
+                LOG_IRQ("%s: reset the PowerPC system\n",
+                            __func__);
+                ppc40x_system_reset(cpu);
+            }
+            break;
+        case PPC40x_INPUT_RESET_CHIP:
+            if (level) {
+                LOG_IRQ("%s: reset the PowerPC chip\n", __func__);
+                ppc40x_chip_reset(cpu);
+            }
+            break;
+        case PPC40x_INPUT_RESET_CORE:
+            /* XXX: TODO: update DBSR[MRR] */
+            if (level) {
+                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
+                ppc40x_core_reset(cpu);
+            }
+            break;
+        case PPC40x_INPUT_CINT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the critical IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
+            break;
+        case PPC40x_INPUT_INT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC40x_INPUT_HALT:
+            /* Level sensitive - active low */
+            if (level) {
+                LOG_IRQ("%s: stop the CPU\n", __func__);
+                env->halted = 1;
+            } else {
+                LOG_IRQ("%s: restart the CPU\n", __func__);
+                env->halted = 0;
+                qemu_cpu_kick(CPU(cpu));
+            }
+            break;
+        case PPC40x_INPUT_DEBUG:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the debug pin state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
+            break;
+        default:
+            /* Unknown pin - do nothing */
+            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppc40x_irq_init(CPUPPCState *env)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
+                                                  cpu, PPC40x_INPUT_NB);
+}
+
+/* PowerPC E500 internal IRQ controller */
+static void ppce500_set_irq(void *opaque, int pin, int level)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    int cur_level;
+
+    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPCE500_INPUT_MCK:
+            if (level) {
+                LOG_IRQ("%s: reset the PowerPC system\n",
+                            __func__);
+                qemu_system_reset_request();
+            }
+            break;
+        case PPCE500_INPUT_RESET_CORE:
+            if (level) {
+                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
+                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, level);
+            }
+            break;
+        case PPCE500_INPUT_CINT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the critical IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
+            break;
+        case PPCE500_INPUT_INT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the core IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPCE500_INPUT_DEBUG:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the debug pin state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
+            break;
+        default:
+            /* Unknown pin - do nothing */
+            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppce500_irq_init(CPUPPCState *env)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
+                                                  cpu, PPCE500_INPUT_NB);
+}
+
+/* Enable or Disable the E500 EPR capability */
+void ppce500_set_mpic_proxy(bool enabled)
+{
+    CPUPPCState *env;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        PowerPCCPU *cpu = ppc_env_get_cpu(env);
+        CPUState *cs = CPU(cpu);
+
+        env->mpic_proxy = enabled;
+        if (kvm_enabled()) {
+            kvmppc_set_mpic_proxy(POWERPC_CPU(cs), enabled);
+        }
+    }
+}
+
+/*****************************************************************************/
+/* PowerPC time base and decrementer emulation */
+
+uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset)
+{
+    /* TB time in tb periods */
+    return muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec()) + tb_offset;
+}
+
+uint64_t cpu_ppc_load_tbl (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    if (kvm_enabled()) {
+        return env->spr[SPR_TBL];
+    }
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
+    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
+
+    return tb;
+}
+
+static inline uint32_t _cpu_ppc_load_tbu(CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
+    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
+
+    return tb >> 32;
+}
+
+uint32_t cpu_ppc_load_tbu (CPUPPCState *env)
+{
+    if (kvm_enabled()) {
+        return env->spr[SPR_TBU];
+    }
+
+    return _cpu_ppc_load_tbu(env);
+}
+
+static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
+                                    int64_t *tb_offsetp, uint64_t value)
+{
+    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec());
+    LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
+                __func__, value, *tb_offsetp);
+}
+
+void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
+    tb &= 0xFFFFFFFF00000000ULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+                     &tb_env->tb_offset, tb | (uint64_t)value);
+}
+
+static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
+    tb &= 0x00000000FFFFFFFFULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
+}
+
+void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value)
+{
+    _cpu_ppc_store_tbu(env, value);
+}
+
+uint64_t cpu_ppc_load_atbl (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
+    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
+
+    return tb;
+}
+
+uint32_t cpu_ppc_load_atbu (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
+    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
+
+    return tb >> 32;
+}
+
+void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
+    tb &= 0xFFFFFFFF00000000ULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+                     &tb_env->atb_offset, tb | (uint64_t)value);
+}
+
+void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
+    tb &= 0x00000000FFFFFFFFULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+                     &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
+}
+
+static void cpu_ppc_tb_stop (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb, atb, vmclk;
+
+    /* If the time base is already frozen, do nothing */
+    if (tb_env->tb_freq != 0) {
+        vmclk = qemu_get_clock_ns(vm_clock);
+        /* Get the time base */
+        tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
+        /* Get the alternate time base */
+        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
+        /* Store the time base value (ie compute the current offset) */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
+        /* Store the alternate time base value (compute the current offset) */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
+        /* Set the time base frequency to zero */
+        tb_env->tb_freq = 0;
+        /* Now, the time bases are frozen to tb_offset / atb_offset value */
+    }
+}
+
+static void cpu_ppc_tb_start (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb, atb, vmclk;
+
+    /* If the time base is not frozen, do nothing */
+    if (tb_env->tb_freq == 0) {
+        vmclk = qemu_get_clock_ns(vm_clock);
+        /* Get the time base from tb_offset */
+        tb = tb_env->tb_offset;
+        /* Get the alternate time base from atb_offset */
+        atb = tb_env->atb_offset;
+        /* Restore the tb frequency from the decrementer frequency */
+        tb_env->tb_freq = tb_env->decr_freq;
+        /* Store the time base value */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
+        /* Store the alternate time base value */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
+    }
+}
+
+static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint32_t decr;
+    int64_t diff;
+
+    diff = next - qemu_get_clock_ns(vm_clock);
+    if (diff >= 0) {
+        decr = muldiv64(diff, tb_env->decr_freq, get_ticks_per_sec());
+    } else if (tb_env->flags & PPC_TIMER_BOOKE) {
+        decr = 0;
+    }  else {
+        decr = -muldiv64(-diff, tb_env->decr_freq, get_ticks_per_sec());
+    }
+    LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
+
+    return decr;
+}
+
+uint32_t cpu_ppc_load_decr (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+
+    if (kvm_enabled()) {
+        return env->spr[SPR_DECR];
+    }
+
+    return _cpu_ppc_load_decr(env, tb_env->decr_next);
+}
+
+uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+
+    return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
+}
+
+uint64_t cpu_ppc_load_purr (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t diff;
+
+    diff = qemu_get_clock_ns(vm_clock) - tb_env->purr_start;
+
+    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, get_ticks_per_sec());
+}
+
+/* When decrementer expires,
+ * all we need to do is generate or queue a CPU exception
+ */
+static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu)
+{
+    /* Raise it */
+    LOG_TB("raise decrementer exception\n");
+    ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1);
+}
+
+static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
+{
+    /* Raise it */
+    LOG_TB("raise decrementer exception\n");
+    ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
+}
+
+static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
+                                 struct QEMUTimer *timer,
+                                 void (*raise_excp)(PowerPCCPU *),
+                                 uint32_t decr, uint32_t value,
+                                 int is_excp)
+{
+    CPUPPCState *env = &cpu->env;
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t now, next;
+
+    LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
+                decr, value);
+
+    if (kvm_enabled()) {
+        /* KVM handles decrementer exceptions, we don't need our own timer */
+        return;
+    }
+
+    now = qemu_get_clock_ns(vm_clock);
+    next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
+    if (is_excp) {
+        next += *nextp - now;
+    }
+    if (next == now) {
+        next++;
+    }
+    *nextp = next;
+    /* Adjust timer */
+    qemu_mod_timer(timer, next);
+
+    /* If we set a negative value and the decrementer was positive, raise an
+     * exception.
+     */
+    if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
+        && (value & 0x80000000)
+        && !(decr & 0x80000000)) {
+        (*raise_excp)(cpu);
+    }
+}
+
+static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
+                                       uint32_t value, int is_excp)
+{
+    ppc_tb_t *tb_env = cpu->env.tb_env;
+
+    __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
+                         &cpu_ppc_decr_excp, decr, value, is_excp);
+}
+
+void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0);
+}
+
+static void cpu_ppc_decr_cb(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+
+    _cpu_ppc_store_decr(cpu, 0x00000000, 0xFFFFFFFF, 1);
+}
+
+static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
+                                        uint32_t value, int is_excp)
+{
+    ppc_tb_t *tb_env = cpu->env.tb_env;
+
+    if (tb_env->hdecr_timer != NULL) {
+        __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
+                             &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
+    }
+}
+
+void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, 0);
+}
+
+static void cpu_ppc_hdecr_cb(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+
+    _cpu_ppc_store_hdecr(cpu, 0x00000000, 0xFFFFFFFF, 1);
+}
+
+static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
+{
+    ppc_tb_t *tb_env = cpu->env.tb_env;
+
+    tb_env->purr_load = value;
+    tb_env->purr_start = qemu_get_clock_ns(vm_clock);
+}
+
+static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
+{
+    CPUPPCState *env = opaque;
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    ppc_tb_t *tb_env = env->tb_env;
+
+    tb_env->tb_freq = freq;
+    tb_env->decr_freq = freq;
+    /* There is a bug in Linux 2.4 kernels:
+     * if a decrementer exception is pending when it enables msr_ee at startup,
+     * it's not ready to handle it...
+     */
+    _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+    _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+    cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
+}
+
+/* Set up (once) timebase frequency (in Hz) */
+clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    ppc_tb_t *tb_env;
+
+    tb_env = g_malloc0(sizeof(ppc_tb_t));
+    env->tb_env = tb_env;
+    tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
+    /* Create new timer */
+    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, cpu);
+    if (0) {
+        /* XXX: find a suitable condition to enable the hypervisor decrementer
+         */
+        tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb,
+                                                cpu);
+    } else {
+        tb_env->hdecr_timer = NULL;
+    }
+    cpu_ppc_set_tb_clk(env, freq);
+
+    return &cpu_ppc_set_tb_clk;
+}
+
+/* Specific helpers for POWER & PowerPC 601 RTC */
+#if 0
+static clk_setup_cb cpu_ppc601_rtc_init (CPUPPCState *env)
+{
+    return cpu_ppc_tb_init(env, 7812500);
+}
+#endif
+
+void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value)
+{
+    _cpu_ppc_store_tbu(env, value);
+}
+
+uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env)
+{
+    return _cpu_ppc_load_tbu(env);
+}
+
+void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value)
+{
+    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
+}
+
+uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env)
+{
+    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
+}
+
+/*****************************************************************************/
+/* PowerPC 40x timers */
+
+/* PIT, FIT & WDT */
+typedef struct ppc40x_timer_t ppc40x_timer_t;
+struct ppc40x_timer_t {
+    uint64_t pit_reload;  /* PIT auto-reload value        */
+    uint64_t fit_next;    /* Tick for next FIT interrupt  */
+    struct QEMUTimer *fit_timer;
+    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
+    struct QEMUTimer *wdt_timer;
+
+    /* 405 have the PIT, 440 have a DECR.  */
+    unsigned int decr_excp;
+};
+
+/* Fixed interval timer */
+static void cpu_4xx_fit_cb (void *opaque)
+{
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    ppc_tb_t *tb_env;
+    ppc40x_timer_t *ppc40x_timer;
+    uint64_t now, next;
+
+    env = opaque;
+    cpu = ppc_env_get_cpu(env);
+    tb_env = env->tb_env;
+    ppc40x_timer = tb_env->opaque;
+    now = qemu_get_clock_ns(vm_clock);
+    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
+    case 0:
+        next = 1 << 9;
+        break;
+    case 1:
+        next = 1 << 13;
+        break;
+    case 2:
+        next = 1 << 17;
+        break;
+    case 3:
+        next = 1 << 21;
+        break;
+    default:
+        /* Cannot occur, but makes gcc happy */
+        return;
+    }
+    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->tb_freq);
+    if (next == now)
+        next++;
+    qemu_mod_timer(ppc40x_timer->fit_timer, next);
+    env->spr[SPR_40x_TSR] |= 1 << 26;
+    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) {
+        ppc_set_irq(cpu, PPC_INTERRUPT_FIT, 1);
+    }
+    LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
+           (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
+           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
+}
+
+/* Programmable interval timer */
+static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp)
+{
+    ppc40x_timer_t *ppc40x_timer;
+    uint64_t now, next;
+
+    ppc40x_timer = tb_env->opaque;
+    if (ppc40x_timer->pit_reload <= 1 ||
+        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
+        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
+        /* Stop PIT */
+        LOG_TB("%s: stop PIT\n", __func__);
+        qemu_del_timer(tb_env->decr_timer);
+    } else {
+        LOG_TB("%s: start PIT %016" PRIx64 "\n",
+                    __func__, ppc40x_timer->pit_reload);
+        now = qemu_get_clock_ns(vm_clock);
+        next = now + muldiv64(ppc40x_timer->pit_reload,
+                              get_ticks_per_sec(), tb_env->decr_freq);
+        if (is_excp)
+            next += tb_env->decr_next - now;
+        if (next == now)
+            next++;
+        qemu_mod_timer(tb_env->decr_timer, next);
+        tb_env->decr_next = next;
+    }
+}
+
+static void cpu_4xx_pit_cb (void *opaque)
+{
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    ppc_tb_t *tb_env;
+    ppc40x_timer_t *ppc40x_timer;
+
+    env = opaque;
+    cpu = ppc_env_get_cpu(env);
+    tb_env = env->tb_env;
+    ppc40x_timer = tb_env->opaque;
+    env->spr[SPR_40x_TSR] |= 1 << 27;
+    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) {
+        ppc_set_irq(cpu, ppc40x_timer->decr_excp, 1);
+    }
+    start_stop_pit(env, tb_env, 1);
+    LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
+           "%016" PRIx64 "\n", __func__,
+           (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
+           (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
+           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
+           ppc40x_timer->pit_reload);
+}
+
+/* Watchdog timer */
+static void cpu_4xx_wdt_cb (void *opaque)
+{
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    ppc_tb_t *tb_env;
+    ppc40x_timer_t *ppc40x_timer;
+    uint64_t now, next;
+
+    env = opaque;
+    cpu = ppc_env_get_cpu(env);
+    tb_env = env->tb_env;
+    ppc40x_timer = tb_env->opaque;
+    now = qemu_get_clock_ns(vm_clock);
+    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
+    case 0:
+        next = 1 << 17;
+        break;
+    case 1:
+        next = 1 << 21;
+        break;
+    case 2:
+        next = 1 << 25;
+        break;
+    case 3:
+        next = 1 << 29;
+        break;
+    default:
+        /* Cannot occur, but makes gcc happy */
+        return;
+    }
+    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->decr_freq);
+    if (next == now)
+        next++;
+    LOG_TB("%s: TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
+           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
+    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
+    case 0x0:
+    case 0x1:
+        qemu_mod_timer(ppc40x_timer->wdt_timer, next);
+        ppc40x_timer->wdt_next = next;
+        env->spr[SPR_40x_TSR] |= 1 << 31;
+        break;
+    case 0x2:
+        qemu_mod_timer(ppc40x_timer->wdt_timer, next);
+        ppc40x_timer->wdt_next = next;
+        env->spr[SPR_40x_TSR] |= 1 << 30;
+        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) {
+            ppc_set_irq(cpu, PPC_INTERRUPT_WDT, 1);
+        }
+        break;
+    case 0x3:
+        env->spr[SPR_40x_TSR] &= ~0x30000000;
+        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
+        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
+        case 0x0:
+            /* No reset */
+            break;
+        case 0x1: /* Core reset */
+            ppc40x_core_reset(cpu);
+            break;
+        case 0x2: /* Chip reset */
+            ppc40x_chip_reset(cpu);
+            break;
+        case 0x3: /* System reset */
+            ppc40x_system_reset(cpu);
+            break;
+        }
+    }
+}
+
+void store_40x_pit (CPUPPCState *env, target_ulong val)
+{
+    ppc_tb_t *tb_env;
+    ppc40x_timer_t *ppc40x_timer;
+
+    tb_env = env->tb_env;
+    ppc40x_timer = tb_env->opaque;
+    LOG_TB("%s val" TARGET_FMT_lx "\n", __func__, val);
+    ppc40x_timer->pit_reload = val;
+    start_stop_pit(env, tb_env, 0);
+}
+
+target_ulong load_40x_pit (CPUPPCState *env)
+{
+    return cpu_ppc_load_decr(env);
+}
+
+static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq)
+{
+    CPUPPCState *env = opaque;
+    ppc_tb_t *tb_env = env->tb_env;
+
+    LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__,
+                freq);
+    tb_env->tb_freq = freq;
+    tb_env->decr_freq = freq;
+    /* XXX: we should also update all timers */
+}
+
+clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq,
+                                  unsigned int decr_excp)
+{
+    ppc_tb_t *tb_env;
+    ppc40x_timer_t *ppc40x_timer;
+
+    tb_env = g_malloc0(sizeof(ppc_tb_t));
+    env->tb_env = tb_env;
+    tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
+    ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t));
+    tb_env->tb_freq = freq;
+    tb_env->decr_freq = freq;
+    tb_env->opaque = ppc40x_timer;
+    LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
+    if (ppc40x_timer != NULL) {
+        /* We use decr timer for PIT */
+        tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_4xx_pit_cb, env);
+        ppc40x_timer->fit_timer =
+            qemu_new_timer_ns(vm_clock, &cpu_4xx_fit_cb, env);
+        ppc40x_timer->wdt_timer =
+            qemu_new_timer_ns(vm_clock, &cpu_4xx_wdt_cb, env);
+        ppc40x_timer->decr_excp = decr_excp;
+    }
+
+    return &ppc_40x_set_tb_clk;
+}
+
+/*****************************************************************************/
+/* Embedded PowerPC Device Control Registers */
+typedef struct ppc_dcrn_t ppc_dcrn_t;
+struct ppc_dcrn_t {
+    dcr_read_cb dcr_read;
+    dcr_write_cb dcr_write;
+    void *opaque;
+};
+
+/* XXX: on 460, DCR addresses are 32 bits wide,
+ *      using DCRIPR to get the 22 upper bits of the DCR address
+ */
+#define DCRN_NB 1024
+struct ppc_dcr_t {
+    ppc_dcrn_t dcrn[DCRN_NB];
+    int (*read_error)(int dcrn);
+    int (*write_error)(int dcrn);
+};
+
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
+{
+    ppc_dcrn_t *dcr;
+
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        goto error;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->dcr_read == NULL)
+        goto error;
+    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
+
+    return 0;
+
+ error:
+    if (dcr_env->read_error != NULL)
+        return (*dcr_env->read_error)(dcrn);
+
+    return -1;
+}
+
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
+{
+    ppc_dcrn_t *dcr;
+
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        goto error;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->dcr_write == NULL)
+        goto error;
+    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
+
+    return 0;
+
+ error:
+    if (dcr_env->write_error != NULL)
+        return (*dcr_env->write_error)(dcrn);
+
+    return -1;
+}
+
+int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque,
+                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
+{
+    ppc_dcr_t *dcr_env;
+    ppc_dcrn_t *dcr;
+
+    dcr_env = env->dcr_env;
+    if (dcr_env == NULL)
+        return -1;
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        return -1;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->opaque != NULL ||
+        dcr->dcr_read != NULL ||
+        dcr->dcr_write != NULL)
+        return -1;
+    dcr->opaque = opaque;
+    dcr->dcr_read = dcr_read;
+    dcr->dcr_write = dcr_write;
+
+    return 0;
+}
+
+int ppc_dcr_init (CPUPPCState *env, int (*read_error)(int dcrn),
+                  int (*write_error)(int dcrn))
+{
+    ppc_dcr_t *dcr_env;
+
+    dcr_env = g_malloc0(sizeof(ppc_dcr_t));
+    dcr_env->read_error = read_error;
+    dcr_env->write_error = write_error;
+    env->dcr_env = dcr_env;
+
+    return 0;
+}
+
+/*****************************************************************************/
+/* Debug port */
+void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
+{
+    addr &= 0xF;
+    switch (addr) {
+    case 0:
+        printf("%c", val);
+        break;
+    case 1:
+        printf("\n");
+        fflush(stdout);
+        break;
+    case 2:
+        printf("Set loglevel to %04" PRIx32 "\n", val);
+        qemu_set_log(val | 0x100);
+        break;
+    }
+}
+
+/*****************************************************************************/
+/* NVRAM helpers */
+static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
+{
+    return (*nvram->read_fn)(nvram->opaque, addr);
+}
+
+static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
+{
+    (*nvram->write_fn)(nvram->opaque, addr, val);
+}
+
+static void NVRAM_set_byte(nvram_t *nvram, uint32_t addr, uint8_t value)
+{
+    nvram_write(nvram, addr, value);
+}
+
+static uint8_t NVRAM_get_byte(nvram_t *nvram, uint32_t addr)
+{
+    return nvram_read(nvram, addr);
+}
+
+static void NVRAM_set_word(nvram_t *nvram, uint32_t addr, uint16_t value)
+{
+    nvram_write(nvram, addr, value >> 8);
+    nvram_write(nvram, addr + 1, value & 0xFF);
+}
+
+static uint16_t NVRAM_get_word(nvram_t *nvram, uint32_t addr)
+{
+    uint16_t tmp;
+
+    tmp = nvram_read(nvram, addr) << 8;
+    tmp |= nvram_read(nvram, addr + 1);
+
+    return tmp;
+}
+
+static void NVRAM_set_lword(nvram_t *nvram, uint32_t addr, uint32_t value)
+{
+    nvram_write(nvram, addr, value >> 24);
+    nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
+    nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
+    nvram_write(nvram, addr + 3, value & 0xFF);
+}
+
+uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
+{
+    uint32_t tmp;
+
+    tmp = nvram_read(nvram, addr) << 24;
+    tmp |= nvram_read(nvram, addr + 1) << 16;
+    tmp |= nvram_read(nvram, addr + 2) << 8;
+    tmp |= nvram_read(nvram, addr + 3);
+
+    return tmp;
+}
+
+static void NVRAM_set_string(nvram_t *nvram, uint32_t addr, const char *str,
+                             uint32_t max)
+{
+    int i;
+
+    for (i = 0; i < max && str[i] != '\0'; i++) {
+        nvram_write(nvram, addr + i, str[i]);
+    }
+    nvram_write(nvram, addr + i, str[i]);
+    nvram_write(nvram, addr + max - 1, '\0');
+}
+
+int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
+{
+    int i;
+
+    memset(dst, 0, max);
+    for (i = 0; i < max; i++) {
+        dst[i] = NVRAM_get_byte(nvram, addr + i);
+        if (dst[i] == '\0')
+            break;
+    }
+
+    return i;
+}
+
+static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
+{
+    uint16_t tmp;
+    uint16_t pd, pd1, pd2;
+
+    tmp = prev >> 8;
+    pd = prev ^ value;
+    pd1 = pd & 0x000F;
+    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
+    tmp ^= (pd1 << 3) | (pd1 << 8);
+    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
+
+    return tmp;
+}
+
+static uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
+{
+    uint32_t i;
+    uint16_t crc = 0xFFFF;
+    int odd;
+
+    odd = count & 1;
+    count &= ~1;
+    for (i = 0; i != count; i++) {
+        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
+    }
+    if (odd) {
+        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
+    }
+
+    return crc;
+}
+
+#define CMDLINE_ADDR 0x017ff000
+
+int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
+                          const char *arch,
+                          uint32_t RAM_size, int boot_device,
+                          uint32_t kernel_image, uint32_t kernel_size,
+                          const char *cmdline,
+                          uint32_t initrd_image, uint32_t initrd_size,
+                          uint32_t NVRAM_image,
+                          int width, int height, int depth)
+{
+    uint16_t crc;
+
+    /* Set parameters for Open Hack'Ware BIOS */
+    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
+    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
+    NVRAM_set_word(nvram,   0x14, NVRAM_size);
+    NVRAM_set_string(nvram, 0x20, arch, 16);
+    NVRAM_set_lword(nvram,  0x30, RAM_size);
+    NVRAM_set_byte(nvram,   0x34, boot_device);
+    NVRAM_set_lword(nvram,  0x38, kernel_image);
+    NVRAM_set_lword(nvram,  0x3C, kernel_size);
+    if (cmdline) {
+        /* XXX: put the cmdline in NVRAM too ? */
+        pstrcpy_targphys("cmdline", CMDLINE_ADDR, RAM_size - CMDLINE_ADDR, cmdline);
+        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
+        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
+    } else {
+        NVRAM_set_lword(nvram,  0x40, 0);
+        NVRAM_set_lword(nvram,  0x44, 0);
+    }
+    NVRAM_set_lword(nvram,  0x48, initrd_image);
+    NVRAM_set_lword(nvram,  0x4C, initrd_size);
+    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
+
+    NVRAM_set_word(nvram,   0x54, width);
+    NVRAM_set_word(nvram,   0x56, height);
+    NVRAM_set_word(nvram,   0x58, depth);
+    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
+    NVRAM_set_word(nvram,   0xFC, crc);
+
+    return 0;
+}
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
new file mode 100644 (file)
index 0000000..ba443cf
--- /dev/null
@@ -0,0 +1,662 @@
+/*
+ * QEMU PowerPC 405 evaluation boards emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "hw/ppc.h"
+#include "hw/ppc405.h"
+#include "hw/nvram.h"
+#include "hw/flash.h"
+#include "sysemu/sysemu.h"
+#include "block/block.h"
+#include "hw/boards.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define BIOS_FILENAME "ppc405_rom.bin"
+#define BIOS_SIZE (2048 * 1024)
+
+#define KERNEL_LOAD_ADDR 0x00000000
+#define INITRD_LOAD_ADDR 0x01800000
+
+#define USE_FLASH_BIOS
+
+#define DEBUG_BOARD_INIT
+
+/*****************************************************************************/
+/* PPC405EP reference board (IBM) */
+/* Standalone board with:
+ * - PowerPC 405EP CPU
+ * - SDRAM (0x00000000)
+ * - Flash (0xFFF80000)
+ * - SRAM  (0xFFF00000)
+ * - NVRAM (0xF0000000)
+ * - FPGA  (0xF0300000)
+ */
+typedef struct ref405ep_fpga_t ref405ep_fpga_t;
+struct ref405ep_fpga_t {
+    uint8_t reg0;
+    uint8_t reg1;
+};
+
+static uint32_t ref405ep_fpga_readb (void *opaque, hwaddr addr)
+{
+    ref405ep_fpga_t *fpga;
+    uint32_t ret;
+
+    fpga = opaque;
+    switch (addr) {
+    case 0x0:
+        ret = fpga->reg0;
+        break;
+    case 0x1:
+        ret = fpga->reg1;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void ref405ep_fpga_writeb (void *opaque,
+                                  hwaddr addr, uint32_t value)
+{
+    ref405ep_fpga_t *fpga;
+
+    fpga = opaque;
+    switch (addr) {
+    case 0x0:
+        /* Read only */
+        break;
+    case 0x1:
+        fpga->reg1 = value;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t ref405ep_fpga_readw (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+    ret = ref405ep_fpga_readb(opaque, addr) << 8;
+    ret |= ref405ep_fpga_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void ref405ep_fpga_writew (void *opaque,
+                                  hwaddr addr, uint32_t value)
+{
+    ref405ep_fpga_writeb(opaque, addr, (value >> 8) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 1, value & 0xFF);
+}
+
+static uint32_t ref405ep_fpga_readl (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+    ret = ref405ep_fpga_readb(opaque, addr) << 24;
+    ret |= ref405ep_fpga_readb(opaque, addr + 1) << 16;
+    ret |= ref405ep_fpga_readb(opaque, addr + 2) << 8;
+    ret |= ref405ep_fpga_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void ref405ep_fpga_writel (void *opaque,
+                                  hwaddr addr, uint32_t value)
+{
+    ref405ep_fpga_writeb(opaque, addr, (value >> 24) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 1, (value >> 16) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 2, (value >> 8) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 3, value & 0xFF);
+}
+
+static const MemoryRegionOps ref405ep_fpga_ops = {
+    .old_mmio = {
+        .read = {
+            ref405ep_fpga_readb, ref405ep_fpga_readw, ref405ep_fpga_readl,
+        },
+        .write = {
+            ref405ep_fpga_writeb, ref405ep_fpga_writew, ref405ep_fpga_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ref405ep_fpga_reset (void *opaque)
+{
+    ref405ep_fpga_t *fpga;
+
+    fpga = opaque;
+    fpga->reg0 = 0x00;
+    fpga->reg1 = 0x0F;
+}
+
+static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base)
+{
+    ref405ep_fpga_t *fpga;
+    MemoryRegion *fpga_memory = g_new(MemoryRegion, 1);
+
+    fpga = g_malloc0(sizeof(ref405ep_fpga_t));
+    memory_region_init_io(fpga_memory, &ref405ep_fpga_ops, fpga,
+                          "fpga", 0x00000100);
+    memory_region_add_subregion(sysmem, base, fpga_memory);
+    qemu_register_reset(&ref405ep_fpga_reset, fpga);
+}
+
+static void ref405ep_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    ppc4xx_bd_info_t bd;
+    CPUPPCState *env;
+    qemu_irq *pic;
+    MemoryRegion *bios;
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    ram_addr_t bdloc;
+    MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
+    hwaddr ram_bases[2], ram_sizes[2];
+    target_ulong sram_size;
+    long bios_size;
+    //int phy_addr = 0;
+    //static int phy_addr = 1;
+    target_ulong kernel_base, initrd_base;
+    long kernel_size, initrd_size;
+    int linux_boot;
+    int fl_idx, fl_sectors, len;
+    DriveInfo *dinfo;
+    MemoryRegion *sysmem = get_system_memory();
+
+    /* XXX: fix this */
+    memory_region_init_ram(&ram_memories[0], "ef405ep.ram", 0x08000000);
+    vmstate_register_ram_global(&ram_memories[0]);
+    ram_bases[0] = 0;
+    ram_sizes[0] = 0x08000000;
+    memory_region_init(&ram_memories[1], "ef405ep.ram1", 0);
+    ram_bases[1] = 0x00000000;
+    ram_sizes[1] = 0x00000000;
+    ram_size = 128 * 1024 * 1024;
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register cpu\n", __func__);
+#endif
+    env = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
+                        33333333, &pic, kernel_filename == NULL ? 0 : 1);
+    /* allocate SRAM */
+    sram_size = 512 * 1024;
+    memory_region_init_ram(sram, "ef405ep.sram", sram_size);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(sysmem, 0xFFF00000, sram);
+    /* allocate and load BIOS */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register BIOS\n", __func__);
+#endif
+    fl_idx = 0;
+#ifdef USE_FLASH_BIOS
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+    if (dinfo) {
+        bios_size = bdrv_getlength(dinfo->bdrv);
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size %lx"
+               " at addr %lx '%s' %d\n",
+               fl_idx, bios_size, -bios_size,
+               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
+#endif
+        pflash_cfi02_register((uint32_t)(-bios_size),
+                              NULL, "ef405ep.bios", bios_size,
+                              dinfo->bdrv, 65536, fl_sectors, 1,
+                              2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
+                              1);
+        fl_idx++;
+    } else
+#endif
+    {
+#ifdef DEBUG_BOARD_INIT
+        printf("Load BIOS from file\n");
+#endif
+        bios = g_new(MemoryRegion, 1);
+        memory_region_init_ram(bios, "ef405ep.bios", BIOS_SIZE);
+        vmstate_register_ram_global(bios);
+        if (bios_name == NULL)
+            bios_name = BIOS_FILENAME;
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (filename) {
+            bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
+            g_free(filename);
+        } else {
+            bios_size = -1;
+        }
+        if (bios_size < 0 || bios_size > BIOS_SIZE) {
+            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n",
+                    bios_name);
+            exit(1);
+        }
+        bios_size = (bios_size + 0xfff) & ~0xfff;
+        memory_region_set_readonly(bios, true);
+        memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
+    }
+    /* Register FPGA */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register FPGA\n", __func__);
+#endif
+    ref405ep_fpga_init(sysmem, 0xF0300000);
+    /* Register NVRAM */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register NVRAM\n", __func__);
+#endif
+    m48t59_init(NULL, 0xF0000000, 0, 8192, 8);
+    /* Load kernel */
+    linux_boot = (kernel_filename != NULL);
+    if (linux_boot) {
+#ifdef DEBUG_BOARD_INIT
+        printf("%s: load kernel\n", __func__);
+#endif
+        memset(&bd, 0, sizeof(bd));
+        bd.bi_memstart = 0x00000000;
+        bd.bi_memsize = ram_size;
+        bd.bi_flashstart = -bios_size;
+        bd.bi_flashsize = -bios_size;
+        bd.bi_flashoffset = 0;
+        bd.bi_sramstart = 0xFFF00000;
+        bd.bi_sramsize = sram_size;
+        bd.bi_bootflags = 0;
+        bd.bi_intfreq = 133333333;
+        bd.bi_busfreq = 33333333;
+        bd.bi_baudrate = 115200;
+        bd.bi_s_version[0] = 'Q';
+        bd.bi_s_version[1] = 'M';
+        bd.bi_s_version[2] = 'U';
+        bd.bi_s_version[3] = '\0';
+        bd.bi_r_version[0] = 'Q';
+        bd.bi_r_version[1] = 'E';
+        bd.bi_r_version[2] = 'M';
+        bd.bi_r_version[3] = 'U';
+        bd.bi_r_version[4] = '\0';
+        bd.bi_procfreq = 133333333;
+        bd.bi_plb_busfreq = 33333333;
+        bd.bi_pci_busfreq = 33333333;
+        bd.bi_opbfreq = 33333333;
+        bdloc = ppc405_set_bootinfo(env, &bd, 0x00000001);
+        env->gpr[3] = bdloc;
+        kernel_base = KERNEL_LOAD_ADDR;
+        /* now we can load the kernel */
+        kernel_size = load_image_targphys(kernel_filename, kernel_base,
+                                          ram_size - kernel_base);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+        printf("Load kernel size %ld at " TARGET_FMT_lx,
+               kernel_size, kernel_base);
+        /* load initrd */
+        if (initrd_filename) {
+            initrd_base = INITRD_LOAD_ADDR;
+            initrd_size = load_image_targphys(initrd_filename, initrd_base,
+                                              ram_size - initrd_base);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_base = 0;
+            initrd_size = 0;
+        }
+        env->gpr[4] = initrd_base;
+        env->gpr[5] = initrd_size;
+        if (kernel_cmdline != NULL) {
+            len = strlen(kernel_cmdline);
+            bdloc -= ((len + 255) & ~255);
+            cpu_physical_memory_write(bdloc, (void *)kernel_cmdline, len + 1);
+            env->gpr[6] = bdloc;
+            env->gpr[7] = bdloc + len;
+        } else {
+            env->gpr[6] = 0;
+            env->gpr[7] = 0;
+        }
+        env->nip = KERNEL_LOAD_ADDR;
+    } else {
+        kernel_base = 0;
+        kernel_size = 0;
+        initrd_base = 0;
+        initrd_size = 0;
+        bdloc = 0;
+    }
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: Done\n", __func__);
+#endif
+    printf("bdloc " RAM_ADDR_FMT "\n", bdloc);
+}
+
+static QEMUMachine ref405ep_machine = {
+    .name = "ref405ep",
+    .desc = "ref405ep",
+    .init = ref405ep_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+/*****************************************************************************/
+/* AMCC Taihu evaluation board */
+/* - PowerPC 405EP processor
+ * - SDRAM               128 MB at 0x00000000
+ * - Boot flash          2 MB   at 0xFFE00000
+ * - Application flash   32 MB  at 0xFC000000
+ * - 2 serial ports
+ * - 2 ethernet PHY
+ * - 1 USB 1.1 device    0x50000000
+ * - 1 LCD display       0x50100000
+ * - 1 CPLD              0x50100000
+ * - 1 I2C EEPROM
+ * - 1 I2C thermal sensor
+ * - a set of LEDs
+ * - bit-bang SPI port using GPIOs
+ * - 1 EBC interface connector 0 0x50200000
+ * - 1 cardbus controller + expansion slot.
+ * - 1 PCI expansion slot.
+ */
+typedef struct taihu_cpld_t taihu_cpld_t;
+struct taihu_cpld_t {
+    uint8_t reg0;
+    uint8_t reg1;
+};
+
+static uint32_t taihu_cpld_readb (void *opaque, hwaddr addr)
+{
+    taihu_cpld_t *cpld;
+    uint32_t ret;
+
+    cpld = opaque;
+    switch (addr) {
+    case 0x0:
+        ret = cpld->reg0;
+        break;
+    case 0x1:
+        ret = cpld->reg1;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void taihu_cpld_writeb (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+    taihu_cpld_t *cpld;
+
+    cpld = opaque;
+    switch (addr) {
+    case 0x0:
+        /* Read only */
+        break;
+    case 0x1:
+        cpld->reg1 = value;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t taihu_cpld_readw (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+    ret = taihu_cpld_readb(opaque, addr) << 8;
+    ret |= taihu_cpld_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void taihu_cpld_writew (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+    taihu_cpld_writeb(opaque, addr, (value >> 8) & 0xFF);
+    taihu_cpld_writeb(opaque, addr + 1, value & 0xFF);
+}
+
+static uint32_t taihu_cpld_readl (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+    ret = taihu_cpld_readb(opaque, addr) << 24;
+    ret |= taihu_cpld_readb(opaque, addr + 1) << 16;
+    ret |= taihu_cpld_readb(opaque, addr + 2) << 8;
+    ret |= taihu_cpld_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void taihu_cpld_writel (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+    taihu_cpld_writel(opaque, addr, (value >> 24) & 0xFF);
+    taihu_cpld_writel(opaque, addr + 1, (value >> 16) & 0xFF);
+    taihu_cpld_writel(opaque, addr + 2, (value >> 8) & 0xFF);
+    taihu_cpld_writeb(opaque, addr + 3, value & 0xFF);
+}
+
+static const MemoryRegionOps taihu_cpld_ops = {
+    .old_mmio = {
+        .read = { taihu_cpld_readb, taihu_cpld_readw, taihu_cpld_readl, },
+        .write = { taihu_cpld_writeb, taihu_cpld_writew, taihu_cpld_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void taihu_cpld_reset (void *opaque)
+{
+    taihu_cpld_t *cpld;
+
+    cpld = opaque;
+    cpld->reg0 = 0x01;
+    cpld->reg1 = 0x80;
+}
+
+static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base)
+{
+    taihu_cpld_t *cpld;
+    MemoryRegion *cpld_memory = g_new(MemoryRegion, 1);
+
+    cpld = g_malloc0(sizeof(taihu_cpld_t));
+    memory_region_init_io(cpld_memory, &taihu_cpld_ops, cpld, "cpld", 0x100);
+    memory_region_add_subregion(sysmem, base, cpld_memory);
+    qemu_register_reset(&taihu_cpld_reset, cpld);
+}
+
+static void taihu_405ep_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *kernel_filename = args->kernel_filename;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    qemu_irq *pic;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *bios;
+    MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
+    hwaddr ram_bases[2], ram_sizes[2];
+    long bios_size;
+    target_ulong kernel_base, initrd_base;
+    long kernel_size, initrd_size;
+    int linux_boot;
+    int fl_idx, fl_sectors;
+    DriveInfo *dinfo;
+
+    /* RAM is soldered to the board so the size cannot be changed */
+    memory_region_init_ram(&ram_memories[0],
+                           "taihu_405ep.ram-0", 0x04000000);
+    vmstate_register_ram_global(&ram_memories[0]);
+    ram_bases[0] = 0;
+    ram_sizes[0] = 0x04000000;
+    memory_region_init_ram(&ram_memories[1],
+                           "taihu_405ep.ram-1", 0x04000000);
+    vmstate_register_ram_global(&ram_memories[1]);
+    ram_bases[1] = 0x04000000;
+    ram_sizes[1] = 0x04000000;
+    ram_size = 0x08000000;
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register cpu\n", __func__);
+#endif
+    ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
+                  33333333, &pic, kernel_filename == NULL ? 0 : 1);
+    /* allocate and load BIOS */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register BIOS\n", __func__);
+#endif
+    fl_idx = 0;
+#if defined(USE_FLASH_BIOS)
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+    if (dinfo) {
+        bios_size = bdrv_getlength(dinfo->bdrv);
+        /* XXX: should check that size is 2MB */
+        //        bios_size = 2 * 1024 * 1024;
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size %lx"
+               " at addr %lx '%s' %d\n",
+               fl_idx, bios_size, -bios_size,
+               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
+#endif
+        pflash_cfi02_register((uint32_t)(-bios_size),
+                              NULL, "taihu_405ep.bios", bios_size,
+                              dinfo->bdrv, 65536, fl_sectors, 1,
+                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
+                              1);
+        fl_idx++;
+    } else
+#endif
+    {
+#ifdef DEBUG_BOARD_INIT
+        printf("Load BIOS from file\n");
+#endif
+        if (bios_name == NULL)
+            bios_name = BIOS_FILENAME;
+        bios = g_new(MemoryRegion, 1);
+        memory_region_init_ram(bios, "taihu_405ep.bios", BIOS_SIZE);
+        vmstate_register_ram_global(bios);
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (filename) {
+            bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
+            g_free(filename);
+        } else {
+            bios_size = -1;
+        }
+        if (bios_size < 0 || bios_size > BIOS_SIZE) {
+            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n",
+                    bios_name);
+            exit(1);
+        }
+        bios_size = (bios_size + 0xfff) & ~0xfff;
+        memory_region_set_readonly(bios, true);
+        memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
+    }
+    /* Register Linux flash */
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+    if (dinfo) {
+        bios_size = bdrv_getlength(dinfo->bdrv);
+        /* XXX: should check that size is 32MB */
+        bios_size = 32 * 1024 * 1024;
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size %lx"
+               " at addr " TARGET_FMT_lx " '%s'\n",
+               fl_idx, bios_size, (target_ulong)0xfc000000,
+               bdrv_get_device_name(dinfo->bdrv));
+#endif
+        pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size,
+                              dinfo->bdrv, 65536, fl_sectors, 1,
+                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
+                              1);
+        fl_idx++;
+    }
+    /* Register CLPD & LCD display */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register CPLD\n", __func__);
+#endif
+    taihu_cpld_init(sysmem, 0x50100000);
+    /* Load kernel */
+    linux_boot = (kernel_filename != NULL);
+    if (linux_boot) {
+#ifdef DEBUG_BOARD_INIT
+        printf("%s: load kernel\n", __func__);
+#endif
+        kernel_base = KERNEL_LOAD_ADDR;
+        /* now we can load the kernel */
+        kernel_size = load_image_targphys(kernel_filename, kernel_base,
+                                          ram_size - kernel_base);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+        /* load initrd */
+        if (initrd_filename) {
+            initrd_base = INITRD_LOAD_ADDR;
+            initrd_size = load_image_targphys(initrd_filename, initrd_base,
+                                              ram_size - initrd_base);
+            if (initrd_size < 0) {
+                fprintf(stderr,
+                        "qemu: could not load initial ram disk '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_base = 0;
+            initrd_size = 0;
+        }
+    } else {
+        kernel_base = 0;
+        kernel_size = 0;
+        initrd_base = 0;
+        initrd_size = 0;
+    }
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: Done\n", __func__);
+#endif
+}
+
+static QEMUMachine taihu_machine = {
+    .name = "taihu",
+    .desc = "taihu",
+    .init = taihu_405ep_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void ppc405_machine_init(void)
+{
+    qemu_register_machine(&ref405ep_machine);
+    qemu_register_machine(&taihu_machine);
+}
+
+machine_init(ppc405_machine_init);
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
new file mode 100644 (file)
index 0000000..8465f6d
--- /dev/null
@@ -0,0 +1,2548 @@
+/*
+ * QEMU PowerPC 405 embedded processors emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "hw/ppc.h"
+#include "hw/ppc405.h"
+#include "hw/serial.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+
+#define DEBUG_OPBA
+#define DEBUG_SDRAM
+#define DEBUG_GPIO
+#define DEBUG_SERIAL
+#define DEBUG_OCM
+//#define DEBUG_I2C
+#define DEBUG_GPT
+#define DEBUG_MAL
+#define DEBUG_CLOCKS
+//#define DEBUG_CLOCKS_LL
+
+ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
+                                uint32_t flags)
+{
+    ram_addr_t bdloc;
+    int i, n;
+
+    /* We put the bd structure at the top of memory */
+    if (bd->bi_memsize >= 0x01000000UL)
+        bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t);
+    else
+        bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t);
+    stl_be_phys(bdloc + 0x00, bd->bi_memstart);
+    stl_be_phys(bdloc + 0x04, bd->bi_memsize);
+    stl_be_phys(bdloc + 0x08, bd->bi_flashstart);
+    stl_be_phys(bdloc + 0x0C, bd->bi_flashsize);
+    stl_be_phys(bdloc + 0x10, bd->bi_flashoffset);
+    stl_be_phys(bdloc + 0x14, bd->bi_sramstart);
+    stl_be_phys(bdloc + 0x18, bd->bi_sramsize);
+    stl_be_phys(bdloc + 0x1C, bd->bi_bootflags);
+    stl_be_phys(bdloc + 0x20, bd->bi_ipaddr);
+    for (i = 0; i < 6; i++) {
+        stb_phys(bdloc + 0x24 + i, bd->bi_enetaddr[i]);
+    }
+    stw_be_phys(bdloc + 0x2A, bd->bi_ethspeed);
+    stl_be_phys(bdloc + 0x2C, bd->bi_intfreq);
+    stl_be_phys(bdloc + 0x30, bd->bi_busfreq);
+    stl_be_phys(bdloc + 0x34, bd->bi_baudrate);
+    for (i = 0; i < 4; i++) {
+        stb_phys(bdloc + 0x38 + i, bd->bi_s_version[i]);
+    }
+    for (i = 0; i < 32; i++) {
+        stb_phys(bdloc + 0x3C + i, bd->bi_r_version[i]);
+    }
+    stl_be_phys(bdloc + 0x5C, bd->bi_plb_busfreq);
+    stl_be_phys(bdloc + 0x60, bd->bi_pci_busfreq);
+    for (i = 0; i < 6; i++) {
+        stb_phys(bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]);
+    }
+    n = 0x6A;
+    if (flags & 0x00000001) {
+        for (i = 0; i < 6; i++)
+            stb_phys(bdloc + n++, bd->bi_pci_enetaddr2[i]);
+    }
+    stl_be_phys(bdloc + n, bd->bi_opbfreq);
+    n += 4;
+    for (i = 0; i < 2; i++) {
+        stl_be_phys(bdloc + n, bd->bi_iic_fast[i]);
+        n += 4;
+    }
+
+    return bdloc;
+}
+
+/*****************************************************************************/
+/* Shared peripherals */
+
+/*****************************************************************************/
+/* Peripheral local bus arbitrer */
+enum {
+    PLB0_BESR = 0x084,
+    PLB0_BEAR = 0x086,
+    PLB0_ACR  = 0x087,
+};
+
+typedef struct ppc4xx_plb_t ppc4xx_plb_t;
+struct ppc4xx_plb_t {
+    uint32_t acr;
+    uint32_t bear;
+    uint32_t besr;
+};
+
+static uint32_t dcr_read_plb (void *opaque, int dcrn)
+{
+    ppc4xx_plb_t *plb;
+    uint32_t ret;
+
+    plb = opaque;
+    switch (dcrn) {
+    case PLB0_ACR:
+        ret = plb->acr;
+        break;
+    case PLB0_BEAR:
+        ret = plb->bear;
+        break;
+    case PLB0_BESR:
+        ret = plb->besr;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_plb (void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = opaque;
+    switch (dcrn) {
+    case PLB0_ACR:
+        /* We don't care about the actual parameters written as
+         * we don't manage any priorities on the bus
+         */
+        plb->acr = val & 0xF8000000;
+        break;
+    case PLB0_BEAR:
+        /* Read only */
+        break;
+    case PLB0_BESR:
+        /* Write-clear */
+        plb->besr &= ~val;
+        break;
+    }
+}
+
+static void ppc4xx_plb_reset (void *opaque)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = opaque;
+    plb->acr = 0x00000000;
+    plb->bear = 0x00000000;
+    plb->besr = 0x00000000;
+}
+
+static void ppc4xx_plb_init(CPUPPCState *env)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = g_malloc0(sizeof(ppc4xx_plb_t));
+    ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
+    ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
+    ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
+    qemu_register_reset(ppc4xx_plb_reset, plb);
+}
+
+/*****************************************************************************/
+/* PLB to OPB bridge */
+enum {
+    POB0_BESR0 = 0x0A0,
+    POB0_BESR1 = 0x0A2,
+    POB0_BEAR  = 0x0A4,
+};
+
+typedef struct ppc4xx_pob_t ppc4xx_pob_t;
+struct ppc4xx_pob_t {
+    uint32_t bear;
+    uint32_t besr0;
+    uint32_t besr1;
+};
+
+static uint32_t dcr_read_pob (void *opaque, int dcrn)
+{
+    ppc4xx_pob_t *pob;
+    uint32_t ret;
+
+    pob = opaque;
+    switch (dcrn) {
+    case POB0_BEAR:
+        ret = pob->bear;
+        break;
+    case POB0_BESR0:
+        ret = pob->besr0;
+        break;
+    case POB0_BESR1:
+        ret = pob->besr1;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_pob (void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = opaque;
+    switch (dcrn) {
+    case POB0_BEAR:
+        /* Read only */
+        break;
+    case POB0_BESR0:
+        /* Write-clear */
+        pob->besr0 &= ~val;
+        break;
+    case POB0_BESR1:
+        /* Write-clear */
+        pob->besr1 &= ~val;
+        break;
+    }
+}
+
+static void ppc4xx_pob_reset (void *opaque)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = opaque;
+    /* No error */
+    pob->bear = 0x00000000;
+    pob->besr0 = 0x0000000;
+    pob->besr1 = 0x0000000;
+}
+
+static void ppc4xx_pob_init(CPUPPCState *env)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = g_malloc0(sizeof(ppc4xx_pob_t));
+    ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob);
+    ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob);
+    ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob);
+    qemu_register_reset(ppc4xx_pob_reset, pob);
+}
+
+/*****************************************************************************/
+/* OPB arbitrer */
+typedef struct ppc4xx_opba_t ppc4xx_opba_t;
+struct ppc4xx_opba_t {
+    MemoryRegion io;
+    uint8_t cr;
+    uint8_t pr;
+};
+
+static uint32_t opba_readb (void *opaque, hwaddr addr)
+{
+    ppc4xx_opba_t *opba;
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    opba = opaque;
+    switch (addr) {
+    case 0x00:
+        ret = opba->cr;
+        break;
+    case 0x01:
+        ret = opba->pr;
+        break;
+    default:
+        ret = 0x00;
+        break;
+    }
+
+    return ret;
+}
+
+static void opba_writeb (void *opaque,
+                         hwaddr addr, uint32_t value)
+{
+    ppc4xx_opba_t *opba;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    opba = opaque;
+    switch (addr) {
+    case 0x00:
+        opba->cr = value & 0xF8;
+        break;
+    case 0x01:
+        opba->pr = value & 0xFF;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t opba_readw (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = opba_readb(opaque, addr) << 8;
+    ret |= opba_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void opba_writew (void *opaque,
+                         hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    opba_writeb(opaque, addr, value >> 8);
+    opba_writeb(opaque, addr + 1, value);
+}
+
+static uint32_t opba_readl (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = opba_readb(opaque, addr) << 24;
+    ret |= opba_readb(opaque, addr + 1) << 16;
+
+    return ret;
+}
+
+static void opba_writel (void *opaque,
+                         hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    opba_writeb(opaque, addr, value >> 24);
+    opba_writeb(opaque, addr + 1, value >> 16);
+}
+
+static const MemoryRegionOps opba_ops = {
+    .old_mmio = {
+        .read = { opba_readb, opba_readw, opba_readl, },
+        .write = { opba_writeb, opba_writew, opba_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ppc4xx_opba_reset (void *opaque)
+{
+    ppc4xx_opba_t *opba;
+
+    opba = opaque;
+    opba->cr = 0x00; /* No dynamic priorities - park disabled */
+    opba->pr = 0x11;
+}
+
+static void ppc4xx_opba_init(hwaddr base)
+{
+    ppc4xx_opba_t *opba;
+
+    opba = g_malloc0(sizeof(ppc4xx_opba_t));
+#ifdef DEBUG_OPBA
+    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
+#endif
+    memory_region_init_io(&opba->io, &opba_ops, opba, "opba", 0x002);
+    memory_region_add_subregion(get_system_memory(), base, &opba->io);
+    qemu_register_reset(ppc4xx_opba_reset, opba);
+}
+
+/*****************************************************************************/
+/* Code decompression controller */
+/* XXX: TODO */
+
+/*****************************************************************************/
+/* Peripheral controller */
+typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
+struct ppc4xx_ebc_t {
+    uint32_t addr;
+    uint32_t bcr[8];
+    uint32_t bap[8];
+    uint32_t bear;
+    uint32_t besr0;
+    uint32_t besr1;
+    uint32_t cfg;
+};
+
+enum {
+    EBC0_CFGADDR = 0x012,
+    EBC0_CFGDATA = 0x013,
+};
+
+static uint32_t dcr_read_ebc (void *opaque, int dcrn)
+{
+    ppc4xx_ebc_t *ebc;
+    uint32_t ret;
+
+    ebc = opaque;
+    switch (dcrn) {
+    case EBC0_CFGADDR:
+        ret = ebc->addr;
+        break;
+    case EBC0_CFGDATA:
+        switch (ebc->addr) {
+        case 0x00: /* B0CR */
+            ret = ebc->bcr[0];
+            break;
+        case 0x01: /* B1CR */
+            ret = ebc->bcr[1];
+            break;
+        case 0x02: /* B2CR */
+            ret = ebc->bcr[2];
+            break;
+        case 0x03: /* B3CR */
+            ret = ebc->bcr[3];
+            break;
+        case 0x04: /* B4CR */
+            ret = ebc->bcr[4];
+            break;
+        case 0x05: /* B5CR */
+            ret = ebc->bcr[5];
+            break;
+        case 0x06: /* B6CR */
+            ret = ebc->bcr[6];
+            break;
+        case 0x07: /* B7CR */
+            ret = ebc->bcr[7];
+            break;
+        case 0x10: /* B0AP */
+            ret = ebc->bap[0];
+            break;
+        case 0x11: /* B1AP */
+            ret = ebc->bap[1];
+            break;
+        case 0x12: /* B2AP */
+            ret = ebc->bap[2];
+            break;
+        case 0x13: /* B3AP */
+            ret = ebc->bap[3];
+            break;
+        case 0x14: /* B4AP */
+            ret = ebc->bap[4];
+            break;
+        case 0x15: /* B5AP */
+            ret = ebc->bap[5];
+            break;
+        case 0x16: /* B6AP */
+            ret = ebc->bap[6];
+            break;
+        case 0x17: /* B7AP */
+            ret = ebc->bap[7];
+            break;
+        case 0x20: /* BEAR */
+            ret = ebc->bear;
+            break;
+        case 0x21: /* BESR0 */
+            ret = ebc->besr0;
+            break;
+        case 0x22: /* BESR1 */
+            ret = ebc->besr1;
+            break;
+        case 0x23: /* CFG */
+            ret = ebc->cfg;
+            break;
+        default:
+            ret = 0x00000000;
+            break;
+        }
+        break;
+    default:
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_ebc (void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_ebc_t *ebc;
+
+    ebc = opaque;
+    switch (dcrn) {
+    case EBC0_CFGADDR:
+        ebc->addr = val;
+        break;
+    case EBC0_CFGDATA:
+        switch (ebc->addr) {
+        case 0x00: /* B0CR */
+            break;
+        case 0x01: /* B1CR */
+            break;
+        case 0x02: /* B2CR */
+            break;
+        case 0x03: /* B3CR */
+            break;
+        case 0x04: /* B4CR */
+            break;
+        case 0x05: /* B5CR */
+            break;
+        case 0x06: /* B6CR */
+            break;
+        case 0x07: /* B7CR */
+            break;
+        case 0x10: /* B0AP */
+            break;
+        case 0x11: /* B1AP */
+            break;
+        case 0x12: /* B2AP */
+            break;
+        case 0x13: /* B3AP */
+            break;
+        case 0x14: /* B4AP */
+            break;
+        case 0x15: /* B5AP */
+            break;
+        case 0x16: /* B6AP */
+            break;
+        case 0x17: /* B7AP */
+            break;
+        case 0x20: /* BEAR */
+            break;
+        case 0x21: /* BESR0 */
+            break;
+        case 0x22: /* BESR1 */
+            break;
+        case 0x23: /* CFG */
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+static void ebc_reset (void *opaque)
+{
+    ppc4xx_ebc_t *ebc;
+    int i;
+
+    ebc = opaque;
+    ebc->addr = 0x00000000;
+    ebc->bap[0] = 0x7F8FFE80;
+    ebc->bcr[0] = 0xFFE28000;
+    for (i = 0; i < 8; i++) {
+        ebc->bap[i] = 0x00000000;
+        ebc->bcr[i] = 0x00000000;
+    }
+    ebc->besr0 = 0x00000000;
+    ebc->besr1 = 0x00000000;
+    ebc->cfg = 0x80400000;
+}
+
+static void ppc405_ebc_init(CPUPPCState *env)
+{
+    ppc4xx_ebc_t *ebc;
+
+    ebc = g_malloc0(sizeof(ppc4xx_ebc_t));
+    qemu_register_reset(&ebc_reset, ebc);
+    ppc_dcr_register(env, EBC0_CFGADDR,
+                     ebc, &dcr_read_ebc, &dcr_write_ebc);
+    ppc_dcr_register(env, EBC0_CFGDATA,
+                     ebc, &dcr_read_ebc, &dcr_write_ebc);
+}
+
+/*****************************************************************************/
+/* DMA controller */
+enum {
+    DMA0_CR0 = 0x100,
+    DMA0_CT0 = 0x101,
+    DMA0_DA0 = 0x102,
+    DMA0_SA0 = 0x103,
+    DMA0_SG0 = 0x104,
+    DMA0_CR1 = 0x108,
+    DMA0_CT1 = 0x109,
+    DMA0_DA1 = 0x10A,
+    DMA0_SA1 = 0x10B,
+    DMA0_SG1 = 0x10C,
+    DMA0_CR2 = 0x110,
+    DMA0_CT2 = 0x111,
+    DMA0_DA2 = 0x112,
+    DMA0_SA2 = 0x113,
+    DMA0_SG2 = 0x114,
+    DMA0_CR3 = 0x118,
+    DMA0_CT3 = 0x119,
+    DMA0_DA3 = 0x11A,
+    DMA0_SA3 = 0x11B,
+    DMA0_SG3 = 0x11C,
+    DMA0_SR  = 0x120,
+    DMA0_SGC = 0x123,
+    DMA0_SLP = 0x125,
+    DMA0_POL = 0x126,
+};
+
+typedef struct ppc405_dma_t ppc405_dma_t;
+struct ppc405_dma_t {
+    qemu_irq irqs[4];
+    uint32_t cr[4];
+    uint32_t ct[4];
+    uint32_t da[4];
+    uint32_t sa[4];
+    uint32_t sg[4];
+    uint32_t sr;
+    uint32_t sgc;
+    uint32_t slp;
+    uint32_t pol;
+};
+
+static uint32_t dcr_read_dma (void *opaque, int dcrn)
+{
+    return 0;
+}
+
+static void dcr_write_dma (void *opaque, int dcrn, uint32_t val)
+{
+}
+
+static void ppc405_dma_reset (void *opaque)
+{
+    ppc405_dma_t *dma;
+    int i;
+
+    dma = opaque;
+    for (i = 0; i < 4; i++) {
+        dma->cr[i] = 0x00000000;
+        dma->ct[i] = 0x00000000;
+        dma->da[i] = 0x00000000;
+        dma->sa[i] = 0x00000000;
+        dma->sg[i] = 0x00000000;
+    }
+    dma->sr = 0x00000000;
+    dma->sgc = 0x00000000;
+    dma->slp = 0x7C000000;
+    dma->pol = 0x00000000;
+}
+
+static void ppc405_dma_init(CPUPPCState *env, qemu_irq irqs[4])
+{
+    ppc405_dma_t *dma;
+
+    dma = g_malloc0(sizeof(ppc405_dma_t));
+    memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq));
+    qemu_register_reset(&ppc405_dma_reset, dma);
+    ppc_dcr_register(env, DMA0_CR0,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CT0,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_DA0,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SA0,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SG0,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CR1,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CT1,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_DA1,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SA1,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SG1,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CR2,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CT2,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_DA2,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SA2,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SG2,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CR3,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CT3,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_DA3,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SA3,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SG3,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SR,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SGC,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SLP,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_POL,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+}
+
+/*****************************************************************************/
+/* GPIO */
+typedef struct ppc405_gpio_t ppc405_gpio_t;
+struct ppc405_gpio_t {
+    MemoryRegion io;
+    uint32_t or;
+    uint32_t tcr;
+    uint32_t osrh;
+    uint32_t osrl;
+    uint32_t tsrh;
+    uint32_t tsrl;
+    uint32_t odr;
+    uint32_t ir;
+    uint32_t rr1;
+    uint32_t isr1h;
+    uint32_t isr1l;
+};
+
+static uint32_t ppc405_gpio_readb (void *opaque, hwaddr addr)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writeb (void *opaque,
+                                hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+}
+
+static uint32_t ppc405_gpio_readw (void *opaque, hwaddr addr)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writew (void *opaque,
+                                hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+}
+
+static uint32_t ppc405_gpio_readl (void *opaque, hwaddr addr)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writel (void *opaque,
+                                hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+}
+
+static const MemoryRegionOps ppc405_gpio_ops = {
+    .old_mmio = {
+        .read = { ppc405_gpio_readb, ppc405_gpio_readw, ppc405_gpio_readl, },
+        .write = { ppc405_gpio_writeb, ppc405_gpio_writew, ppc405_gpio_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ppc405_gpio_reset (void *opaque)
+{
+}
+
+static void ppc405_gpio_init(hwaddr base)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = g_malloc0(sizeof(ppc405_gpio_t));
+#ifdef DEBUG_GPIO
+    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
+#endif
+    memory_region_init_io(&gpio->io, &ppc405_gpio_ops, gpio, "pgio", 0x038);
+    memory_region_add_subregion(get_system_memory(), base, &gpio->io);
+    qemu_register_reset(&ppc405_gpio_reset, gpio);
+}
+
+/*****************************************************************************/
+/* On Chip Memory */
+enum {
+    OCM0_ISARC   = 0x018,
+    OCM0_ISACNTL = 0x019,
+    OCM0_DSARC   = 0x01A,
+    OCM0_DSACNTL = 0x01B,
+};
+
+typedef struct ppc405_ocm_t ppc405_ocm_t;
+struct ppc405_ocm_t {
+    MemoryRegion ram;
+    MemoryRegion isarc_ram;
+    MemoryRegion dsarc_ram;
+    uint32_t isarc;
+    uint32_t isacntl;
+    uint32_t dsarc;
+    uint32_t dsacntl;
+};
+
+static void ocm_update_mappings (ppc405_ocm_t *ocm,
+                                 uint32_t isarc, uint32_t isacntl,
+                                 uint32_t dsarc, uint32_t dsacntl)
+{
+#ifdef DEBUG_OCM
+    printf("OCM update ISA %08" PRIx32 " %08" PRIx32 " (%08" PRIx32
+           " %08" PRIx32 ") DSA %08" PRIx32 " %08" PRIx32
+           " (%08" PRIx32 " %08" PRIx32 ")\n",
+           isarc, isacntl, dsarc, dsacntl,
+           ocm->isarc, ocm->isacntl, ocm->dsarc, ocm->dsacntl);
+#endif
+    if (ocm->isarc != isarc ||
+        (ocm->isacntl & 0x80000000) != (isacntl & 0x80000000)) {
+        if (ocm->isacntl & 0x80000000) {
+            /* Unmap previously assigned memory region */
+            printf("OCM unmap ISA %08" PRIx32 "\n", ocm->isarc);
+            memory_region_del_subregion(get_system_memory(), &ocm->isarc_ram);
+        }
+        if (isacntl & 0x80000000) {
+            /* Map new instruction memory region */
+#ifdef DEBUG_OCM
+            printf("OCM map ISA %08" PRIx32 "\n", isarc);
+#endif
+            memory_region_add_subregion(get_system_memory(), isarc,
+                                        &ocm->isarc_ram);
+        }
+    }
+    if (ocm->dsarc != dsarc ||
+        (ocm->dsacntl & 0x80000000) != (dsacntl & 0x80000000)) {
+        if (ocm->dsacntl & 0x80000000) {
+            /* Beware not to unmap the region we just mapped */
+            if (!(isacntl & 0x80000000) || ocm->dsarc != isarc) {
+                /* Unmap previously assigned memory region */
+#ifdef DEBUG_OCM
+                printf("OCM unmap DSA %08" PRIx32 "\n", ocm->dsarc);
+#endif
+                memory_region_del_subregion(get_system_memory(),
+                                            &ocm->dsarc_ram);
+            }
+        }
+        if (dsacntl & 0x80000000) {
+            /* Beware not to remap the region we just mapped */
+            if (!(isacntl & 0x80000000) || dsarc != isarc) {
+                /* Map new data memory region */
+#ifdef DEBUG_OCM
+                printf("OCM map DSA %08" PRIx32 "\n", dsarc);
+#endif
+                memory_region_add_subregion(get_system_memory(), dsarc,
+                                            &ocm->dsarc_ram);
+            }
+        }
+    }
+}
+
+static uint32_t dcr_read_ocm (void *opaque, int dcrn)
+{
+    ppc405_ocm_t *ocm;
+    uint32_t ret;
+
+    ocm = opaque;
+    switch (dcrn) {
+    case OCM0_ISARC:
+        ret = ocm->isarc;
+        break;
+    case OCM0_ISACNTL:
+        ret = ocm->isacntl;
+        break;
+    case OCM0_DSARC:
+        ret = ocm->dsarc;
+        break;
+    case OCM0_DSACNTL:
+        ret = ocm->dsacntl;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_ocm (void *opaque, int dcrn, uint32_t val)
+{
+    ppc405_ocm_t *ocm;
+    uint32_t isarc, dsarc, isacntl, dsacntl;
+
+    ocm = opaque;
+    isarc = ocm->isarc;
+    dsarc = ocm->dsarc;
+    isacntl = ocm->isacntl;
+    dsacntl = ocm->dsacntl;
+    switch (dcrn) {
+    case OCM0_ISARC:
+        isarc = val & 0xFC000000;
+        break;
+    case OCM0_ISACNTL:
+        isacntl = val & 0xC0000000;
+        break;
+    case OCM0_DSARC:
+        isarc = val & 0xFC000000;
+        break;
+    case OCM0_DSACNTL:
+        isacntl = val & 0xC0000000;
+        break;
+    }
+    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
+    ocm->isarc = isarc;
+    ocm->dsarc = dsarc;
+    ocm->isacntl = isacntl;
+    ocm->dsacntl = dsacntl;
+}
+
+static void ocm_reset (void *opaque)
+{
+    ppc405_ocm_t *ocm;
+    uint32_t isarc, dsarc, isacntl, dsacntl;
+
+    ocm = opaque;
+    isarc = 0x00000000;
+    isacntl = 0x00000000;
+    dsarc = 0x00000000;
+    dsacntl = 0x00000000;
+    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
+    ocm->isarc = isarc;
+    ocm->dsarc = dsarc;
+    ocm->isacntl = isacntl;
+    ocm->dsacntl = dsacntl;
+}
+
+static void ppc405_ocm_init(CPUPPCState *env)
+{
+    ppc405_ocm_t *ocm;
+
+    ocm = g_malloc0(sizeof(ppc405_ocm_t));
+    /* XXX: Size is 4096 or 0x04000000 */
+    memory_region_init_ram(&ocm->isarc_ram, "ppc405.ocm", 4096);
+    vmstate_register_ram_global(&ocm->isarc_ram);
+    memory_region_init_alias(&ocm->dsarc_ram, "ppc405.dsarc", &ocm->isarc_ram,
+                             0, 4096);
+    qemu_register_reset(&ocm_reset, ocm);
+    ppc_dcr_register(env, OCM0_ISARC,
+                     ocm, &dcr_read_ocm, &dcr_write_ocm);
+    ppc_dcr_register(env, OCM0_ISACNTL,
+                     ocm, &dcr_read_ocm, &dcr_write_ocm);
+    ppc_dcr_register(env, OCM0_DSARC,
+                     ocm, &dcr_read_ocm, &dcr_write_ocm);
+    ppc_dcr_register(env, OCM0_DSACNTL,
+                     ocm, &dcr_read_ocm, &dcr_write_ocm);
+}
+
+/*****************************************************************************/
+/* I2C controller */
+typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
+struct ppc4xx_i2c_t {
+    qemu_irq irq;
+    MemoryRegion iomem;
+    uint8_t mdata;
+    uint8_t lmadr;
+    uint8_t hmadr;
+    uint8_t cntl;
+    uint8_t mdcntl;
+    uint8_t sts;
+    uint8_t extsts;
+    uint8_t sdata;
+    uint8_t lsadr;
+    uint8_t hsadr;
+    uint8_t clkdiv;
+    uint8_t intrmsk;
+    uint8_t xfrcnt;
+    uint8_t xtcntlss;
+    uint8_t directcntl;
+};
+
+static uint32_t ppc4xx_i2c_readb (void *opaque, hwaddr addr)
+{
+    ppc4xx_i2c_t *i2c;
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    i2c = opaque;
+    switch (addr) {
+    case 0x00:
+        //        i2c_readbyte(&i2c->mdata);
+        ret = i2c->mdata;
+        break;
+    case 0x02:
+        ret = i2c->sdata;
+        break;
+    case 0x04:
+        ret = i2c->lmadr;
+        break;
+    case 0x05:
+        ret = i2c->hmadr;
+        break;
+    case 0x06:
+        ret = i2c->cntl;
+        break;
+    case 0x07:
+        ret = i2c->mdcntl;
+        break;
+    case 0x08:
+        ret = i2c->sts;
+        break;
+    case 0x09:
+        ret = i2c->extsts;
+        break;
+    case 0x0A:
+        ret = i2c->lsadr;
+        break;
+    case 0x0B:
+        ret = i2c->hsadr;
+        break;
+    case 0x0C:
+        ret = i2c->clkdiv;
+        break;
+    case 0x0D:
+        ret = i2c->intrmsk;
+        break;
+    case 0x0E:
+        ret = i2c->xfrcnt;
+        break;
+    case 0x0F:
+        ret = i2c->xtcntlss;
+        break;
+    case 0x10:
+        ret = i2c->directcntl;
+        break;
+    default:
+        ret = 0x00;
+        break;
+    }
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
+#endif
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writeb (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+    ppc4xx_i2c_t *i2c;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    i2c = opaque;
+    switch (addr) {
+    case 0x00:
+        i2c->mdata = value;
+        //        i2c_sendbyte(&i2c->mdata);
+        break;
+    case 0x02:
+        i2c->sdata = value;
+        break;
+    case 0x04:
+        i2c->lmadr = value;
+        break;
+    case 0x05:
+        i2c->hmadr = value;
+        break;
+    case 0x06:
+        i2c->cntl = value;
+        break;
+    case 0x07:
+        i2c->mdcntl = value & 0xDF;
+        break;
+    case 0x08:
+        i2c->sts &= ~(value & 0x0A);
+        break;
+    case 0x09:
+        i2c->extsts &= ~(value & 0x8F);
+        break;
+    case 0x0A:
+        i2c->lsadr = value;
+        break;
+    case 0x0B:
+        i2c->hsadr = value;
+        break;
+    case 0x0C:
+        i2c->clkdiv = value;
+        break;
+    case 0x0D:
+        i2c->intrmsk = value;
+        break;
+    case 0x0E:
+        i2c->xfrcnt = value & 0x77;
+        break;
+    case 0x0F:
+        i2c->xtcntlss = value;
+        break;
+    case 0x10:
+        i2c->directcntl = value & 0x7;
+        break;
+    }
+}
+
+static uint32_t ppc4xx_i2c_readw (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writew (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value);
+}
+
+static uint32_t ppc4xx_i2c_readl (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writel (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
+    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 3, value);
+}
+
+static const MemoryRegionOps i2c_ops = {
+    .old_mmio = {
+        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
+        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ppc4xx_i2c_reset (void *opaque)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = opaque;
+    i2c->mdata = 0x00;
+    i2c->sdata = 0x00;
+    i2c->cntl = 0x00;
+    i2c->mdcntl = 0x00;
+    i2c->sts = 0x00;
+    i2c->extsts = 0x00;
+    i2c->clkdiv = 0x00;
+    i2c->xfrcnt = 0x00;
+    i2c->directcntl = 0x0F;
+}
+
+static void ppc405_i2c_init(hwaddr base, qemu_irq irq)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
+    i2c->irq = irq;
+#ifdef DEBUG_I2C
+    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
+#endif
+    memory_region_init_io(&i2c->iomem, &i2c_ops, i2c, "i2c", 0x011);
+    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
+    qemu_register_reset(ppc4xx_i2c_reset, i2c);
+}
+
+/*****************************************************************************/
+/* General purpose timers */
+typedef struct ppc4xx_gpt_t ppc4xx_gpt_t;
+struct ppc4xx_gpt_t {
+    MemoryRegion iomem;
+    int64_t tb_offset;
+    uint32_t tb_freq;
+    struct QEMUTimer *timer;
+    qemu_irq irqs[5];
+    uint32_t oe;
+    uint32_t ol;
+    uint32_t im;
+    uint32_t is;
+    uint32_t ie;
+    uint32_t comp[5];
+    uint32_t mask[5];
+};
+
+static uint32_t ppc4xx_gpt_readb (void *opaque, hwaddr addr)
+{
+#ifdef DEBUG_GPT
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    /* XXX: generate a bus fault */
+    return -1;
+}
+
+static void ppc4xx_gpt_writeb (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    /* XXX: generate a bus fault */
+}
+
+static uint32_t ppc4xx_gpt_readw (void *opaque, hwaddr addr)
+{
+#ifdef DEBUG_GPT
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    /* XXX: generate a bus fault */
+    return -1;
+}
+
+static void ppc4xx_gpt_writew (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    /* XXX: generate a bus fault */
+}
+
+static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n)
+{
+    /* XXX: TODO */
+    return 0;
+}
+
+static void ppc4xx_gpt_set_output (ppc4xx_gpt_t *gpt, int n, int level)
+{
+    /* XXX: TODO */
+}
+
+static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt)
+{
+    uint32_t mask;
+    int i;
+
+    mask = 0x80000000;
+    for (i = 0; i < 5; i++) {
+        if (gpt->oe & mask) {
+            /* Output is enabled */
+            if (ppc4xx_gpt_compare(gpt, i)) {
+                /* Comparison is OK */
+                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask);
+            } else {
+                /* Comparison is KO */
+                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask ? 0 : 1);
+            }
+        }
+        mask = mask >> 1;
+    }
+}
+
+static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt)
+{
+    uint32_t mask;
+    int i;
+
+    mask = 0x00008000;
+    for (i = 0; i < 5; i++) {
+        if (gpt->is & gpt->im & mask)
+            qemu_irq_raise(gpt->irqs[i]);
+        else
+            qemu_irq_lower(gpt->irqs[i]);
+        mask = mask >> 1;
+    }
+}
+
+static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt)
+{
+    /* XXX: TODO */
+}
+
+static uint32_t ppc4xx_gpt_readl (void *opaque, hwaddr addr)
+{
+    ppc4xx_gpt_t *gpt;
+    uint32_t ret;
+    int idx;
+
+#ifdef DEBUG_GPT
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    gpt = opaque;
+    switch (addr) {
+    case 0x00:
+        /* Time base counter */
+        ret = muldiv64(qemu_get_clock_ns(vm_clock) + gpt->tb_offset,
+                       gpt->tb_freq, get_ticks_per_sec());
+        break;
+    case 0x10:
+        /* Output enable */
+        ret = gpt->oe;
+        break;
+    case 0x14:
+        /* Output level */
+        ret = gpt->ol;
+        break;
+    case 0x18:
+        /* Interrupt mask */
+        ret = gpt->im;
+        break;
+    case 0x1C:
+    case 0x20:
+        /* Interrupt status */
+        ret = gpt->is;
+        break;
+    case 0x24:
+        /* Interrupt enable */
+        ret = gpt->ie;
+        break;
+    case 0x80 ... 0x90:
+        /* Compare timer */
+        idx = (addr - 0x80) >> 2;
+        ret = gpt->comp[idx];
+        break;
+    case 0xC0 ... 0xD0:
+        /* Compare mask */
+        idx = (addr - 0xC0) >> 2;
+        ret = gpt->mask[idx];
+        break;
+    default:
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+static void ppc4xx_gpt_writel (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+    ppc4xx_gpt_t *gpt;
+    int idx;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    gpt = opaque;
+    switch (addr) {
+    case 0x00:
+        /* Time base counter */
+        gpt->tb_offset = muldiv64(value, get_ticks_per_sec(), gpt->tb_freq)
+            - qemu_get_clock_ns(vm_clock);
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    case 0x10:
+        /* Output enable */
+        gpt->oe = value & 0xF8000000;
+        ppc4xx_gpt_set_outputs(gpt);
+        break;
+    case 0x14:
+        /* Output level */
+        gpt->ol = value & 0xF8000000;
+        ppc4xx_gpt_set_outputs(gpt);
+        break;
+    case 0x18:
+        /* Interrupt mask */
+        gpt->im = value & 0x0000F800;
+        break;
+    case 0x1C:
+        /* Interrupt status set */
+        gpt->is |= value & 0x0000F800;
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x20:
+        /* Interrupt status clear */
+        gpt->is &= ~(value & 0x0000F800);
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x24:
+        /* Interrupt enable */
+        gpt->ie = value & 0x0000F800;
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x80 ... 0x90:
+        /* Compare timer */
+        idx = (addr - 0x80) >> 2;
+        gpt->comp[idx] = value & 0xF8000000;
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    case 0xC0 ... 0xD0:
+        /* Compare mask */
+        idx = (addr - 0xC0) >> 2;
+        gpt->mask[idx] = value & 0xF8000000;
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    }
+}
+
+static const MemoryRegionOps gpt_ops = {
+    .old_mmio = {
+        .read = { ppc4xx_gpt_readb, ppc4xx_gpt_readw, ppc4xx_gpt_readl, },
+        .write = { ppc4xx_gpt_writeb, ppc4xx_gpt_writew, ppc4xx_gpt_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ppc4xx_gpt_cb (void *opaque)
+{
+    ppc4xx_gpt_t *gpt;
+
+    gpt = opaque;
+    ppc4xx_gpt_set_irqs(gpt);
+    ppc4xx_gpt_set_outputs(gpt);
+    ppc4xx_gpt_compute_timer(gpt);
+}
+
+static void ppc4xx_gpt_reset (void *opaque)
+{
+    ppc4xx_gpt_t *gpt;
+    int i;
+
+    gpt = opaque;
+    qemu_del_timer(gpt->timer);
+    gpt->oe = 0x00000000;
+    gpt->ol = 0x00000000;
+    gpt->im = 0x00000000;
+    gpt->is = 0x00000000;
+    gpt->ie = 0x00000000;
+    for (i = 0; i < 5; i++) {
+        gpt->comp[i] = 0x00000000;
+        gpt->mask[i] = 0x00000000;
+    }
+}
+
+static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5])
+{
+    ppc4xx_gpt_t *gpt;
+    int i;
+
+    gpt = g_malloc0(sizeof(ppc4xx_gpt_t));
+    for (i = 0; i < 5; i++) {
+        gpt->irqs[i] = irqs[i];
+    }
+    gpt->timer = qemu_new_timer_ns(vm_clock, &ppc4xx_gpt_cb, gpt);
+#ifdef DEBUG_GPT
+    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
+#endif
+    memory_region_init_io(&gpt->iomem, &gpt_ops, gpt, "gpt", 0x0d4);
+    memory_region_add_subregion(get_system_memory(), base, &gpt->iomem);
+    qemu_register_reset(ppc4xx_gpt_reset, gpt);
+}
+
+/*****************************************************************************/
+/* MAL */
+enum {
+    MAL0_CFG      = 0x180,
+    MAL0_ESR      = 0x181,
+    MAL0_IER      = 0x182,
+    MAL0_TXCASR   = 0x184,
+    MAL0_TXCARR   = 0x185,
+    MAL0_TXEOBISR = 0x186,
+    MAL0_TXDEIR   = 0x187,
+    MAL0_RXCASR   = 0x190,
+    MAL0_RXCARR   = 0x191,
+    MAL0_RXEOBISR = 0x192,
+    MAL0_RXDEIR   = 0x193,
+    MAL0_TXCTP0R  = 0x1A0,
+    MAL0_TXCTP1R  = 0x1A1,
+    MAL0_TXCTP2R  = 0x1A2,
+    MAL0_TXCTP3R  = 0x1A3,
+    MAL0_RXCTP0R  = 0x1C0,
+    MAL0_RXCTP1R  = 0x1C1,
+    MAL0_RCBS0    = 0x1E0,
+    MAL0_RCBS1    = 0x1E1,
+};
+
+typedef struct ppc40x_mal_t ppc40x_mal_t;
+struct ppc40x_mal_t {
+    qemu_irq irqs[4];
+    uint32_t cfg;
+    uint32_t esr;
+    uint32_t ier;
+    uint32_t txcasr;
+    uint32_t txcarr;
+    uint32_t txeobisr;
+    uint32_t txdeir;
+    uint32_t rxcasr;
+    uint32_t rxcarr;
+    uint32_t rxeobisr;
+    uint32_t rxdeir;
+    uint32_t txctpr[4];
+    uint32_t rxctpr[2];
+    uint32_t rcbs[2];
+};
+
+static void ppc40x_mal_reset (void *opaque);
+
+static uint32_t dcr_read_mal (void *opaque, int dcrn)
+{
+    ppc40x_mal_t *mal;
+    uint32_t ret;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        ret = mal->cfg;
+        break;
+    case MAL0_ESR:
+        ret = mal->esr;
+        break;
+    case MAL0_IER:
+        ret = mal->ier;
+        break;
+    case MAL0_TXCASR:
+        ret = mal->txcasr;
+        break;
+    case MAL0_TXCARR:
+        ret = mal->txcarr;
+        break;
+    case MAL0_TXEOBISR:
+        ret = mal->txeobisr;
+        break;
+    case MAL0_TXDEIR:
+        ret = mal->txdeir;
+        break;
+    case MAL0_RXCASR:
+        ret = mal->rxcasr;
+        break;
+    case MAL0_RXCARR:
+        ret = mal->rxcarr;
+        break;
+    case MAL0_RXEOBISR:
+        ret = mal->rxeobisr;
+        break;
+    case MAL0_RXDEIR:
+        ret = mal->rxdeir;
+        break;
+    case MAL0_TXCTP0R:
+        ret = mal->txctpr[0];
+        break;
+    case MAL0_TXCTP1R:
+        ret = mal->txctpr[1];
+        break;
+    case MAL0_TXCTP2R:
+        ret = mal->txctpr[2];
+        break;
+    case MAL0_TXCTP3R:
+        ret = mal->txctpr[3];
+        break;
+    case MAL0_RXCTP0R:
+        ret = mal->rxctpr[0];
+        break;
+    case MAL0_RXCTP1R:
+        ret = mal->rxctpr[1];
+        break;
+    case MAL0_RCBS0:
+        ret = mal->rcbs[0];
+        break;
+    case MAL0_RCBS1:
+        ret = mal->rcbs[1];
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_mal (void *opaque, int dcrn, uint32_t val)
+{
+    ppc40x_mal_t *mal;
+    int idx;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        if (val & 0x80000000)
+            ppc40x_mal_reset(mal);
+        mal->cfg = val & 0x00FFC087;
+        break;
+    case MAL0_ESR:
+        /* Read/clear */
+        mal->esr &= ~val;
+        break;
+    case MAL0_IER:
+        mal->ier = val & 0x0000001F;
+        break;
+    case MAL0_TXCASR:
+        mal->txcasr = val & 0xF0000000;
+        break;
+    case MAL0_TXCARR:
+        mal->txcarr = val & 0xF0000000;
+        break;
+    case MAL0_TXEOBISR:
+        /* Read/clear */
+        mal->txeobisr &= ~val;
+        break;
+    case MAL0_TXDEIR:
+        /* Read/clear */
+        mal->txdeir &= ~val;
+        break;
+    case MAL0_RXCASR:
+        mal->rxcasr = val & 0xC0000000;
+        break;
+    case MAL0_RXCARR:
+        mal->rxcarr = val & 0xC0000000;
+        break;
+    case MAL0_RXEOBISR:
+        /* Read/clear */
+        mal->rxeobisr &= ~val;
+        break;
+    case MAL0_RXDEIR:
+        /* Read/clear */
+        mal->rxdeir &= ~val;
+        break;
+    case MAL0_TXCTP0R:
+        idx = 0;
+        goto update_tx_ptr;
+    case MAL0_TXCTP1R:
+        idx = 1;
+        goto update_tx_ptr;
+    case MAL0_TXCTP2R:
+        idx = 2;
+        goto update_tx_ptr;
+    case MAL0_TXCTP3R:
+        idx = 3;
+    update_tx_ptr:
+        mal->txctpr[idx] = val;
+        break;
+    case MAL0_RXCTP0R:
+        idx = 0;
+        goto update_rx_ptr;
+    case MAL0_RXCTP1R:
+        idx = 1;
+    update_rx_ptr:
+        mal->rxctpr[idx] = val;
+        break;
+    case MAL0_RCBS0:
+        idx = 0;
+        goto update_rx_size;
+    case MAL0_RCBS1:
+        idx = 1;
+    update_rx_size:
+        mal->rcbs[idx] = val & 0x000000FF;
+        break;
+    }
+}
+
+static void ppc40x_mal_reset (void *opaque)
+{
+    ppc40x_mal_t *mal;
+
+    mal = opaque;
+    mal->cfg = 0x0007C000;
+    mal->esr = 0x00000000;
+    mal->ier = 0x00000000;
+    mal->rxcasr = 0x00000000;
+    mal->rxdeir = 0x00000000;
+    mal->rxeobisr = 0x00000000;
+    mal->txcasr = 0x00000000;
+    mal->txdeir = 0x00000000;
+    mal->txeobisr = 0x00000000;
+}
+
+static void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
+{
+    ppc40x_mal_t *mal;
+    int i;
+
+    mal = g_malloc0(sizeof(ppc40x_mal_t));
+    for (i = 0; i < 4; i++)
+        mal->irqs[i] = irqs[i];
+    qemu_register_reset(&ppc40x_mal_reset, mal);
+    ppc_dcr_register(env, MAL0_CFG,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_ESR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_IER,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCASR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCARR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXEOBISR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXDEIR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCASR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCARR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXEOBISR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXDEIR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP0R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP1R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP2R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP3R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCTP0R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCTP1R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RCBS0,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RCBS1,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+}
+
+/*****************************************************************************/
+/* SPR */
+void ppc40x_core_reset(PowerPCCPU *cpu)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong dbsr;
+
+    printf("Reset PowerPC core\n");
+    cpu_interrupt(env, CPU_INTERRUPT_RESET);
+    dbsr = env->spr[SPR_40x_DBSR];
+    dbsr &= ~0x00000300;
+    dbsr |= 0x00000100;
+    env->spr[SPR_40x_DBSR] = dbsr;
+}
+
+void ppc40x_chip_reset(PowerPCCPU *cpu)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong dbsr;
+
+    printf("Reset PowerPC chip\n");
+    cpu_interrupt(env, CPU_INTERRUPT_RESET);
+    /* XXX: TODO reset all internal peripherals */
+    dbsr = env->spr[SPR_40x_DBSR];
+    dbsr &= ~0x00000300;
+    dbsr |= 0x00000200;
+    env->spr[SPR_40x_DBSR] = dbsr;
+}
+
+void ppc40x_system_reset(PowerPCCPU *cpu)
+{
+    printf("Reset PowerPC system\n");
+    qemu_system_reset_request();
+}
+
+void store_40x_dbcr0 (CPUPPCState *env, uint32_t val)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    switch ((val >> 28) & 0x3) {
+    case 0x0:
+        /* No action */
+        break;
+    case 0x1:
+        /* Core reset */
+        ppc40x_core_reset(cpu);
+        break;
+    case 0x2:
+        /* Chip reset */
+        ppc40x_chip_reset(cpu);
+        break;
+    case 0x3:
+        /* System reset */
+        ppc40x_system_reset(cpu);
+        break;
+    }
+}
+
+/*****************************************************************************/
+/* PowerPC 405CR */
+enum {
+    PPC405CR_CPC0_PLLMR  = 0x0B0,
+    PPC405CR_CPC0_CR0    = 0x0B1,
+    PPC405CR_CPC0_CR1    = 0x0B2,
+    PPC405CR_CPC0_PSR    = 0x0B4,
+    PPC405CR_CPC0_JTAGID = 0x0B5,
+    PPC405CR_CPC0_ER     = 0x0B9,
+    PPC405CR_CPC0_FR     = 0x0BA,
+    PPC405CR_CPC0_SR     = 0x0BB,
+};
+
+enum {
+    PPC405CR_CPU_CLK   = 0,
+    PPC405CR_TMR_CLK   = 1,
+    PPC405CR_PLB_CLK   = 2,
+    PPC405CR_SDRAM_CLK = 3,
+    PPC405CR_OPB_CLK   = 4,
+    PPC405CR_EXT_CLK   = 5,
+    PPC405CR_UART_CLK  = 6,
+    PPC405CR_CLK_NB    = 7,
+};
+
+typedef struct ppc405cr_cpc_t ppc405cr_cpc_t;
+struct ppc405cr_cpc_t {
+    clk_setup_t clk_setup[PPC405CR_CLK_NB];
+    uint32_t sysclk;
+    uint32_t psr;
+    uint32_t cr0;
+    uint32_t cr1;
+    uint32_t jtagid;
+    uint32_t pllmr;
+    uint32_t er;
+    uint32_t fr;
+};
+
+static void ppc405cr_clk_setup (ppc405cr_cpc_t *cpc)
+{
+    uint64_t VCO_out, PLL_out;
+    uint32_t CPU_clk, TMR_clk, SDRAM_clk, PLB_clk, OPB_clk, EXT_clk, UART_clk;
+    int M, D0, D1, D2;
+
+    D0 = ((cpc->pllmr >> 26) & 0x3) + 1; /* CBDV */
+    if (cpc->pllmr & 0x80000000) {
+        D1 = (((cpc->pllmr >> 20) - 1) & 0xF) + 1; /* FBDV */
+        D2 = 8 - ((cpc->pllmr >> 16) & 0x7); /* FWDVA */
+        M = D0 * D1 * D2;
+        VCO_out = cpc->sysclk * M;
+        if (VCO_out < 400000000 || VCO_out > 800000000) {
+            /* PLL cannot lock */
+            cpc->pllmr &= ~0x80000000;
+            goto bypass_pll;
+        }
+        PLL_out = VCO_out / D2;
+    } else {
+        /* Bypass PLL */
+    bypass_pll:
+        M = D0;
+        PLL_out = cpc->sysclk * M;
+    }
+    CPU_clk = PLL_out;
+    if (cpc->cr1 & 0x00800000)
+        TMR_clk = cpc->sysclk; /* Should have a separate clock */
+    else
+        TMR_clk = CPU_clk;
+    PLB_clk = CPU_clk / D0;
+    SDRAM_clk = PLB_clk;
+    D0 = ((cpc->pllmr >> 10) & 0x3) + 1;
+    OPB_clk = PLB_clk / D0;
+    D0 = ((cpc->pllmr >> 24) & 0x3) + 2;
+    EXT_clk = PLB_clk / D0;
+    D0 = ((cpc->cr0 >> 1) & 0x1F) + 1;
+    UART_clk = CPU_clk / D0;
+    /* Setup CPU clocks */
+    clk_setup(&cpc->clk_setup[PPC405CR_CPU_CLK], CPU_clk);
+    /* Setup time-base clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_TMR_CLK], TMR_clk);
+    /* Setup PLB clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_PLB_CLK], PLB_clk);
+    /* Setup SDRAM clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_SDRAM_CLK], SDRAM_clk);
+    /* Setup OPB clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_OPB_CLK], OPB_clk);
+    /* Setup external clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_EXT_CLK], EXT_clk);
+    /* Setup UART clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_UART_CLK], UART_clk);
+}
+
+static uint32_t dcr_read_crcpc (void *opaque, int dcrn)
+{
+    ppc405cr_cpc_t *cpc;
+    uint32_t ret;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405CR_CPC0_PLLMR:
+        ret = cpc->pllmr;
+        break;
+    case PPC405CR_CPC0_CR0:
+        ret = cpc->cr0;
+        break;
+    case PPC405CR_CPC0_CR1:
+        ret = cpc->cr1;
+        break;
+    case PPC405CR_CPC0_PSR:
+        ret = cpc->psr;
+        break;
+    case PPC405CR_CPC0_JTAGID:
+        ret = cpc->jtagid;
+        break;
+    case PPC405CR_CPC0_ER:
+        ret = cpc->er;
+        break;
+    case PPC405CR_CPC0_FR:
+        ret = cpc->fr;
+        break;
+    case PPC405CR_CPC0_SR:
+        ret = ~(cpc->er | cpc->fr) & 0xFFFF0000;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_crcpc (void *opaque, int dcrn, uint32_t val)
+{
+    ppc405cr_cpc_t *cpc;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405CR_CPC0_PLLMR:
+        cpc->pllmr = val & 0xFFF77C3F;
+        break;
+    case PPC405CR_CPC0_CR0:
+        cpc->cr0 = val & 0x0FFFFFFE;
+        break;
+    case PPC405CR_CPC0_CR1:
+        cpc->cr1 = val & 0x00800000;
+        break;
+    case PPC405CR_CPC0_PSR:
+        /* Read-only */
+        break;
+    case PPC405CR_CPC0_JTAGID:
+        /* Read-only */
+        break;
+    case PPC405CR_CPC0_ER:
+        cpc->er = val & 0xBFFC0000;
+        break;
+    case PPC405CR_CPC0_FR:
+        cpc->fr = val & 0xBFFC0000;
+        break;
+    case PPC405CR_CPC0_SR:
+        /* Read-only */
+        break;
+    }
+}
+
+static void ppc405cr_cpc_reset (void *opaque)
+{
+    ppc405cr_cpc_t *cpc;
+    int D;
+
+    cpc = opaque;
+    /* Compute PLLMR value from PSR settings */
+    cpc->pllmr = 0x80000000;
+    /* PFWD */
+    switch ((cpc->psr >> 30) & 3) {
+    case 0:
+        /* Bypass */
+        cpc->pllmr &= ~0x80000000;
+        break;
+    case 1:
+        /* Divide by 3 */
+        cpc->pllmr |= 5 << 16;
+        break;
+    case 2:
+        /* Divide by 4 */
+        cpc->pllmr |= 4 << 16;
+        break;
+    case 3:
+        /* Divide by 6 */
+        cpc->pllmr |= 2 << 16;
+        break;
+    }
+    /* PFBD */
+    D = (cpc->psr >> 28) & 3;
+    cpc->pllmr |= (D + 1) << 20;
+    /* PT   */
+    D = (cpc->psr >> 25) & 7;
+    switch (D) {
+    case 0x2:
+        cpc->pllmr |= 0x13;
+        break;
+    case 0x4:
+        cpc->pllmr |= 0x15;
+        break;
+    case 0x5:
+        cpc->pllmr |= 0x16;
+        break;
+    default:
+        break;
+    }
+    /* PDC  */
+    D = (cpc->psr >> 23) & 3;
+    cpc->pllmr |= D << 26;
+    /* ODP  */
+    D = (cpc->psr >> 21) & 3;
+    cpc->pllmr |= D << 10;
+    /* EBPD */
+    D = (cpc->psr >> 17) & 3;
+    cpc->pllmr |= D << 24;
+    cpc->cr0 = 0x0000003C;
+    cpc->cr1 = 0x2B0D8800;
+    cpc->er = 0x00000000;
+    cpc->fr = 0x00000000;
+    ppc405cr_clk_setup(cpc);
+}
+
+static void ppc405cr_clk_init (ppc405cr_cpc_t *cpc)
+{
+    int D;
+
+    /* XXX: this should be read from IO pins */
+    cpc->psr = 0x00000000; /* 8 bits ROM */
+    /* PFWD */
+    D = 0x2; /* Divide by 4 */
+    cpc->psr |= D << 30;
+    /* PFBD */
+    D = 0x1; /* Divide by 2 */
+    cpc->psr |= D << 28;
+    /* PDC */
+    D = 0x1; /* Divide by 2 */
+    cpc->psr |= D << 23;
+    /* PT */
+    D = 0x5; /* M = 16 */
+    cpc->psr |= D << 25;
+    /* ODP */
+    D = 0x1; /* Divide by 2 */
+    cpc->psr |= D << 21;
+    /* EBDP */
+    D = 0x2; /* Divide by 4 */
+    cpc->psr |= D << 17;
+}
+
+static void ppc405cr_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[7],
+                               uint32_t sysclk)
+{
+    ppc405cr_cpc_t *cpc;
+
+    cpc = g_malloc0(sizeof(ppc405cr_cpc_t));
+    memcpy(cpc->clk_setup, clk_setup,
+           PPC405CR_CLK_NB * sizeof(clk_setup_t));
+    cpc->sysclk = sysclk;
+    cpc->jtagid = 0x42051049;
+    ppc_dcr_register(env, PPC405CR_CPC0_PSR, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_CR0, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_CR1, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_JTAGID, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_PLLMR, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_ER, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_FR, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_SR, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc405cr_clk_init(cpc);
+    qemu_register_reset(ppc405cr_cpc_reset, cpc);
+}
+
+CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
+                        MemoryRegion ram_memories[4],
+                        hwaddr ram_bases[4],
+                        hwaddr ram_sizes[4],
+                        uint32_t sysclk, qemu_irq **picp,
+                        int do_init)
+{
+    clk_setup_t clk_setup[PPC405CR_CLK_NB];
+    qemu_irq dma_irqs[4];
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    qemu_irq *pic, *irqs;
+
+    memset(clk_setup, 0, sizeof(clk_setup));
+    cpu = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
+                      &clk_setup[PPC405CR_TMR_CLK], sysclk);
+    env = &cpu->env;
+    /* Memory mapped devices registers */
+    /* PLB arbitrer */
+    ppc4xx_plb_init(env);
+    /* PLB to OPB bridge */
+    ppc4xx_pob_init(env);
+    /* OBP arbitrer */
+    ppc4xx_opba_init(0xef600600);
+    /* Universal interrupt controller */
+    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] =
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] =
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+    *picp = pic;
+    /* SDRAM controller */
+    ppc4xx_sdram_init(env, pic[14], 1, ram_memories,
+                      ram_bases, ram_sizes, do_init);
+    /* External bus controller */
+    ppc405_ebc_init(env);
+    /* DMA controller */
+    dma_irqs[0] = pic[26];
+    dma_irqs[1] = pic[25];
+    dma_irqs[2] = pic[24];
+    dma_irqs[3] = pic[23];
+    ppc405_dma_init(env, dma_irqs);
+    /* Serial ports */
+    if (serial_hds[0] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+                       DEVICE_BIG_ENDIAN);
+    }
+    if (serial_hds[1] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+                       DEVICE_BIG_ENDIAN);
+    }
+    /* IIC controller */
+    ppc405_i2c_init(0xef600500, pic[2]);
+    /* GPIO */
+    ppc405_gpio_init(0xef600700);
+    /* CPU control */
+    ppc405cr_cpc_init(env, clk_setup, sysclk);
+
+    return env;
+}
+
+/*****************************************************************************/
+/* PowerPC 405EP */
+/* CPU control */
+enum {
+    PPC405EP_CPC0_PLLMR0 = 0x0F0,
+    PPC405EP_CPC0_BOOT   = 0x0F1,
+    PPC405EP_CPC0_EPCTL  = 0x0F3,
+    PPC405EP_CPC0_PLLMR1 = 0x0F4,
+    PPC405EP_CPC0_UCR    = 0x0F5,
+    PPC405EP_CPC0_SRR    = 0x0F6,
+    PPC405EP_CPC0_JTAGID = 0x0F7,
+    PPC405EP_CPC0_PCI    = 0x0F9,
+#if 0
+    PPC405EP_CPC0_ER     = xxx,
+    PPC405EP_CPC0_FR     = xxx,
+    PPC405EP_CPC0_SR     = xxx,
+#endif
+};
+
+enum {
+    PPC405EP_CPU_CLK   = 0,
+    PPC405EP_PLB_CLK   = 1,
+    PPC405EP_OPB_CLK   = 2,
+    PPC405EP_EBC_CLK   = 3,
+    PPC405EP_MAL_CLK   = 4,
+    PPC405EP_PCI_CLK   = 5,
+    PPC405EP_UART0_CLK = 6,
+    PPC405EP_UART1_CLK = 7,
+    PPC405EP_CLK_NB    = 8,
+};
+
+typedef struct ppc405ep_cpc_t ppc405ep_cpc_t;
+struct ppc405ep_cpc_t {
+    uint32_t sysclk;
+    clk_setup_t clk_setup[PPC405EP_CLK_NB];
+    uint32_t boot;
+    uint32_t epctl;
+    uint32_t pllmr[2];
+    uint32_t ucr;
+    uint32_t srr;
+    uint32_t jtagid;
+    uint32_t pci;
+    /* Clock and power management */
+    uint32_t er;
+    uint32_t fr;
+    uint32_t sr;
+};
+
+static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc)
+{
+    uint32_t CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk;
+    uint32_t UART0_clk, UART1_clk;
+    uint64_t VCO_out, PLL_out;
+    int M, D;
+
+    VCO_out = 0;
+    if ((cpc->pllmr[1] & 0x80000000) && !(cpc->pllmr[1] & 0x40000000)) {
+        M = (((cpc->pllmr[1] >> 20) - 1) & 0xF) + 1; /* FBMUL */
+#ifdef DEBUG_CLOCKS_LL
+        printf("FBMUL %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 20) & 0xF, M);
+#endif
+        D = 8 - ((cpc->pllmr[1] >> 16) & 0x7); /* FWDA */
+#ifdef DEBUG_CLOCKS_LL
+        printf("FWDA %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 16) & 0x7, D);
+#endif
+        VCO_out = cpc->sysclk * M * D;
+        if (VCO_out < 500000000UL || VCO_out > 1000000000UL) {
+            /* Error - unlock the PLL */
+            printf("VCO out of range %" PRIu64 "\n", VCO_out);
+#if 0
+            cpc->pllmr[1] &= ~0x80000000;
+            goto pll_bypass;
+#endif
+        }
+        PLL_out = VCO_out / D;
+        /* Pretend the PLL is locked */
+        cpc->boot |= 0x00000001;
+    } else {
+#if 0
+    pll_bypass:
+#endif
+        PLL_out = cpc->sysclk;
+        if (cpc->pllmr[1] & 0x40000000) {
+            /* Pretend the PLL is not locked */
+            cpc->boot &= ~0x00000001;
+        }
+    }
+    /* Now, compute all other clocks */
+    D = ((cpc->pllmr[0] >> 20) & 0x3) + 1; /* CCDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("CCDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 20) & 0x3, D);
+#endif
+    CPU_clk = PLL_out / D;
+    D = ((cpc->pllmr[0] >> 16) & 0x3) + 1; /* CBDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("CBDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 16) & 0x3, D);
+#endif
+    PLB_clk = CPU_clk / D;
+    D = ((cpc->pllmr[0] >> 12) & 0x3) + 1; /* OPDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("OPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 12) & 0x3, D);
+#endif
+    OPB_clk = PLB_clk / D;
+    D = ((cpc->pllmr[0] >> 8) & 0x3) + 2; /* EPDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("EPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 8) & 0x3, D);
+#endif
+    EBC_clk = PLB_clk / D;
+    D = ((cpc->pllmr[0] >> 4) & 0x3) + 1; /* MPDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("MPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 4) & 0x3, D);
+#endif
+    MAL_clk = PLB_clk / D;
+    D = (cpc->pllmr[0] & 0x3) + 1; /* PPDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("PPDV %01" PRIx32 " %d\n", cpc->pllmr[0] & 0x3, D);
+#endif
+    PCI_clk = PLB_clk / D;
+    D = ((cpc->ucr - 1) & 0x7F) + 1; /* U0DIV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("U0DIV %01" PRIx32 " %d\n", cpc->ucr & 0x7F, D);
+#endif
+    UART0_clk = PLL_out / D;
+    D = (((cpc->ucr >> 8) - 1) & 0x7F) + 1; /* U1DIV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("U1DIV %01" PRIx32 " %d\n", (cpc->ucr >> 8) & 0x7F, D);
+#endif
+    UART1_clk = PLL_out / D;
+#ifdef DEBUG_CLOCKS
+    printf("Setup PPC405EP clocks - sysclk %" PRIu32 " VCO %" PRIu64
+           " PLL out %" PRIu64 " Hz\n", cpc->sysclk, VCO_out, PLL_out);
+    printf("CPU %" PRIu32 " PLB %" PRIu32 " OPB %" PRIu32 " EBC %" PRIu32
+           " MAL %" PRIu32 " PCI %" PRIu32 " UART0 %" PRIu32
+           " UART1 %" PRIu32 "\n",
+           CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk,
+           UART0_clk, UART1_clk);
+#endif
+    /* Setup CPU clocks */
+    clk_setup(&cpc->clk_setup[PPC405EP_CPU_CLK], CPU_clk);
+    /* Setup PLB clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_PLB_CLK], PLB_clk);
+    /* Setup OPB clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_OPB_CLK], OPB_clk);
+    /* Setup external clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_EBC_CLK], EBC_clk);
+    /* Setup MAL clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_MAL_CLK], MAL_clk);
+    /* Setup PCI clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_PCI_CLK], PCI_clk);
+    /* Setup UART0 clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_UART0_CLK], UART0_clk);
+    /* Setup UART1 clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_UART1_CLK], UART1_clk);
+}
+
+static uint32_t dcr_read_epcpc (void *opaque, int dcrn)
+{
+    ppc405ep_cpc_t *cpc;
+    uint32_t ret;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405EP_CPC0_BOOT:
+        ret = cpc->boot;
+        break;
+    case PPC405EP_CPC0_EPCTL:
+        ret = cpc->epctl;
+        break;
+    case PPC405EP_CPC0_PLLMR0:
+        ret = cpc->pllmr[0];
+        break;
+    case PPC405EP_CPC0_PLLMR1:
+        ret = cpc->pllmr[1];
+        break;
+    case PPC405EP_CPC0_UCR:
+        ret = cpc->ucr;
+        break;
+    case PPC405EP_CPC0_SRR:
+        ret = cpc->srr;
+        break;
+    case PPC405EP_CPC0_JTAGID:
+        ret = cpc->jtagid;
+        break;
+    case PPC405EP_CPC0_PCI:
+        ret = cpc->pci;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_epcpc (void *opaque, int dcrn, uint32_t val)
+{
+    ppc405ep_cpc_t *cpc;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405EP_CPC0_BOOT:
+        /* Read-only register */
+        break;
+    case PPC405EP_CPC0_EPCTL:
+        /* Don't care for now */
+        cpc->epctl = val & 0xC00000F3;
+        break;
+    case PPC405EP_CPC0_PLLMR0:
+        cpc->pllmr[0] = val & 0x00633333;
+        ppc405ep_compute_clocks(cpc);
+        break;
+    case PPC405EP_CPC0_PLLMR1:
+        cpc->pllmr[1] = val & 0xC0F73FFF;
+        ppc405ep_compute_clocks(cpc);
+        break;
+    case PPC405EP_CPC0_UCR:
+        /* UART control - don't care for now */
+        cpc->ucr = val & 0x003F7F7F;
+        break;
+    case PPC405EP_CPC0_SRR:
+        cpc->srr = val;
+        break;
+    case PPC405EP_CPC0_JTAGID:
+        /* Read-only */
+        break;
+    case PPC405EP_CPC0_PCI:
+        cpc->pci = val;
+        break;
+    }
+}
+
+static void ppc405ep_cpc_reset (void *opaque)
+{
+    ppc405ep_cpc_t *cpc = opaque;
+
+    cpc->boot = 0x00000010;     /* Boot from PCI - IIC EEPROM disabled */
+    cpc->epctl = 0x00000000;
+    cpc->pllmr[0] = 0x00011010;
+    cpc->pllmr[1] = 0x40000000;
+    cpc->ucr = 0x00000000;
+    cpc->srr = 0x00040000;
+    cpc->pci = 0x00000000;
+    cpc->er = 0x00000000;
+    cpc->fr = 0x00000000;
+    cpc->sr = 0x00000000;
+    ppc405ep_compute_clocks(cpc);
+}
+
+/* XXX: sysclk should be between 25 and 100 MHz */
+static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8],
+                               uint32_t sysclk)
+{
+    ppc405ep_cpc_t *cpc;
+
+    cpc = g_malloc0(sizeof(ppc405ep_cpc_t));
+    memcpy(cpc->clk_setup, clk_setup,
+           PPC405EP_CLK_NB * sizeof(clk_setup_t));
+    cpc->jtagid = 0x20267049;
+    cpc->sysclk = sysclk;
+    qemu_register_reset(&ppc405ep_cpc_reset, cpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_BOOT, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_EPCTL, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_PLLMR0, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_PLLMR1, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_UCR, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_SRR, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_JTAGID, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+#if 0
+    ppc_dcr_register(env, PPC405EP_CPC0_ER, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_FR, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_SR, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+#endif
+}
+
+CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
+                        MemoryRegion ram_memories[2],
+                        hwaddr ram_bases[2],
+                        hwaddr ram_sizes[2],
+                        uint32_t sysclk, qemu_irq **picp,
+                        int do_init)
+{
+    clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
+    qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    qemu_irq *pic, *irqs;
+
+    memset(clk_setup, 0, sizeof(clk_setup));
+    /* init CPUs */
+    cpu = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
+                      &tlb_clk_setup, sysclk);
+    env = &cpu->env;
+    clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
+    clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
+    /* Internal devices init */
+    /* Memory mapped devices registers */
+    /* PLB arbitrer */
+    ppc4xx_plb_init(env);
+    /* PLB to OPB bridge */
+    ppc4xx_pob_init(env);
+    /* OBP arbitrer */
+    ppc4xx_opba_init(0xef600600);
+    /* Initialize timers */
+    ppc_booke_timers_init(cpu, sysclk, 0);
+    /* Universal interrupt controller */
+    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] =
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] =
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+    *picp = pic;
+    /* SDRAM controller */
+       /* XXX 405EP has no ECC interrupt */
+    ppc4xx_sdram_init(env, pic[17], 2, ram_memories,
+                      ram_bases, ram_sizes, do_init);
+    /* External bus controller */
+    ppc405_ebc_init(env);
+    /* DMA controller */
+    dma_irqs[0] = pic[5];
+    dma_irqs[1] = pic[6];
+    dma_irqs[2] = pic[7];
+    dma_irqs[3] = pic[8];
+    ppc405_dma_init(env, dma_irqs);
+    /* IIC controller */
+    ppc405_i2c_init(0xef600500, pic[2]);
+    /* GPIO */
+    ppc405_gpio_init(0xef600700);
+    /* Serial ports */
+    if (serial_hds[0] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+                       DEVICE_BIG_ENDIAN);
+    }
+    if (serial_hds[1] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+                       DEVICE_BIG_ENDIAN);
+    }
+    /* OCM */
+    ppc405_ocm_init(env);
+    /* GPT */
+    gpt_irqs[0] = pic[19];
+    gpt_irqs[1] = pic[20];
+    gpt_irqs[2] = pic[21];
+    gpt_irqs[3] = pic[22];
+    gpt_irqs[4] = pic[23];
+    ppc4xx_gpt_init(0xef600000, gpt_irqs);
+    /* PCI */
+    /* Uses pic[3], pic[16], pic[18] */
+    /* MAL */
+    mal_irqs[0] = pic[11];
+    mal_irqs[1] = pic[12];
+    mal_irqs[2] = pic[13];
+    mal_irqs[3] = pic[14];
+    ppc405_mal_init(env, mal_irqs);
+    /* Ethernet */
+    /* Uses pic[9], pic[15], pic[17] */
+    /* CPU control */
+    ppc405ep_cpc_init(env, clk_setup, sysclk);
+
+    return env;
+}
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
new file mode 100644 (file)
index 0000000..66911b5
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * QEMU PowerPC 440 Bamboo board emulation
+ *
+ * Copyright 2007 IBM Corporation.
+ * Authors:
+ *     Jerone Young <jyoung5@us.ibm.com>
+ *     Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ *     Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include "config.h"
+#include "qemu-common.h"
+#include "net/net.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/boards.h"
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+#include "sysemu/device_tree.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+#include "hw/serial.h"
+#include "hw/ppc.h"
+#include "hw/ppc405.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+
+#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
+
+/* from u-boot */
+#define KERNEL_ADDR  0x1000000
+#define FDT_ADDR     0x1800000
+#define RAMDISK_ADDR 0x1900000
+
+#define PPC440EP_PCI_CONFIG     0xeec00000
+#define PPC440EP_PCI_INTACK     0xeed00000
+#define PPC440EP_PCI_SPECIAL    0xeed00000
+#define PPC440EP_PCI_REGS       0xef400000
+#define PPC440EP_PCI_IO         0xe8000000
+#define PPC440EP_PCI_IOLEN      0x00010000
+
+#define PPC440EP_SDRAM_NR_BANKS 4
+
+static const unsigned int ppc440ep_sdram_bank_sizes[] = {
+    256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0
+};
+
+static hwaddr entry;
+
+static int bamboo_load_device_tree(hwaddr addr,
+                                     uint32_t ramsize,
+                                     hwaddr initrd_base,
+                                     hwaddr initrd_size,
+                                     const char *kernel_cmdline)
+{
+    int ret = -1;
+#ifdef CONFIG_FDT
+    uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
+    char *filename;
+    int fdt_size;
+    void *fdt;
+    uint32_t tb_freq = 400000000;
+    uint32_t clock_freq = 400000000;
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
+    if (!filename) {
+        goto out;
+    }
+    fdt = load_device_tree(filename, &fdt_size);
+    g_free(filename);
+    if (fdt == NULL) {
+        goto out;
+    }
+
+    /* Manipulate device tree in memory. */
+
+    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
+                               sizeof(mem_reg_property));
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /memory/reg\n");
+
+    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                                    initrd_base);
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+
+    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                                    (initrd_base + initrd_size));
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
+
+    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
+                                      kernel_cmdline);
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /chosen/bootargs\n");
+
+    /* Copy data from the host device tree into the guest. Since the guest can
+     * directly access the timebase without host involvement, we must expose
+     * the correct frequencies. */
+    if (kvm_enabled()) {
+        tb_freq = kvmppc_get_tbfreq();
+        clock_freq = kvmppc_get_clockfreq();
+    }
+
+    qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
+                              clock_freq);
+    qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
+                              tb_freq);
+
+    ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
+    g_free(fdt);
+
+out:
+#endif
+
+    return ret;
+}
+
+/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
+                                     target_ulong va,
+                                     hwaddr pa)
+{
+    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
+
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 1 << 31; /* up to 0x80000000  */
+    tlb->EPN = va & TARGET_PAGE_MASK;
+    tlb->RPN = pa & TARGET_PAGE_MASK;
+    tlb->PID = 0;
+
+    tlb = &env->tlb.tlbe[1];
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 1 << 31; /* up to 0xffffffff  */
+    tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
+    tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
+    tlb->PID = 0;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+    env->gpr[1] = (16<<20) - 8;
+    env->gpr[3] = FDT_ADDR;
+    env->nip = entry;
+
+    /* Create a mapping for the kernel.  */
+    mmubooke_create_initial_mapping(env, 0, 0);
+}
+
+static void bamboo_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram_memories
+        = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
+    hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
+    hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS];
+    qemu_irq *pic;
+    qemu_irq *irqs;
+    PCIBus *pcibus;
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    uint64_t elf_entry;
+    uint64_t elf_lowaddr;
+    hwaddr loadaddr = 0;
+    target_long initrd_size = 0;
+    DeviceState *dev;
+    int success;
+    int i;
+
+    /* Setup CPU. */
+    if (cpu_model == NULL) {
+        cpu_model = "440EP";
+    }
+    cpu = cpu_ppc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to initialize CPU!\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    qemu_register_reset(main_cpu_reset, cpu);
+    ppc_booke_timers_init(cpu, 400000000, 0);
+    ppc_dcr_init(env, NULL, NULL);
+
+    /* interrupt controller */
+    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+
+    /* SDRAM controller */
+    memset(ram_bases, 0, sizeof(ram_bases));
+    memset(ram_sizes, 0, sizeof(ram_sizes));
+    ram_size = ppc4xx_sdram_adjust(ram_size, PPC440EP_SDRAM_NR_BANKS,
+                                   ram_memories,
+                                   ram_bases, ram_sizes,
+                                   ppc440ep_sdram_bank_sizes);
+    /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
+    ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_memories,
+                      ram_bases, ram_sizes, 1);
+
+    /* PCI */
+    dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
+                                PPC440EP_PCI_CONFIG,
+                                pic[pci_irq_nrs[0]], pic[pci_irq_nrs[1]],
+                                pic[pci_irq_nrs[2]], pic[pci_irq_nrs[3]],
+                                NULL);
+    pcibus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
+    if (!pcibus) {
+        fprintf(stderr, "couldn't create PCI controller!\n");
+        exit(1);
+    }
+
+    isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
+
+    if (serial_hds[0] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+                       DEVICE_BIG_ENDIAN);
+    }
+    if (serial_hds[1] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+                       DEVICE_BIG_ENDIAN);
+    }
+
+    if (pcibus) {
+        /* Register network interfaces. */
+        for (i = 0; i < nb_nics; i++) {
+            /* There are no PCI NICs on the Bamboo board, but there are
+             * PCI slots, so we can pick whatever default model we want. */
+            pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
+        }
+    }
+
+    /* Load kernel. */
+    if (kernel_filename) {
+        success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
+        if (success < 0) {
+            success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                               &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
+            entry = elf_entry;
+            loadaddr = elf_lowaddr;
+        }
+        /* XXX try again as binary */
+        if (success < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    /* Load initrd. */
+    if (initrd_filename) {
+        initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR,
+                                          ram_size - RAMDISK_ADDR);
+
+        if (initrd_size < 0) {
+            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
+                    initrd_filename, RAMDISK_ADDR);
+            exit(1);
+        }
+    }
+
+    /* If we're loading a kernel directly, we must load the device tree too. */
+    if (kernel_filename) {
+        if (bamboo_load_device_tree(FDT_ADDR, ram_size, RAMDISK_ADDR,
+                                    initrd_size, kernel_cmdline) < 0) {
+            fprintf(stderr, "couldn't load device tree\n");
+            exit(1);
+        }
+    }
+
+    if (kvm_enabled())
+        kvmppc_init();
+}
+
+static QEMUMachine bamboo_machine = {
+    .name = "bamboo",
+    .desc = "bamboo",
+    .init = bamboo_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void bamboo_machine_init(void)
+{
+    qemu_register_machine(&bamboo_machine);
+}
+
+machine_init(bamboo_machine_init);
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
new file mode 100644 (file)
index 0000000..49ec728
--- /dev/null
@@ -0,0 +1,721 @@
+/*
+ * QEMU PowerPC 4xx embedded processors shared devices emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "hw/ppc.h"
+#include "hw/ppc4xx.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+
+//#define DEBUG_MMIO
+//#define DEBUG_UNASSIGNED
+#define DEBUG_UIC
+
+
+#ifdef DEBUG_UIC
+#  define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
+#else
+#  define LOG_UIC(...) do { } while (0)
+#endif
+
+static void ppc4xx_reset(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+/*****************************************************************************/
+/* Generic PowerPC 4xx processor instantiation */
+PowerPCCPU *ppc4xx_init(const char *cpu_model,
+                        clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
+                        uint32_t sysclk)
+{
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+
+    /* init CPUs */
+    cpu = cpu_ppc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find PowerPC %s CPU definition\n",
+                cpu_model);
+        exit(1);
+    }
+    env = &cpu->env;
+
+    cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
+    cpu_clk->opaque = env;
+    /* Set time-base frequency to sysclk */
+    tb_clk->cb = ppc_40x_timers_init(env, sysclk, PPC_INTERRUPT_PIT);
+    tb_clk->opaque = env;
+    ppc_dcr_init(env, NULL, NULL);
+    /* Register qemu callbacks */
+    qemu_register_reset(ppc4xx_reset, cpu);
+
+    return cpu;
+}
+
+/*****************************************************************************/
+/* "Universal" Interrupt controller */
+enum {
+    DCR_UICSR  = 0x000,
+    DCR_UICSRS = 0x001,
+    DCR_UICER  = 0x002,
+    DCR_UICCR  = 0x003,
+    DCR_UICPR  = 0x004,
+    DCR_UICTR  = 0x005,
+    DCR_UICMSR = 0x006,
+    DCR_UICVR  = 0x007,
+    DCR_UICVCR = 0x008,
+    DCR_UICMAX = 0x009,
+};
+
+#define UIC_MAX_IRQ 32
+typedef struct ppcuic_t ppcuic_t;
+struct ppcuic_t {
+    uint32_t dcr_base;
+    int use_vectors;
+    uint32_t level;  /* Remembers the state of level-triggered interrupts. */
+    uint32_t uicsr;  /* Status register */
+    uint32_t uicer;  /* Enable register */
+    uint32_t uiccr;  /* Critical register */
+    uint32_t uicpr;  /* Polarity register */
+    uint32_t uictr;  /* Triggering register */
+    uint32_t uicvcr; /* Vector configuration register */
+    uint32_t uicvr;
+    qemu_irq *irqs;
+};
+
+static void ppcuic_trigger_irq (ppcuic_t *uic)
+{
+    uint32_t ir, cr;
+    int start, end, inc, i;
+
+    /* Trigger interrupt if any is pending */
+    ir = uic->uicsr & uic->uicer & (~uic->uiccr);
+    cr = uic->uicsr & uic->uicer & uic->uiccr;
+    LOG_UIC("%s: uicsr %08" PRIx32 " uicer %08" PRIx32
+                " uiccr %08" PRIx32 "\n"
+                "   %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
+                __func__, uic->uicsr, uic->uicer, uic->uiccr,
+                uic->uicsr & uic->uicer, ir, cr);
+    if (ir != 0x0000000) {
+        LOG_UIC("Raise UIC interrupt\n");
+        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
+    } else {
+        LOG_UIC("Lower UIC interrupt\n");
+        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
+    }
+    /* Trigger critical interrupt if any is pending and update vector */
+    if (cr != 0x0000000) {
+        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
+        if (uic->use_vectors) {
+            /* Compute critical IRQ vector */
+            if (uic->uicvcr & 1) {
+                start = 31;
+                end = 0;
+                inc = -1;
+            } else {
+                start = 0;
+                end = 31;
+                inc = 1;
+            }
+            uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
+            for (i = start; i <= end; i += inc) {
+                if (cr & (1 << i)) {
+                    uic->uicvr += (i - start) * 512 * inc;
+                    break;
+                }
+            }
+        }
+        LOG_UIC("Raise UIC critical interrupt - "
+                    "vector %08" PRIx32 "\n", uic->uicvr);
+    } else {
+        LOG_UIC("Lower UIC critical interrupt\n");
+        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
+        uic->uicvr = 0x00000000;
+    }
+}
+
+static void ppcuic_set_irq (void *opaque, int irq_num, int level)
+{
+    ppcuic_t *uic;
+    uint32_t mask, sr;
+
+    uic = opaque;
+    mask = 1 << (31-irq_num);
+    LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32
+                " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
+                __func__, irq_num, level,
+                uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
+    if (irq_num < 0 || irq_num > 31)
+        return;
+    sr = uic->uicsr;
+
+    /* Update status register */
+    if (uic->uictr & mask) {
+        /* Edge sensitive interrupt */
+        if (level == 1)
+            uic->uicsr |= mask;
+    } else {
+        /* Level sensitive interrupt */
+        if (level == 1) {
+            uic->uicsr |= mask;
+            uic->level |= mask;
+        } else {
+            uic->uicsr &= ~mask;
+            uic->level &= ~mask;
+        }
+    }
+    LOG_UIC("%s: irq %d level %d sr %" PRIx32 " => "
+                "%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
+    if (sr != uic->uicsr)
+        ppcuic_trigger_irq(uic);
+}
+
+static uint32_t dcr_read_uic (void *opaque, int dcrn)
+{
+    ppcuic_t *uic;
+    uint32_t ret;
+
+    uic = opaque;
+    dcrn -= uic->dcr_base;
+    switch (dcrn) {
+    case DCR_UICSR:
+    case DCR_UICSRS:
+        ret = uic->uicsr;
+        break;
+    case DCR_UICER:
+        ret = uic->uicer;
+        break;
+    case DCR_UICCR:
+        ret = uic->uiccr;
+        break;
+    case DCR_UICPR:
+        ret = uic->uicpr;
+        break;
+    case DCR_UICTR:
+        ret = uic->uictr;
+        break;
+    case DCR_UICMSR:
+        ret = uic->uicsr & uic->uicer;
+        break;
+    case DCR_UICVR:
+        if (!uic->use_vectors)
+            goto no_read;
+        ret = uic->uicvr;
+        break;
+    case DCR_UICVCR:
+        if (!uic->use_vectors)
+            goto no_read;
+        ret = uic->uicvcr;
+        break;
+    default:
+    no_read:
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_uic (void *opaque, int dcrn, uint32_t val)
+{
+    ppcuic_t *uic;
+
+    uic = opaque;
+    dcrn -= uic->dcr_base;
+    LOG_UIC("%s: dcr %d val 0x%x\n", __func__, dcrn, val);
+    switch (dcrn) {
+    case DCR_UICSR:
+        uic->uicsr &= ~val;
+        uic->uicsr |= uic->level;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICSRS:
+        uic->uicsr |= val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICER:
+        uic->uicer = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICCR:
+        uic->uiccr = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICPR:
+        uic->uicpr = val;
+        break;
+    case DCR_UICTR:
+        uic->uictr = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICMSR:
+        break;
+    case DCR_UICVR:
+        break;
+    case DCR_UICVCR:
+        uic->uicvcr = val & 0xFFFFFFFD;
+        ppcuic_trigger_irq(uic);
+        break;
+    }
+}
+
+static void ppcuic_reset (void *opaque)
+{
+    ppcuic_t *uic;
+
+    uic = opaque;
+    uic->uiccr = 0x00000000;
+    uic->uicer = 0x00000000;
+    uic->uicpr = 0x00000000;
+    uic->uicsr = 0x00000000;
+    uic->uictr = 0x00000000;
+    if (uic->use_vectors) {
+        uic->uicvcr = 0x00000000;
+        uic->uicvr = 0x0000000;
+    }
+}
+
+qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs,
+                       uint32_t dcr_base, int has_ssr, int has_vr)
+{
+    ppcuic_t *uic;
+    int i;
+
+    uic = g_malloc0(sizeof(ppcuic_t));
+    uic->dcr_base = dcr_base;
+    uic->irqs = irqs;
+    if (has_vr)
+        uic->use_vectors = 1;
+    for (i = 0; i < DCR_UICMAX; i++) {
+        ppc_dcr_register(env, dcr_base + i, uic,
+                         &dcr_read_uic, &dcr_write_uic);
+    }
+    qemu_register_reset(ppcuic_reset, uic);
+
+    return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
+}
+
+/*****************************************************************************/
+/* SDRAM controller */
+typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
+struct ppc4xx_sdram_t {
+    uint32_t addr;
+    int nbanks;
+    MemoryRegion containers[4]; /* used for clipping */
+    MemoryRegion *ram_memories;
+    hwaddr ram_bases[4];
+    hwaddr ram_sizes[4];
+    uint32_t besr0;
+    uint32_t besr1;
+    uint32_t bear;
+    uint32_t cfg;
+    uint32_t status;
+    uint32_t rtr;
+    uint32_t pmit;
+    uint32_t bcr[4];
+    uint32_t tr;
+    uint32_t ecccfg;
+    uint32_t eccesr;
+    qemu_irq irq;
+};
+
+enum {
+    SDRAM0_CFGADDR = 0x010,
+    SDRAM0_CFGDATA = 0x011,
+};
+
+/* XXX: TOFIX: some patches have made this code become inconsistent:
+ *      there are type inconsistencies, mixing hwaddr, target_ulong
+ *      and uint32_t
+ */
+static uint32_t sdram_bcr (hwaddr ram_base,
+                           hwaddr ram_size)
+{
+    uint32_t bcr;
+
+    switch (ram_size) {
+    case (4 * 1024 * 1024):
+        bcr = 0x00000000;
+        break;
+    case (8 * 1024 * 1024):
+        bcr = 0x00020000;
+        break;
+    case (16 * 1024 * 1024):
+        bcr = 0x00040000;
+        break;
+    case (32 * 1024 * 1024):
+        bcr = 0x00060000;
+        break;
+    case (64 * 1024 * 1024):
+        bcr = 0x00080000;
+        break;
+    case (128 * 1024 * 1024):
+        bcr = 0x000A0000;
+        break;
+    case (256 * 1024 * 1024):
+        bcr = 0x000C0000;
+        break;
+    default:
+        printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__,
+               ram_size);
+        return 0x00000000;
+    }
+    bcr |= ram_base & 0xFF800000;
+    bcr |= 1;
+
+    return bcr;
+}
+
+static inline hwaddr sdram_base(uint32_t bcr)
+{
+    return bcr & 0xFF800000;
+}
+
+static target_ulong sdram_size (uint32_t bcr)
+{
+    target_ulong size;
+    int sh;
+
+    sh = (bcr >> 17) & 0x7;
+    if (sh == 7)
+        size = -1;
+    else
+        size = (4 * 1024 * 1024) << sh;
+
+    return size;
+}
+
+static void sdram_set_bcr(ppc4xx_sdram_t *sdram,
+                          uint32_t *bcrp, uint32_t bcr, int enabled)
+{
+    unsigned n = bcrp - sdram->bcr;
+
+    if (*bcrp & 0x00000001) {
+        /* Unmap RAM */
+#ifdef DEBUG_SDRAM
+        printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
+#endif
+        memory_region_del_subregion(get_system_memory(),
+                                    &sdram->containers[n]);
+        memory_region_del_subregion(&sdram->containers[n],
+                                    &sdram->ram_memories[n]);
+        memory_region_destroy(&sdram->containers[n]);
+    }
+    *bcrp = bcr & 0xFFDEE001;
+    if (enabled && (bcr & 0x00000001)) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(bcr), sdram_size(bcr));
+#endif
+        memory_region_init(&sdram->containers[n], "sdram-containers",
+                           sdram_size(bcr));
+        memory_region_add_subregion(&sdram->containers[n], 0,
+                                    &sdram->ram_memories[n]);
+        memory_region_add_subregion(get_system_memory(),
+                                    sdram_base(bcr),
+                                    &sdram->containers[n]);
+    }
+}
+
+static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+        if (sdram->ram_sizes[i] != 0) {
+            sdram_set_bcr(sdram,
+                          &sdram->bcr[i],
+                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
+                          1);
+        } else {
+            sdram_set_bcr(sdram, &sdram->bcr[i], 0x00000000, 0);
+        }
+    }
+}
+
+static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
+#endif
+        memory_region_del_subregion(get_system_memory(),
+                                    &sdram->ram_memories[i]);
+    }
+}
+
+static uint32_t dcr_read_sdram (void *opaque, int dcrn)
+{
+    ppc4xx_sdram_t *sdram;
+    uint32_t ret;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        ret = sdram->addr;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            ret = sdram->besr0;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            ret = sdram->besr1;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            ret = sdram->bear;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            ret = sdram->cfg;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            ret = sdram->status;
+            break;
+        case 0x30: /* SDRAM_RTR */
+            ret = sdram->rtr;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            ret = sdram->pmit;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            ret = sdram->bcr[0];
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            ret = sdram->bcr[1];
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            ret = sdram->bcr[2];
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            ret = sdram->bcr[3];
+            break;
+        case 0x80: /* SDRAM_TR */
+            ret = -1; /* ? */
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            ret = sdram->ecccfg;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            ret = sdram->eccesr;
+            break;
+        default: /* Error */
+            ret = -1;
+            break;
+        }
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        sdram->addr = val;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            sdram->besr0 &= ~val;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            sdram->besr1 &= ~val;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            sdram->bear = val;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            val &= 0xFFE00000;
+            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: enable SDRAM controller\n", __func__);
+#endif
+                /* validate all RAM mappings */
+                sdram_map_bcr(sdram);
+                sdram->status &= ~0x80000000;
+            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: disable SDRAM controller\n", __func__);
+#endif
+                /* invalidate all RAM mappings */
+                sdram_unmap_bcr(sdram);
+                sdram->status |= 0x80000000;
+            }
+            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
+                sdram->status |= 0x40000000;
+            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
+                sdram->status &= ~0x40000000;
+            sdram->cfg = val;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            /* Read-only register */
+            break;
+        case 0x30: /* SDRAM_RTR */
+            sdram->rtr = val & 0x3FF80000;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            sdram_set_bcr(sdram, &sdram->bcr[0], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            sdram_set_bcr(sdram, &sdram->bcr[1], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            sdram_set_bcr(sdram, &sdram->bcr[2], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            sdram_set_bcr(sdram, &sdram->bcr[3], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x80: /* SDRAM_TR */
+            sdram->tr = val & 0x018FC01F;
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            sdram->ecccfg = val & 0x00F00000;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            val &= 0xFFF0F000;
+            if (sdram->eccesr == 0 && val != 0)
+                qemu_irq_raise(sdram->irq);
+            else if (sdram->eccesr != 0 && val == 0)
+                qemu_irq_lower(sdram->irq);
+            sdram->eccesr = val;
+            break;
+        default: /* Error */
+            break;
+        }
+        break;
+    }
+}
+
+static void sdram_reset (void *opaque)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    sdram->addr = 0x00000000;
+    sdram->bear = 0x00000000;
+    sdram->besr0 = 0x00000000; /* No error */
+    sdram->besr1 = 0x00000000; /* No error */
+    sdram->cfg = 0x00000000;
+    sdram->ecccfg = 0x00000000; /* No ECC */
+    sdram->eccesr = 0x00000000; /* No error */
+    sdram->pmit = 0x07C00000;
+    sdram->rtr = 0x05F00000;
+    sdram->tr = 0x00854009;
+    /* We pre-initialize RAM banks */
+    sdram->status = 0x00000000;
+    sdram->cfg = 0x00800000;
+}
+
+void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
+                        MemoryRegion *ram_memories,
+                        hwaddr *ram_bases,
+                        hwaddr *ram_sizes,
+                        int do_init)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = g_malloc0(sizeof(ppc4xx_sdram_t));
+    sdram->irq = irq;
+    sdram->nbanks = nbanks;
+    sdram->ram_memories = ram_memories;
+    memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr));
+    memcpy(sdram->ram_bases, ram_bases,
+           nbanks * sizeof(hwaddr));
+    memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr));
+    memcpy(sdram->ram_sizes, ram_sizes,
+           nbanks * sizeof(hwaddr));
+    qemu_register_reset(&sdram_reset, sdram);
+    ppc_dcr_register(env, SDRAM0_CFGADDR,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM0_CFGDATA,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    if (do_init)
+        sdram_map_bcr(sdram);
+}
+
+/* Fill in consecutive SDRAM banks with 'ram_size' bytes of memory.
+ *
+ * sdram_bank_sizes[] must be 0-terminated.
+ *
+ * The 4xx SDRAM controller supports a small number of banks, and each bank
+ * must be one of a small set of sizes. The number of banks and the supported
+ * sizes varies by SoC. */
+ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
+                               MemoryRegion ram_memories[],
+                               hwaddr ram_bases[],
+                               hwaddr ram_sizes[],
+                               const unsigned int sdram_bank_sizes[])
+{
+    ram_addr_t size_left = ram_size;
+    ram_addr_t base = 0;
+    int i;
+    int j;
+
+    for (i = 0; i < nr_banks; i++) {
+        for (j = 0; sdram_bank_sizes[j] != 0; j++) {
+            unsigned int bank_size = sdram_bank_sizes[j];
+
+            if (bank_size <= size_left) {
+                char name[32];
+                snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
+                memory_region_init_ram(&ram_memories[i], name, bank_size);
+                vmstate_register_ram_global(&ram_memories[i]);
+                ram_bases[i] = base;
+                ram_sizes[i] = bank_size;
+                base += bank_size;
+                size_left -= bank_size;
+                break;
+            }
+        }
+
+        if (!size_left) {
+            /* No need to use the remaining banks. */
+            break;
+        }
+    }
+
+    ram_size -= size_left;
+    if (size_left)
+        printf("Truncating memory to %d MiB to fit SDRAM controller limits.\n",
+               (int)(ram_size >> 20));
+
+    return ram_size;
+}
diff --git a/hw/ppc/ppc_booke.c b/hw/ppc/ppc_booke.c
new file mode 100644 (file)
index 0000000..30375c0
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * QEMU PowerPC Booke hardware System Emulator
+ *
+ * Copyright (c) 2011 AdaCore
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "hw/ppc.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "hw/nvram.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+
+
+/* Timer Control Register */
+
+#define TCR_WP_SHIFT  30        /* Watchdog Timer Period */
+#define TCR_WP_MASK   (0x3 << TCR_WP_SHIFT)
+#define TCR_WRC_SHIFT 28        /* Watchdog Timer Reset Control */
+#define TCR_WRC_MASK  (0x3 << TCR_WRC_SHIFT)
+#define TCR_WIE       (1 << 27) /* Watchdog Timer Interrupt Enable */
+#define TCR_DIE       (1 << 26) /* Decrementer Interrupt Enable */
+#define TCR_FP_SHIFT  24        /* Fixed-Interval Timer Period */
+#define TCR_FP_MASK   (0x3 << TCR_FP_SHIFT)
+#define TCR_FIE       (1 << 23) /* Fixed-Interval Timer Interrupt Enable */
+#define TCR_ARE       (1 << 22) /* Auto-Reload Enable */
+
+/* Timer Control Register (e500 specific fields) */
+
+#define TCR_E500_FPEXT_SHIFT 13 /* Fixed-Interval Timer Period Extension */
+#define TCR_E500_FPEXT_MASK  (0xf << TCR_E500_FPEXT_SHIFT)
+#define TCR_E500_WPEXT_SHIFT 17 /* Watchdog Timer Period Extension */
+#define TCR_E500_WPEXT_MASK  (0xf << TCR_E500_WPEXT_SHIFT)
+
+/* Timer Status Register  */
+
+#define TSR_FIS       (1 << 26) /* Fixed-Interval Timer Interrupt Status */
+#define TSR_DIS       (1 << 27) /* Decrementer Interrupt Status */
+#define TSR_WRS_SHIFT 28        /* Watchdog Timer Reset Status */
+#define TSR_WRS_MASK  (0x3 << TSR_WRS_SHIFT)
+#define TSR_WIS       (1 << 30) /* Watchdog Timer Interrupt Status */
+#define TSR_ENW       (1 << 31) /* Enable Next Watchdog Timer */
+
+typedef struct booke_timer_t booke_timer_t;
+struct booke_timer_t {
+
+    uint64_t fit_next;
+    struct QEMUTimer *fit_timer;
+
+    uint64_t wdt_next;
+    struct QEMUTimer *wdt_timer;
+
+    uint32_t flags;
+};
+
+static void booke_update_irq(PowerPCCPU *cpu)
+{
+    CPUPPCState *env = &cpu->env;
+
+    ppc_set_irq(cpu, PPC_INTERRUPT_DECR,
+                (env->spr[SPR_BOOKE_TSR] & TSR_DIS
+                 && env->spr[SPR_BOOKE_TCR] & TCR_DIE));
+
+    ppc_set_irq(cpu, PPC_INTERRUPT_WDT,
+                (env->spr[SPR_BOOKE_TSR] & TSR_WIS
+                 && env->spr[SPR_BOOKE_TCR] & TCR_WIE));
+
+    ppc_set_irq(cpu, PPC_INTERRUPT_FIT,
+                (env->spr[SPR_BOOKE_TSR] & TSR_FIS
+                 && env->spr[SPR_BOOKE_TCR] & TCR_FIE));
+}
+
+/* Return the location of the bit of time base at which the FIT will raise an
+   interrupt */
+static uint8_t booke_get_fit_target(CPUPPCState *env, ppc_tb_t *tb_env)
+{
+    uint8_t fp = (env->spr[SPR_BOOKE_TCR] & TCR_FP_MASK) >> TCR_FP_SHIFT;
+
+    if (tb_env->flags & PPC_TIMER_E500) {
+        /* e500 Fixed-interval timer period extension */
+        uint32_t fpext = (env->spr[SPR_BOOKE_TCR] & TCR_E500_FPEXT_MASK)
+            >> TCR_E500_FPEXT_SHIFT;
+        fp = 63 - (fp | fpext << 2);
+    } else {
+        fp = env->fit_period[fp];
+    }
+
+    return fp;
+}
+
+/* Return the location of the bit of time base at which the WDT will raise an
+   interrupt */
+static uint8_t booke_get_wdt_target(CPUPPCState *env, ppc_tb_t *tb_env)
+{
+    uint8_t wp = (env->spr[SPR_BOOKE_TCR] & TCR_WP_MASK) >> TCR_WP_SHIFT;
+
+    if (tb_env->flags & PPC_TIMER_E500) {
+        /* e500 Watchdog timer period extension */
+        uint32_t wpext = (env->spr[SPR_BOOKE_TCR] & TCR_E500_WPEXT_MASK)
+            >> TCR_E500_WPEXT_SHIFT;
+        wp = 63 - (wp | wpext << 2);
+    } else {
+        wp = env->wdt_period[wp];
+    }
+
+    return wp;
+}
+
+static void booke_update_fixed_timer(CPUPPCState         *env,
+                                     uint8_t           target_bit,
+                                     uint64_t          *next,
+                                     struct QEMUTimer *timer)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t lapse;
+    uint64_t tb;
+    uint64_t period = 1 << (target_bit + 1);
+    uint64_t now;
+
+    now = qemu_get_clock_ns(vm_clock);
+    tb  = cpu_ppc_get_tb(tb_env, now, tb_env->tb_offset);
+
+    lapse = period - ((tb - (1 << target_bit)) & (period - 1));
+
+    *next = now + muldiv64(lapse, get_ticks_per_sec(), tb_env->tb_freq);
+
+    /* XXX: If expire time is now. We can't run the callback because we don't
+     * have access to it. So we just set the timer one nanosecond later.
+     */
+
+    if (*next == now) {
+        (*next)++;
+    }
+
+    qemu_mod_timer(timer, *next);
+}
+
+static void booke_decr_cb(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    env->spr[SPR_BOOKE_TSR] |= TSR_DIS;
+    booke_update_irq(cpu);
+
+    if (env->spr[SPR_BOOKE_TCR] & TCR_ARE) {
+        /* Auto Reload */
+        cpu_ppc_store_decr(env, env->spr[SPR_BOOKE_DECAR]);
+    }
+}
+
+static void booke_fit_cb(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    ppc_tb_t *tb_env;
+    booke_timer_t *booke_timer;
+
+    tb_env = env->tb_env;
+    booke_timer = tb_env->opaque;
+    env->spr[SPR_BOOKE_TSR] |= TSR_FIS;
+
+    booke_update_irq(cpu);
+
+    booke_update_fixed_timer(env,
+                             booke_get_fit_target(env, tb_env),
+                             &booke_timer->fit_next,
+                             booke_timer->fit_timer);
+}
+
+static void booke_wdt_cb(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    ppc_tb_t *tb_env;
+    booke_timer_t *booke_timer;
+
+    tb_env = env->tb_env;
+    booke_timer = tb_env->opaque;
+
+    /* TODO: There's lots of complicated stuff to do here */
+
+    booke_update_irq(cpu);
+
+    booke_update_fixed_timer(env,
+                             booke_get_wdt_target(env, tb_env),
+                             &booke_timer->wdt_next,
+                             booke_timer->wdt_timer);
+}
+
+void store_booke_tsr(CPUPPCState *env, target_ulong val)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->spr[SPR_BOOKE_TSR] &= ~val;
+    booke_update_irq(cpu);
+}
+
+void store_booke_tcr(CPUPPCState *env, target_ulong val)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    ppc_tb_t *tb_env = env->tb_env;
+    booke_timer_t *booke_timer = tb_env->opaque;
+
+    tb_env = env->tb_env;
+    env->spr[SPR_BOOKE_TCR] = val;
+
+    booke_update_irq(cpu);
+
+    booke_update_fixed_timer(env,
+                             booke_get_fit_target(env, tb_env),
+                             &booke_timer->fit_next,
+                             booke_timer->fit_timer);
+
+    booke_update_fixed_timer(env,
+                             booke_get_wdt_target(env, tb_env),
+                             &booke_timer->wdt_next,
+                             booke_timer->wdt_timer);
+
+}
+
+static void ppc_booke_timer_reset_handle(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    env->spr[SPR_BOOKE_TSR] = 0;
+    env->spr[SPR_BOOKE_TCR] = 0;
+
+    booke_update_irq(cpu);
+}
+
+void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
+{
+    ppc_tb_t *tb_env;
+    booke_timer_t *booke_timer;
+
+    tb_env      = g_malloc0(sizeof(ppc_tb_t));
+    booke_timer = g_malloc0(sizeof(booke_timer_t));
+
+    cpu->env.tb_env = tb_env;
+    tb_env->flags = flags | PPC_TIMER_BOOKE | PPC_DECR_ZERO_TRIGGERED;
+
+    tb_env->tb_freq    = freq;
+    tb_env->decr_freq  = freq;
+    tb_env->opaque     = booke_timer;
+    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, cpu);
+
+    booke_timer->fit_timer =
+        qemu_new_timer_ns(vm_clock, &booke_fit_cb, cpu);
+    booke_timer->wdt_timer =
+        qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu);
+
+    qemu_register_reset(ppc_booke_timer_reset_handle, cpu);
+}
diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c
new file mode 100644 (file)
index 0000000..d904fbe
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * QEMU PowerPC e500v2 ePAPR spinning code
+ *
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Alexander Graf, <agraf@suse.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * This code is not really a device, but models an interface that usually
+ * firmware takes care of. It's used when QEMU plays the role of firmware.
+ *
+ * Specification:
+ *
+ * https://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.1.pdf
+ *
+ */
+
+#include "hw/hw.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "sysemu/kvm.h"
+
+#define MAX_CPUS 32
+
+typedef struct spin_info {
+    uint64_t addr;
+    uint64_t r3;
+    uint32_t resv;
+    uint32_t pir;
+    uint64_t reserved;
+} QEMU_PACKED SpinInfo;
+
+typedef struct spin_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    SpinInfo spin[MAX_CPUS];
+} SpinState;
+
+typedef struct spin_kick {
+    PowerPCCPU *cpu;
+    SpinInfo *spin;
+} SpinKick;
+
+static void spin_reset(void *opaque)
+{
+    SpinState *s = opaque;
+    int i;
+
+    for (i = 0; i < MAX_CPUS; i++) {
+        SpinInfo *info = &s->spin[i];
+
+        info->pir = i;
+        info->r3 = i;
+        info->addr = 1;
+    }
+}
+
+/* Create -kernel TLB entries for BookE, linearly spanning 256MB.  */
+static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
+{
+    return (ffs(size >> 10) - 1) >> 1;
+}
+
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
+                                     target_ulong va,
+                                     hwaddr pa,
+                                     hwaddr len)
+{
+    ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 1);
+    hwaddr size;
+
+    size = (booke206_page_size_to_tlb(len) << MAS1_TSIZE_SHIFT);
+    tlb->mas1 = MAS1_VALID | size;
+    tlb->mas2 = (va & TARGET_PAGE_MASK) | MAS2_M;
+    tlb->mas7_3 = pa & TARGET_PAGE_MASK;
+    tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
+    env->tlb_dirty = true;
+}
+
+static void spin_kick(void *data)
+{
+    SpinKick *kick = data;
+    CPUState *cpu = CPU(kick->cpu);
+    CPUPPCState *env = &kick->cpu->env;
+    SpinInfo *curspin = kick->spin;
+    hwaddr map_size = 64 * 1024 * 1024;
+    hwaddr map_start;
+
+    cpu_synchronize_state(env);
+    stl_p(&curspin->pir, env->spr[SPR_PIR]);
+    env->nip = ldq_p(&curspin->addr) & (map_size - 1);
+    env->gpr[3] = ldq_p(&curspin->r3);
+    env->gpr[4] = 0;
+    env->gpr[5] = 0;
+    env->gpr[6] = 0;
+    env->gpr[7] = map_size;
+    env->gpr[8] = 0;
+    env->gpr[9] = 0;
+
+    map_start = ldq_p(&curspin->addr) & ~(map_size - 1);
+    mmubooke_create_initial_mapping(env, 0, map_start, map_size);
+
+    env->halted = 0;
+    env->exception_index = -1;
+    cpu->stopped = false;
+    qemu_cpu_kick(cpu);
+}
+
+static void spin_write(void *opaque, hwaddr addr, uint64_t value,
+                       unsigned len)
+{
+    SpinState *s = opaque;
+    int env_idx = addr / sizeof(SpinInfo);
+    CPUState *cpu;
+    SpinInfo *curspin = &s->spin[env_idx];
+    uint8_t *curspin_p = (uint8_t*)curspin;
+
+    cpu = qemu_get_cpu(env_idx);
+    if (cpu == NULL) {
+        /* Unknown CPU */
+        return;
+    }
+
+    if (cpu->cpu_index == 0) {
+        /* primary CPU doesn't spin */
+        return;
+    }
+
+    curspin_p = &curspin_p[addr % sizeof(SpinInfo)];
+    switch (len) {
+    case 1:
+        stb_p(curspin_p, value);
+        break;
+    case 2:
+        stw_p(curspin_p, value);
+        break;
+    case 4:
+        stl_p(curspin_p, value);
+        break;
+    }
+
+    if (!(ldq_p(&curspin->addr) & 1)) {
+        /* run CPU */
+        SpinKick kick = {
+            .cpu = POWERPC_CPU(cpu),
+            .spin = curspin,
+        };
+
+        run_on_cpu(cpu, spin_kick, &kick);
+    }
+}
+
+static uint64_t spin_read(void *opaque, hwaddr addr, unsigned len)
+{
+    SpinState *s = opaque;
+    uint8_t *spin_p = &((uint8_t*)s->spin)[addr];
+
+    switch (len) {
+    case 1:
+        return ldub_p(spin_p);
+    case 2:
+        return lduw_p(spin_p);
+    case 4:
+        return ldl_p(spin_p);
+    default:
+        hw_error("ppce500: unexpected %s with len = %u", __func__, len);
+    }
+}
+
+static const MemoryRegionOps spin_rw_ops = {
+    .read = spin_read,
+    .write = spin_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static int ppce500_spin_initfn(SysBusDevice *dev)
+{
+    SpinState *s;
+
+    s = FROM_SYSBUS(SpinState, SYS_BUS_DEVICE(dev));
+
+    memory_region_init_io(&s->iomem, &spin_rw_ops, s, "e500 spin pv device",
+                          sizeof(SpinInfo) * MAX_CPUS);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    qemu_register_reset(spin_reset, s);
+
+    return 0;
+}
+
+static void ppce500_spin_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = ppce500_spin_initfn;
+}
+
+static const TypeInfo ppce500_spin_info = {
+    .name          = "e500-spin",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SpinState),
+    .class_init    = ppce500_spin_class_init,
+};
+
+static void ppce500_spin_register_types(void)
+{
+    type_register_static(&ppce500_spin_info);
+}
+
+type_init(ppce500_spin_register_types)
index e06dded00348ba1c68813efed95209deb23126d3..292091180d40a4c16f251f02e37ad6a0ee6f1306 100644 (file)
@@ -567,7 +567,6 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
 
     dev = qdev_create(NULL, "raven-pcihost");
     pcihost = PCI_HOST_BRIDGE(dev);
-    pcihost->address_space = get_system_memory();
     object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL);
     qdev_init_nofail(dev);
     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
new file mode 100644 (file)
index 0000000..fd24113
--- /dev/null
@@ -0,0 +1,964 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ * Copyright (c) 2010 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+#include "sysemu/sysemu.h"
+#include "hw/hw.h"
+#include "elf.h"
+#include "net/net.h"
+#include "sysemu/blockdev.h"
+#include "sysemu/cpus.h"
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+
+#include "hw/boards.h"
+#include "hw/ppc.h"
+#include "hw/loader.h"
+
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+#include "hw/spapr_pci.h"
+#include "hw/xics.h"
+#include "hw/pci/msi.h"
+
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+#include "hw/pci/pci.h"
+
+#include "exec/address-spaces.h"
+#include "hw/usb.h"
+#include "qemu/config-file.h"
+
+#include <libfdt.h>
+
+/* SLOF memory layout:
+ *
+ * SLOF raw image loaded at 0, copies its romfs right below the flat
+ * device-tree, then position SLOF itself 31M below that
+ *
+ * So we set FW_OVERHEAD to 40MB which should account for all of that
+ * and more
+ *
+ * We load our kernel at 4M, leaving space for SLOF initial image
+ */
+#define FDT_MAX_SIZE            0x10000
+#define RTAS_MAX_SIZE           0x10000
+#define FW_MAX_SIZE             0x400000
+#define FW_FILE_NAME            "slof.bin"
+#define FW_OVERHEAD             0x2800000
+#define KERNEL_LOAD_ADDR        FW_MAX_SIZE
+
+#define MIN_RMA_SLOF            128UL
+
+#define TIMEBASE_FREQ           512000000ULL
+
+#define MAX_CPUS                256
+#define XICS_IRQS               1024
+
+#define PHANDLE_XICP            0x00001111
+
+#define HTAB_SIZE(spapr)        (1ULL << ((spapr)->htab_shift))
+
+sPAPREnvironment *spapr;
+
+int spapr_allocate_irq(int hint, bool lsi)
+{
+    int irq;
+
+    if (hint) {
+        irq = hint;
+        /* FIXME: we should probably check for collisions somehow */
+    } else {
+        irq = spapr->next_irq++;
+    }
+
+    /* Configure irq type */
+    if (!xics_get_qirq(spapr->icp, irq)) {
+        return 0;
+    }
+
+    xics_set_irq_type(spapr->icp, irq, lsi);
+
+    return irq;
+}
+
+/* Allocate block of consequtive IRQs, returns a number of the first */
+int spapr_allocate_irq_block(int num, bool lsi)
+{
+    int first = -1;
+    int i;
+
+    for (i = 0; i < num; ++i) {
+        int irq;
+
+        irq = spapr_allocate_irq(0, lsi);
+        if (!irq) {
+            return -1;
+        }
+
+        if (0 == i) {
+            first = irq;
+        }
+
+        /* If the above doesn't create a consecutive block then that's
+         * an internal bug */
+        assert(irq == (first + i));
+    }
+
+    return first;
+}
+
+static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
+{
+    int ret = 0, offset;
+    CPUPPCState *env;
+    CPUState *cpu;
+    char cpu_model[32];
+    int smt = kvmppc_smt_threads();
+    uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
+
+    assert(spapr->cpu_model);
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu = CPU(ppc_env_get_cpu(env));
+        uint32_t associativity[] = {cpu_to_be32(0x5),
+                                    cpu_to_be32(0x0),
+                                    cpu_to_be32(0x0),
+                                    cpu_to_be32(0x0),
+                                    cpu_to_be32(cpu->numa_node),
+                                    cpu_to_be32(cpu->cpu_index)};
+
+        if ((cpu->cpu_index % smt) != 0) {
+            continue;
+        }
+
+        snprintf(cpu_model, 32, "/cpus/%s@%x", spapr->cpu_model,
+                 cpu->cpu_index);
+
+        offset = fdt_path_offset(fdt, cpu_model);
+        if (offset < 0) {
+            return offset;
+        }
+
+        if (nb_numa_nodes > 1) {
+            ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
+                              sizeof(associativity));
+            if (ret < 0) {
+                return ret;
+            }
+        }
+
+        ret = fdt_setprop(fdt, offset, "ibm,pft-size",
+                          pft_size_prop, sizeof(pft_size_prop));
+        if (ret < 0) {
+            return ret;
+        }
+    }
+    return ret;
+}
+
+
+static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
+                                     size_t maxsize)
+{
+    size_t maxcells = maxsize / sizeof(uint32_t);
+    int i, j, count;
+    uint32_t *p = prop;
+
+    for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
+        struct ppc_one_seg_page_size *sps = &env->sps.sps[i];
+
+        if (!sps->page_shift) {
+            break;
+        }
+        for (count = 0; count < PPC_PAGE_SIZES_MAX_SZ; count++) {
+            if (sps->enc[count].page_shift == 0) {
+                break;
+            }
+        }
+        if ((p - prop) >= (maxcells - 3 - count * 2)) {
+            break;
+        }
+        *(p++) = cpu_to_be32(sps->page_shift);
+        *(p++) = cpu_to_be32(sps->slb_enc);
+        *(p++) = cpu_to_be32(count);
+        for (j = 0; j < count; j++) {
+            *(p++) = cpu_to_be32(sps->enc[j].page_shift);
+            *(p++) = cpu_to_be32(sps->enc[j].pte_enc);
+        }
+    }
+
+    return (p - prop) * sizeof(uint32_t);
+}
+
+#define _FDT(exp) \
+    do { \
+        int ret = (exp);                                           \
+        if (ret < 0) {                                             \
+            fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
+                    #exp, fdt_strerror(ret));                      \
+            exit(1);                                               \
+        }                                                          \
+    } while (0)
+
+
+static void *spapr_create_fdt_skel(const char *cpu_model,
+                                   hwaddr initrd_base,
+                                   hwaddr initrd_size,
+                                   hwaddr kernel_size,
+                                   const char *boot_device,
+                                   const char *kernel_cmdline,
+                                   uint32_t epow_irq)
+{
+    void *fdt;
+    CPUPPCState *env;
+    uint32_t start_prop = cpu_to_be32(initrd_base);
+    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
+    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
+        "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
+    char qemu_hypertas_prop[] = "hcall-memop1";
+    uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
+    uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
+    char *modelname;
+    int i, smt = kvmppc_smt_threads();
+    unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
+
+    fdt = g_malloc0(FDT_MAX_SIZE);
+    _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
+
+    if (kernel_size) {
+        _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR, kernel_size)));
+    }
+    if (initrd_size) {
+        _FDT((fdt_add_reservemap_entry(fdt, initrd_base, initrd_size)));
+    }
+    _FDT((fdt_finish_reservemap(fdt)));
+
+    /* Root node */
+    _FDT((fdt_begin_node(fdt, "")));
+    _FDT((fdt_property_string(fdt, "device_type", "chrp")));
+    _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
+    _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
+
+    _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
+    _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
+
+    /* /chosen */
+    _FDT((fdt_begin_node(fdt, "chosen")));
+
+    /* Set Form1_affinity */
+    _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
+
+    _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));
+    _FDT((fdt_property(fdt, "linux,initrd-start",
+                       &start_prop, sizeof(start_prop))));
+    _FDT((fdt_property(fdt, "linux,initrd-end",
+                       &end_prop, sizeof(end_prop))));
+    if (kernel_size) {
+        uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
+                              cpu_to_be64(kernel_size) };
+
+        _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
+    }
+    if (boot_device) {
+        _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
+    }
+    _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
+    _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
+    _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
+
+    _FDT((fdt_end_node(fdt)));
+
+    /* cpus */
+    _FDT((fdt_begin_node(fdt, "cpus")));
+
+    _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
+    _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
+
+    modelname = g_strdup(cpu_model);
+
+    for (i = 0; i < strlen(modelname); i++) {
+        modelname[i] = toupper(modelname[i]);
+    }
+
+    /* This is needed during FDT finalization */
+    spapr->cpu_model = g_strdup(modelname);
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        CPUState *cpu = CPU(ppc_env_get_cpu(env));
+        int index = cpu->cpu_index;
+        uint32_t servers_prop[smp_threads];
+        uint32_t gservers_prop[smp_threads * 2];
+        char *nodename;
+        uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
+                           0xffffffff, 0xffffffff};
+        uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;
+        uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
+        uint32_t page_sizes_prop[64];
+        size_t page_sizes_prop_size;
+
+        if ((index % smt) != 0) {
+            continue;
+        }
+
+        nodename = g_strdup_printf("%s@%x", modelname, index);
+
+        _FDT((fdt_begin_node(fdt, nodename)));
+
+        g_free(nodename);
+
+        _FDT((fdt_property_cell(fdt, "reg", index)));
+        _FDT((fdt_property_string(fdt, "device_type", "cpu")));
+
+        _FDT((fdt_property_cell(fdt, "cpu-version", env->spr[SPR_PVR])));
+        _FDT((fdt_property_cell(fdt, "dcache-block-size",
+                                env->dcache_line_size)));
+        _FDT((fdt_property_cell(fdt, "icache-block-size",
+                                env->icache_line_size)));
+        _FDT((fdt_property_cell(fdt, "timebase-frequency", tbfreq)));
+        _FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));
+        _FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));
+        _FDT((fdt_property_string(fdt, "status", "okay")));
+        _FDT((fdt_property(fdt, "64-bit", NULL, 0)));
+
+        /* Build interrupt servers and gservers properties */
+        for (i = 0; i < smp_threads; i++) {
+            servers_prop[i] = cpu_to_be32(index + i);
+            /* Hack, direct the group queues back to cpu 0 */
+            gservers_prop[i*2] = cpu_to_be32(index + i);
+            gservers_prop[i*2 + 1] = 0;
+        }
+        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-server#s",
+                           servers_prop, sizeof(servers_prop))));
+        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
+                           gservers_prop, sizeof(gservers_prop))));
+
+        if (env->mmu_model & POWERPC_MMU_1TSEG) {
+            _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
+                               segs, sizeof(segs))));
+        }
+
+        /* Advertise VMX/VSX (vector extensions) if available
+         *   0 / no property == no vector extensions
+         *   1               == VMX / Altivec available
+         *   2               == VSX available */
+        if (env->insns_flags & PPC_ALTIVEC) {
+            uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
+
+            _FDT((fdt_property_cell(fdt, "ibm,vmx", vmx)));
+        }
+
+        /* Advertise DFP (Decimal Floating Point) if available
+         *   0 / no property == no DFP
+         *   1               == DFP available */
+        if (env->insns_flags2 & PPC2_DFP) {
+            _FDT((fdt_property_cell(fdt, "ibm,dfp", 1)));
+        }
+
+        page_sizes_prop_size = create_page_sizes_prop(env, page_sizes_prop,
+                                                      sizeof(page_sizes_prop));
+        if (page_sizes_prop_size) {
+            _FDT((fdt_property(fdt, "ibm,segment-page-sizes",
+                               page_sizes_prop, page_sizes_prop_size)));
+        }
+
+        _FDT((fdt_end_node(fdt)));
+    }
+
+    g_free(modelname);
+
+    _FDT((fdt_end_node(fdt)));
+
+    /* RTAS */
+    _FDT((fdt_begin_node(fdt, "rtas")));
+
+    _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop,
+                       sizeof(hypertas_prop))));
+    _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas_prop,
+                       sizeof(qemu_hypertas_prop))));
+
+    _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
+        refpoints, sizeof(refpoints))));
+
+    _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
+
+    _FDT((fdt_end_node(fdt)));
+
+    /* interrupt controller */
+    _FDT((fdt_begin_node(fdt, "interrupt-controller")));
+
+    _FDT((fdt_property_string(fdt, "device_type",
+                              "PowerPC-External-Interrupt-Presentation")));
+    _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
+    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+    _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
+                       interrupt_server_ranges_prop,
+                       sizeof(interrupt_server_ranges_prop))));
+    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
+    _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
+    _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
+
+    _FDT((fdt_end_node(fdt)));
+
+    /* vdevice */
+    _FDT((fdt_begin_node(fdt, "vdevice")));
+
+    _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
+    _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
+    _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
+    _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
+    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
+    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+
+    _FDT((fdt_end_node(fdt)));
+
+    /* event-sources */
+    spapr_events_fdt_skel(fdt, epow_irq);
+
+    _FDT((fdt_end_node(fdt))); /* close root node */
+    _FDT((fdt_finish(fdt)));
+
+    return fdt;
+}
+
+static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
+{
+    uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
+                                cpu_to_be32(0x0), cpu_to_be32(0x0),
+                                cpu_to_be32(0x0)};
+    char mem_name[32];
+    hwaddr node0_size, mem_start;
+    uint64_t mem_reg_property[2];
+    int i, off;
+
+    /* memory node(s) */
+    node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
+    if (spapr->rma_size > node0_size) {
+        spapr->rma_size = node0_size;
+    }
+
+    /* RMA */
+    mem_reg_property[0] = 0;
+    mem_reg_property[1] = cpu_to_be64(spapr->rma_size);
+    off = fdt_add_subnode(fdt, 0, "memory@0");
+    _FDT(off);
+    _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
+    _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
+                      sizeof(mem_reg_property))));
+    _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
+                      sizeof(associativity))));
+
+    /* RAM: Node 0 */
+    if (node0_size > spapr->rma_size) {
+        mem_reg_property[0] = cpu_to_be64(spapr->rma_size);
+        mem_reg_property[1] = cpu_to_be64(node0_size - spapr->rma_size);
+
+        sprintf(mem_name, "memory@" TARGET_FMT_lx, spapr->rma_size);
+        off = fdt_add_subnode(fdt, 0, mem_name);
+        _FDT(off);
+        _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
+        _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
+                          sizeof(mem_reg_property))));
+        _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
+                          sizeof(associativity))));
+    }
+
+    /* RAM: Node 1 and beyond */
+    mem_start = node0_size;
+    for (i = 1; i < nb_numa_nodes; i++) {
+        mem_reg_property[0] = cpu_to_be64(mem_start);
+        mem_reg_property[1] = cpu_to_be64(node_mem[i]);
+        associativity[3] = associativity[4] = cpu_to_be32(i);
+        sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
+        off = fdt_add_subnode(fdt, 0, mem_name);
+        _FDT(off);
+        _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
+        _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
+                          sizeof(mem_reg_property))));
+        _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
+                          sizeof(associativity))));
+        mem_start += node_mem[i];
+    }
+
+    return 0;
+}
+
+static void spapr_finalize_fdt(sPAPREnvironment *spapr,
+                               hwaddr fdt_addr,
+                               hwaddr rtas_addr,
+                               hwaddr rtas_size)
+{
+    int ret;
+    void *fdt;
+    sPAPRPHBState *phb;
+
+    fdt = g_malloc(FDT_MAX_SIZE);
+
+    /* open out the base tree into a temp buffer for the final tweaks */
+    _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE)));
+
+    ret = spapr_populate_memory(spapr, fdt);
+    if (ret < 0) {
+        fprintf(stderr, "couldn't setup memory nodes in fdt\n");
+        exit(1);
+    }
+
+    ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
+    if (ret < 0) {
+        fprintf(stderr, "couldn't setup vio devices in fdt\n");
+        exit(1);
+    }
+
+    QLIST_FOREACH(phb, &spapr->phbs, list) {
+        ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt);
+    }
+
+    if (ret < 0) {
+        fprintf(stderr, "couldn't setup PCI devices in fdt\n");
+        exit(1);
+    }
+
+    /* RTAS */
+    ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
+    }
+
+    /* Advertise NUMA via ibm,associativity */
+    ret = spapr_fixup_cpu_dt(fdt, spapr);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't finalize CPU device tree properties\n");
+    }
+
+    if (!spapr->has_graphics) {
+        spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
+    }
+
+    _FDT((fdt_pack(fdt)));
+
+    if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
+        hw_error("FDT too big ! 0x%x bytes (max is 0x%x)\n",
+                 fdt_totalsize(fdt), FDT_MAX_SIZE);
+        exit(1);
+    }
+
+    cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
+
+    g_free(fdt);
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
+}
+
+static void emulate_spapr_hypercall(PowerPCCPU *cpu)
+{
+    CPUPPCState *env = &cpu->env;
+
+    if (msr_pr) {
+        hcall_dprintf("Hypercall made with MSR[PR]=1\n");
+        env->gpr[3] = H_PRIVILEGE;
+    } else {
+        env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]);
+    }
+}
+
+static void spapr_reset_htab(sPAPREnvironment *spapr)
+{
+    long shift;
+
+    /* allocate hash page table.  For now we always make this 16mb,
+     * later we should probably make it scale to the size of guest
+     * RAM */
+
+    shift = kvmppc_reset_htab(spapr->htab_shift);
+
+    if (shift > 0) {
+        /* Kernel handles htab, we don't need to allocate one */
+        spapr->htab_shift = shift;
+    } else {
+        if (!spapr->htab) {
+            /* Allocate an htab if we don't yet have one */
+            spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr));
+        }
+
+        /* And clear it */
+        memset(spapr->htab, 0, HTAB_SIZE(spapr));
+    }
+
+    /* Update the RMA size if necessary */
+    if (spapr->vrma_adjust) {
+        spapr->rma_size = kvmppc_rma_size(ram_size, spapr->htab_shift);
+    }
+}
+
+static void ppc_spapr_reset(void)
+{
+    /* Reset the hash table & recalc the RMA */
+    spapr_reset_htab(spapr);
+
+    qemu_devices_reset();
+
+    /* Load the fdt */
+    spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr,
+                       spapr->rtas_size);
+
+    /* Set up the entry state */
+    first_cpu->gpr[3] = spapr->fdt_addr;
+    first_cpu->gpr[5] = 0;
+    first_cpu->halted = 0;
+    first_cpu->nip = spapr->entry_point;
+
+}
+
+static void spapr_cpu_reset(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+
+    /* All CPUs start halted.  CPU0 is unhalted from the machine level
+     * reset code and the rest are explicitly started up by the guest
+     * using an RTAS call */
+    env->halted = 1;
+
+    env->spr[SPR_HIOR] = 0;
+
+    env->external_htab = spapr->htab;
+    env->htab_base = -1;
+    env->htab_mask = HTAB_SIZE(spapr) - 1;
+    env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
+        (spapr->htab_shift - 18);
+}
+
+static void spapr_create_nvram(sPAPREnvironment *spapr)
+{
+    QemuOpts *machine_opts;
+    DeviceState *dev;
+
+    dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+
+    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+    if (machine_opts) {
+        const char *drivename;
+
+        drivename = qemu_opt_get(machine_opts, "nvram");
+        if (drivename) {
+            BlockDriverState *bs;
+
+            bs = bdrv_find(drivename);
+            if (!bs) {
+                fprintf(stderr, "No such block device \"%s\" for nvram\n",
+                        drivename);
+                exit(1);
+            }
+            qdev_prop_set_drive_nofail(dev, "drive", bs);
+        }
+    }
+
+    qdev_init_nofail(dev);
+
+    spapr->nvram = (struct sPAPRNVRAM *)dev;
+}
+
+/* Returns whether we want to use VGA or not */
+static int spapr_vga_init(PCIBus *pci_bus)
+{
+    switch (vga_interface_type) {
+    case VGA_NONE:
+    case VGA_STD:
+        return pci_vga_init(pci_bus) != NULL;
+    default:
+        fprintf(stderr, "This vga model is not supported,"
+                "currently it only supports -vga std\n");
+        exit(0);
+        break;
+    }
+}
+
+/* pSeries LPAR / sPAPR hardware init */
+static void ppc_spapr_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    PCIHostState *phb;
+    int i;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    hwaddr rma_alloc_size;
+    uint32_t initrd_base = 0;
+    long kernel_size = 0, initrd_size = 0;
+    long load_limit, rtas_limit, fw_size;
+    char *filename;
+
+    msi_supported = true;
+
+    spapr = g_malloc0(sizeof(*spapr));
+    QLIST_INIT(&spapr->phbs);
+
+    cpu_ppc_hypercall = emulate_spapr_hypercall;
+
+    /* Allocate RMA if necessary */
+    rma_alloc_size = kvmppc_alloc_rma("ppc_spapr.rma", sysmem);
+
+    if (rma_alloc_size == -1) {
+        hw_error("qemu: Unable to create RMA\n");
+        exit(1);
+    }
+
+    if (rma_alloc_size && (rma_alloc_size < ram_size)) {
+        spapr->rma_size = rma_alloc_size;
+    } else {
+        spapr->rma_size = ram_size;
+
+        /* With KVM, we don't actually know whether KVM supports an
+         * unbounded RMA (PR KVM) or is limited by the hash table size
+         * (HV KVM using VRMA), so we always assume the latter
+         *
+         * In that case, we also limit the initial allocations for RTAS
+         * etc... to 256M since we have no way to know what the VRMA size
+         * is going to be as it depends on the size of the hash table
+         * isn't determined yet.
+         */
+        if (kvm_enabled()) {
+            spapr->vrma_adjust = 1;
+            spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
+        }
+    }
+
+    /* We place the device tree and RTAS just below either the top of the RMA,
+     * or just below 2GB, whichever is lowere, so that it can be
+     * processed with 32-bit real mode code if necessary */
+    rtas_limit = MIN(spapr->rma_size, 0x80000000);
+    spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
+    spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
+    load_limit = spapr->fdt_addr - FW_OVERHEAD;
+
+    /* We aim for a hash table of size 1/128 the size of RAM.  The
+     * normal rule of thumb is 1/64 the size of RAM, but that's much
+     * more than needed for the Linux guests we support. */
+    spapr->htab_shift = 18; /* Minimum architected size */
+    while (spapr->htab_shift <= 46) {
+        if ((1ULL << (spapr->htab_shift + 7)) >= ram_size) {
+            break;
+        }
+        spapr->htab_shift++;
+    }
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = kvm_enabled() ? "host" : "POWER7";
+    }
+    for (i = 0; i < smp_cpus; i++) {
+        cpu = cpu_ppc_init(cpu_model);
+        if (cpu == NULL) {
+            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
+            exit(1);
+        }
+        env = &cpu->env;
+
+        /* Set time-base frequency to 512 MHz */
+        cpu_ppc_tb_init(env, TIMEBASE_FREQ);
+
+        /* PAPR always has exception vectors in RAM not ROM */
+        env->hreset_excp_prefix = 0;
+
+        /* Tell KVM that we're in PAPR mode */
+        if (kvm_enabled()) {
+            kvmppc_set_papr(cpu);
+        }
+
+        qemu_register_reset(spapr_cpu_reset, cpu);
+    }
+
+    /* allocate RAM */
+    spapr->ram_limit = ram_size;
+    if (spapr->ram_limit > rma_alloc_size) {
+        ram_addr_t nonrma_base = rma_alloc_size;
+        ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
+
+        memory_region_init_ram(ram, "ppc_spapr.ram", nonrma_size);
+        vmstate_register_ram_global(ram);
+        memory_region_add_subregion(sysmem, nonrma_base, ram);
+    }
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
+    spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr,
+                                           rtas_limit - spapr->rtas_addr);
+    if (spapr->rtas_size < 0) {
+        hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
+        exit(1);
+    }
+    if (spapr->rtas_size > RTAS_MAX_SIZE) {
+        hw_error("RTAS too big ! 0x%lx bytes (max is 0x%x)\n",
+                 spapr->rtas_size, RTAS_MAX_SIZE);
+        exit(1);
+    }
+    g_free(filename);
+
+
+    /* Set up Interrupt Controller */
+    spapr->icp = xics_system_init(XICS_IRQS);
+    spapr->next_irq = XICS_IRQ_BASE;
+
+    /* Set up EPOW events infrastructure */
+    spapr_events_init(spapr);
+
+    /* Set up IOMMU */
+    spapr_iommu_init();
+
+    /* Set up VIO bus */
+    spapr->vio_bus = spapr_vio_bus_init();
+
+    for (i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            spapr_vty_create(spapr->vio_bus, serial_hds[i]);
+        }
+    }
+
+    /* We always have at least the nvram device on VIO */
+    spapr_create_nvram(spapr);
+
+    /* Set up PCI */
+    spapr_pci_rtas_init();
+
+    phb = spapr_create_phb(spapr, 0, "pci");
+
+    for (i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+
+        if (!nd->model) {
+            nd->model = g_strdup("ibmveth");
+        }
+
+        if (strcmp(nd->model, "ibmveth") == 0) {
+            spapr_vlan_create(spapr->vio_bus, nd);
+        } else {
+            pci_nic_init_nofail(&nd_table[i], nd->model, NULL);
+        }
+    }
+
+    for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
+        spapr_vscsi_create(spapr->vio_bus);
+    }
+
+    /* Graphics */
+    if (spapr_vga_init(phb->bus)) {
+        spapr->has_graphics = true;
+    }
+
+    if (usb_enabled(spapr->has_graphics)) {
+        pci_create_simple(phb->bus, -1, "pci-ohci");
+        if (spapr->has_graphics) {
+            usbdevice_create("keyboard");
+            usbdevice_create("mouse");
+        }
+    }
+
+    if (spapr->rma_size < (MIN_RMA_SLOF << 20)) {
+        fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
+                "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
+        exit(1);
+    }
+
+    if (kernel_filename) {
+        uint64_t lowaddr = 0;
+
+        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+                               NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename,
+                                              KERNEL_LOAD_ADDR,
+                                              load_limit - KERNEL_LOAD_ADDR);
+        }
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+
+        /* load initrd */
+        if (initrd_filename) {
+            /* Try to locate the initrd in the gap between the kernel
+             * and the firmware. Add a bit of space just in case
+             */
+            initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff;
+            initrd_size = load_image_targphys(initrd_filename, initrd_base,
+                                              load_limit - initrd_base);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_base = 0;
+            initrd_size = 0;
+        }
+    }
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
+    fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
+    if (fw_size < 0) {
+        hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
+        exit(1);
+    }
+    g_free(filename);
+
+    spapr->entry_point = 0x100;
+
+    /* Prepare the device tree */
+    spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
+                                            initrd_base, initrd_size,
+                                            kernel_size,
+                                            boot_device, kernel_cmdline,
+                                            spapr->epow_irq);
+    assert(spapr->fdt_skel != NULL);
+}
+
+static QEMUMachine spapr_machine = {
+    .name = "pseries",
+    .desc = "pSeries Logical Partition (PAPR compliant)",
+    .init = ppc_spapr_init,
+    .reset = ppc_spapr_reset,
+    .block_default_type = IF_SCSI,
+    .max_cpus = MAX_CPUS,
+    .no_parallel = 1,
+    .boot_order = NULL,
+};
+
+static void spapr_machine_init(void)
+{
+    qemu_register_machine(&spapr_machine);
+}
+
+machine_init(spapr_machine_init);
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
new file mode 100644 (file)
index 0000000..ce78f09
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * RTAS events handling
+ *
+ * Copyright (c) 2012 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+#include "cpu.h"
+#include "sysemu/sysemu.h"
+#include "char/char.h"
+#include "hw/qdev.h"
+#include "sysemu/device_tree.h"
+
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+
+#include <libfdt.h>
+
+struct rtas_error_log {
+    uint32_t summary;
+#define RTAS_LOG_VERSION_MASK                   0xff000000
+#define   RTAS_LOG_VERSION_6                    0x06000000
+#define RTAS_LOG_SEVERITY_MASK                  0x00e00000
+#define   RTAS_LOG_SEVERITY_ALREADY_REPORTED    0x00c00000
+#define   RTAS_LOG_SEVERITY_FATAL               0x00a00000
+#define   RTAS_LOG_SEVERITY_ERROR               0x00800000
+#define   RTAS_LOG_SEVERITY_ERROR_SYNC          0x00600000
+#define   RTAS_LOG_SEVERITY_WARNING             0x00400000
+#define   RTAS_LOG_SEVERITY_EVENT               0x00200000
+#define   RTAS_LOG_SEVERITY_NO_ERROR            0x00000000
+#define RTAS_LOG_DISPOSITION_MASK               0x00180000
+#define   RTAS_LOG_DISPOSITION_FULLY_RECOVERED  0x00000000
+#define   RTAS_LOG_DISPOSITION_LIMITED_RECOVERY 0x00080000
+#define   RTAS_LOG_DISPOSITION_NOT_RECOVERED    0x00100000
+#define RTAS_LOG_OPTIONAL_PART_PRESENT          0x00040000
+#define RTAS_LOG_INITIATOR_MASK                 0x0000f000
+#define   RTAS_LOG_INITIATOR_UNKNOWN            0x00000000
+#define   RTAS_LOG_INITIATOR_CPU                0x00001000
+#define   RTAS_LOG_INITIATOR_PCI                0x00002000
+#define   RTAS_LOG_INITIATOR_MEMORY             0x00004000
+#define   RTAS_LOG_INITIATOR_HOTPLUG            0x00006000
+#define RTAS_LOG_TARGET_MASK                    0x00000f00
+#define   RTAS_LOG_TARGET_UNKNOWN               0x00000000
+#define   RTAS_LOG_TARGET_CPU                   0x00000100
+#define   RTAS_LOG_TARGET_PCI                   0x00000200
+#define   RTAS_LOG_TARGET_MEMORY                0x00000400
+#define   RTAS_LOG_TARGET_HOTPLUG               0x00000600
+#define RTAS_LOG_TYPE_MASK                      0x000000ff
+#define   RTAS_LOG_TYPE_OTHER                   0x00000000
+#define   RTAS_LOG_TYPE_RETRY                   0x00000001
+#define   RTAS_LOG_TYPE_TCE_ERR                 0x00000002
+#define   RTAS_LOG_TYPE_INTERN_DEV_FAIL         0x00000003
+#define   RTAS_LOG_TYPE_TIMEOUT                 0x00000004
+#define   RTAS_LOG_TYPE_DATA_PARITY             0x00000005
+#define   RTAS_LOG_TYPE_ADDR_PARITY             0x00000006
+#define   RTAS_LOG_TYPE_CACHE_PARITY            0x00000007
+#define   RTAS_LOG_TYPE_ADDR_INVALID            0x00000008
+#define   RTAS_LOG_TYPE_ECC_UNCORR              0x00000009
+#define   RTAS_LOG_TYPE_ECC_CORR                0x0000000a
+#define   RTAS_LOG_TYPE_EPOW                    0x00000040
+    uint32_t extended_length;
+} QEMU_PACKED;
+
+struct rtas_event_log_v6 {
+    uint8_t b0;
+#define RTAS_LOG_V6_B0_VALID                          0x80
+#define RTAS_LOG_V6_B0_UNRECOVERABLE_ERROR            0x40
+#define RTAS_LOG_V6_B0_RECOVERABLE_ERROR              0x20
+#define RTAS_LOG_V6_B0_DEGRADED_OPERATION             0x10
+#define RTAS_LOG_V6_B0_PREDICTIVE_ERROR               0x08
+#define RTAS_LOG_V6_B0_NEW_LOG                        0x04
+#define RTAS_LOG_V6_B0_BIGENDIAN                      0x02
+    uint8_t _resv1;
+    uint8_t b2;
+#define RTAS_LOG_V6_B2_POWERPC_FORMAT                 0x80
+#define RTAS_LOG_V6_B2_LOG_FORMAT_MASK                0x0f
+#define   RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT    0x0e
+    uint8_t _resv2[9];
+    uint32_t company;
+#define RTAS_LOG_V6_COMPANY_IBM                 0x49424d00 /* IBM<null> */
+} QEMU_PACKED;
+
+struct rtas_event_log_v6_section_header {
+    uint16_t section_id;
+    uint16_t section_length;
+    uint8_t section_version;
+    uint8_t section_subtype;
+    uint16_t creator_component_id;
+} QEMU_PACKED;
+
+struct rtas_event_log_v6_maina {
+#define RTAS_LOG_V6_SECTION_ID_MAINA                0x5048 /* PH */
+    struct rtas_event_log_v6_section_header hdr;
+    uint32_t creation_date; /* BCD: YYYYMMDD */
+    uint32_t creation_time; /* BCD: HHMMSS00 */
+    uint8_t _platform1[8];
+    char creator_id;
+    uint8_t _resv1[2];
+    uint8_t section_count;
+    uint8_t _resv2[4];
+    uint8_t _platform2[8];
+    uint32_t plid;
+    uint8_t _platform3[4];
+} QEMU_PACKED;
+
+struct rtas_event_log_v6_mainb {
+#define RTAS_LOG_V6_SECTION_ID_MAINB                0x5548 /* UH */
+    struct rtas_event_log_v6_section_header hdr;
+    uint8_t subsystem_id;
+    uint8_t _platform1;
+    uint8_t event_severity;
+    uint8_t event_subtype;
+    uint8_t _platform2[4];
+    uint8_t _resv1[2];
+    uint16_t action_flags;
+    uint8_t _resv2[4];
+} QEMU_PACKED;
+
+struct rtas_event_log_v6_epow {
+#define RTAS_LOG_V6_SECTION_ID_EPOW                 0x4550 /* EP */
+    struct rtas_event_log_v6_section_header hdr;
+    uint8_t sensor_value;
+#define RTAS_LOG_V6_EPOW_ACTION_RESET                    0
+#define RTAS_LOG_V6_EPOW_ACTION_WARN_COOLING             1
+#define RTAS_LOG_V6_EPOW_ACTION_WARN_POWER               2
+#define RTAS_LOG_V6_EPOW_ACTION_SYSTEM_SHUTDOWN          3
+#define RTAS_LOG_V6_EPOW_ACTION_SYSTEM_HALT              4
+#define RTAS_LOG_V6_EPOW_ACTION_MAIN_ENCLOSURE           5
+#define RTAS_LOG_V6_EPOW_ACTION_POWER_OFF                7
+    uint8_t event_modifier;
+#define RTAS_LOG_V6_EPOW_MODIFIER_NORMAL                 1
+#define RTAS_LOG_V6_EPOW_MODIFIER_ON_UPS                 2
+#define RTAS_LOG_V6_EPOW_MODIFIER_CRITICAL               3
+#define RTAS_LOG_V6_EPOW_MODIFIER_TEMPERATURE            4
+    uint8_t extended_modifier;
+#define RTAS_LOG_V6_EPOW_XMODIFIER_SYSTEM_WIDE           0
+#define RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC    1
+    uint8_t _resv;
+    uint64_t reason_code;
+} QEMU_PACKED;
+
+struct epow_log_full {
+    struct rtas_error_log hdr;
+    struct rtas_event_log_v6 v6hdr;
+    struct rtas_event_log_v6_maina maina;
+    struct rtas_event_log_v6_mainb mainb;
+    struct rtas_event_log_v6_epow epow;
+} QEMU_PACKED;
+
+#define EVENT_MASK_INTERNAL_ERRORS           0x80000000
+#define EVENT_MASK_EPOW                      0x40000000
+#define EVENT_MASK_HOTPLUG                   0x10000000
+#define EVENT_MASK_IO                        0x08000000
+
+#define _FDT(exp) \
+    do { \
+        int ret = (exp);                                           \
+        if (ret < 0) {                                             \
+            fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
+                    #exp, fdt_strerror(ret));                      \
+            exit(1);                                               \
+        }                                                          \
+    } while (0)
+
+void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq)
+{
+    uint32_t epow_irq_ranges[] = {cpu_to_be32(epow_irq), cpu_to_be32(1)};
+    uint32_t epow_interrupts[] = {cpu_to_be32(epow_irq), 0};
+
+    _FDT((fdt_begin_node(fdt, "event-sources")));
+
+    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
+    _FDT((fdt_property(fdt, "interrupt-ranges",
+                       epow_irq_ranges, sizeof(epow_irq_ranges))));
+
+    _FDT((fdt_begin_node(fdt, "epow-events")));
+    _FDT((fdt_property(fdt, "interrupts",
+                       epow_interrupts, sizeof(epow_interrupts))));
+    _FDT((fdt_end_node(fdt)));
+
+    _FDT((fdt_end_node(fdt)));
+}
+
+static struct epow_log_full *pending_epow;
+static uint32_t next_plid;
+
+static void spapr_powerdown_req(Notifier *n, void *opaque)
+{
+    sPAPREnvironment *spapr = container_of(n, sPAPREnvironment, epow_notifier);
+    struct rtas_error_log *hdr;
+    struct rtas_event_log_v6 *v6hdr;
+    struct rtas_event_log_v6_maina *maina;
+    struct rtas_event_log_v6_mainb *mainb;
+    struct rtas_event_log_v6_epow *epow;
+    struct tm tm;
+    int year;
+
+    if (pending_epow) {
+        /* For now, we just throw away earlier events if two come
+         * along before any are consumed.  This is sufficient for our
+         * powerdown messages, but we'll need more if we do more
+         * general error/event logging */
+        g_free(pending_epow);
+    }
+    pending_epow = g_malloc0(sizeof(*pending_epow));
+    hdr = &pending_epow->hdr;
+    v6hdr = &pending_epow->v6hdr;
+    maina = &pending_epow->maina;
+    mainb = &pending_epow->mainb;
+    epow = &pending_epow->epow;
+
+    hdr->summary = cpu_to_be32(RTAS_LOG_VERSION_6
+                               | RTAS_LOG_SEVERITY_EVENT
+                               | RTAS_LOG_DISPOSITION_NOT_RECOVERED
+                               | RTAS_LOG_OPTIONAL_PART_PRESENT
+                               | RTAS_LOG_TYPE_EPOW);
+    hdr->extended_length = cpu_to_be32(sizeof(*pending_epow)
+                                       - sizeof(pending_epow->hdr));
+
+    v6hdr->b0 = RTAS_LOG_V6_B0_VALID | RTAS_LOG_V6_B0_NEW_LOG
+        | RTAS_LOG_V6_B0_BIGENDIAN;
+    v6hdr->b2 = RTAS_LOG_V6_B2_POWERPC_FORMAT
+        | RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT;
+    v6hdr->company = cpu_to_be32(RTAS_LOG_V6_COMPANY_IBM);
+
+    maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA);
+    maina->hdr.section_length = cpu_to_be16(sizeof(*maina));
+    /* FIXME: section version, subtype and creator id? */
+    qemu_get_timedate(&tm, spapr->rtc_offset);
+    year = tm.tm_year + 1900;
+    maina->creation_date = cpu_to_be32((to_bcd(year / 100) << 24)
+                                       | (to_bcd(year % 100) << 16)
+                                       | (to_bcd(tm.tm_mon + 1) << 8)
+                                       | to_bcd(tm.tm_mday));
+    maina->creation_time = cpu_to_be32((to_bcd(tm.tm_hour) << 24)
+                                       | (to_bcd(tm.tm_min) << 16)
+                                       | (to_bcd(tm.tm_sec) << 8));
+    maina->creator_id = 'H'; /* Hypervisor */
+    maina->section_count = 3; /* Main-A, Main-B and EPOW */
+    maina->plid = next_plid++;
+
+    mainb->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINB);
+    mainb->hdr.section_length = cpu_to_be16(sizeof(*mainb));
+    /* FIXME: section version, subtype and creator id? */
+    mainb->subsystem_id = 0xa0; /* External environment */
+    mainb->event_severity = 0x00; /* Informational / non-error */
+    mainb->event_subtype = 0xd0; /* Normal shutdown */
+
+    epow->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_EPOW);
+    epow->hdr.section_length = cpu_to_be16(sizeof(*epow));
+    epow->hdr.section_version = 2; /* includes extended modifier */
+    /* FIXME: section subtype and creator id? */
+    epow->sensor_value = RTAS_LOG_V6_EPOW_ACTION_SYSTEM_SHUTDOWN;
+    epow->event_modifier = RTAS_LOG_V6_EPOW_MODIFIER_NORMAL;
+    epow->extended_modifier = RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC;
+
+    qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->epow_irq));
+}
+
+static void check_exception(sPAPREnvironment *spapr,
+                            uint32_t token, uint32_t nargs,
+                            target_ulong args,
+                            uint32_t nret, target_ulong rets)
+{
+    uint32_t mask, buf, len;
+    uint64_t xinfo;
+
+    if ((nargs < 6) || (nargs > 7) || nret != 1) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    xinfo = rtas_ld(args, 1);
+    mask = rtas_ld(args, 2);
+    buf = rtas_ld(args, 4);
+    len = rtas_ld(args, 5);
+    if (nargs == 7) {
+        xinfo |= (uint64_t)rtas_ld(args, 6) << 32;
+    }
+
+    if ((mask & EVENT_MASK_EPOW) && pending_epow) {
+        if (sizeof(*pending_epow) < len) {
+            len = sizeof(*pending_epow);
+        }
+
+        cpu_physical_memory_write(buf, pending_epow, len);
+        g_free(pending_epow);
+        pending_epow = NULL;
+        rtas_st(rets, 0, 0);
+    } else {
+        rtas_st(rets, 0, 1);
+    }
+}
+
+void spapr_events_init(sPAPREnvironment *spapr)
+{
+    spapr->epow_irq = spapr_allocate_msi(0);
+    spapr->epow_notifier.notify = spapr_powerdown_req;
+    qemu_register_powerdown_notifier(&spapr->epow_notifier);
+    spapr_rtas_register("check-exception", check_exception);
+}
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
new file mode 100644 (file)
index 0000000..77c052f
--- /dev/null
@@ -0,0 +1,772 @@
+#include "sysemu/sysemu.h"
+#include "cpu.h"
+#include "sysemu/sysemu.h"
+#include "helper_regs.h"
+#include "hw/spapr.h"
+
+#define HPTES_PER_GROUP 8
+
+#define HPTE_V_SSIZE_SHIFT      62
+#define HPTE_V_AVPN_SHIFT       7
+#define HPTE_V_AVPN             0x3fffffffffffff80ULL
+#define HPTE_V_AVPN_VAL(x)      (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
+#define HPTE_V_COMPARE(x, y)    (!(((x) ^ (y)) & 0xffffffffffffff80UL))
+#define HPTE_V_BOLTED           0x0000000000000010ULL
+#define HPTE_V_LOCK             0x0000000000000008ULL
+#define HPTE_V_LARGE            0x0000000000000004ULL
+#define HPTE_V_SECONDARY        0x0000000000000002ULL
+#define HPTE_V_VALID            0x0000000000000001ULL
+
+#define HPTE_R_PP0              0x8000000000000000ULL
+#define HPTE_R_TS               0x4000000000000000ULL
+#define HPTE_R_KEY_HI           0x3000000000000000ULL
+#define HPTE_R_RPN_SHIFT        12
+#define HPTE_R_RPN              0x3ffffffffffff000ULL
+#define HPTE_R_FLAGS            0x00000000000003ffULL
+#define HPTE_R_PP               0x0000000000000003ULL
+#define HPTE_R_N                0x0000000000000004ULL
+#define HPTE_R_G                0x0000000000000008ULL
+#define HPTE_R_M                0x0000000000000010ULL
+#define HPTE_R_I                0x0000000000000020ULL
+#define HPTE_R_W                0x0000000000000040ULL
+#define HPTE_R_WIMG             0x0000000000000078ULL
+#define HPTE_R_C                0x0000000000000080ULL
+#define HPTE_R_R                0x0000000000000100ULL
+#define HPTE_R_KEY_LO           0x0000000000000e00ULL
+
+#define HPTE_V_1TB_SEG          0x4000000000000000ULL
+#define HPTE_V_VRMA_MASK        0x4001ffffff000000ULL
+
+static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
+                                     target_ulong pte_index)
+{
+    target_ulong rb, va_low;
+
+    rb = (v & ~0x7fULL) << 16; /* AVA field */
+    va_low = pte_index >> 3;
+    if (v & HPTE_V_SECONDARY) {
+        va_low = ~va_low;
+    }
+    /* xor vsid from AVA */
+    if (!(v & HPTE_V_1TB_SEG)) {
+        va_low ^= v >> 12;
+    } else {
+        va_low ^= v >> 24;
+    }
+    va_low &= 0x7ff;
+    if (v & HPTE_V_LARGE) {
+        rb |= 1;                         /* L field */
+#if 0 /* Disable that P7 specific bit for now */
+        if (r & 0xff000) {
+            /* non-16MB large page, must be 64k */
+            /* (masks depend on page size) */
+            rb |= 0x1000;                /* page encoding in LP field */
+            rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
+            rb |= (va_low & 0xfe);       /* AVAL field */
+        }
+#endif
+    } else {
+        /* 4kB page */
+        rb |= (va_low & 0x7ff) << 12;   /* remaining 11b of AVA */
+    }
+    rb |= (v >> 54) & 0x300;            /* B field */
+    return rb;
+}
+
+static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                            target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong flags = args[0];
+    target_ulong pte_index = args[1];
+    target_ulong pteh = args[2];
+    target_ulong ptel = args[3];
+    target_ulong page_shift = 12;
+    target_ulong raddr;
+    target_ulong i;
+    uint8_t *hpte;
+
+    /* only handle 4k and 16M pages for now */
+    if (pteh & HPTE_V_LARGE) {
+#if 0 /* We don't support 64k pages yet */
+        if ((ptel & 0xf000) == 0x1000) {
+            /* 64k page */
+        } else
+#endif
+        if ((ptel & 0xff000) == 0) {
+            /* 16M page */
+            page_shift = 24;
+            /* lowest AVA bit must be 0 for 16M pages */
+            if (pteh & 0x80) {
+                return H_PARAMETER;
+            }
+        } else {
+            return H_PARAMETER;
+        }
+    }
+
+    raddr = (ptel & HPTE_R_RPN) & ~((1ULL << page_shift) - 1);
+
+    if (raddr < spapr->ram_limit) {
+        /* Regular RAM - should have WIMG=0010 */
+        if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
+            return H_PARAMETER;
+        }
+    } else {
+        /* Looks like an IO address */
+        /* FIXME: What WIMG combinations could be sensible for IO?
+         * For now we allow WIMG=010x, but are there others? */
+        /* FIXME: Should we check against registered IO addresses? */
+        if ((ptel & (HPTE_R_W | HPTE_R_I | HPTE_R_M)) != HPTE_R_I) {
+            return H_PARAMETER;
+        }
+    }
+
+    pteh &= ~0x60ULL;
+
+    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
+        return H_PARAMETER;
+    }
+    if (likely((flags & H_EXACT) == 0)) {
+        pte_index &= ~7ULL;
+        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+        for (i = 0; ; ++i) {
+            if (i == 8) {
+                return H_PTEG_FULL;
+            }
+            if ((ldq_p(hpte) & HPTE_V_VALID) == 0) {
+                break;
+            }
+            hpte += HASH_PTE_SIZE_64;
+        }
+    } else {
+        i = 0;
+        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+        if (ldq_p(hpte) & HPTE_V_VALID) {
+            return H_PTEG_FULL;
+        }
+    }
+    stq_p(hpte + (HASH_PTE_SIZE_64/2), ptel);
+    /* eieio();  FIXME: need some sort of barrier for smp? */
+    stq_p(hpte, pteh);
+
+    args[0] = pte_index + i;
+    return H_SUCCESS;
+}
+
+enum {
+    REMOVE_SUCCESS = 0,
+    REMOVE_NOT_FOUND = 1,
+    REMOVE_PARM = 2,
+    REMOVE_HW = 3,
+};
+
+static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
+                                target_ulong avpn,
+                                target_ulong flags,
+                                target_ulong *vp, target_ulong *rp)
+{
+    uint8_t *hpte;
+    target_ulong v, r, rb;
+
+    if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
+        return REMOVE_PARM;
+    }
+
+    hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
+
+    v = ldq_p(hpte);
+    r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
+
+    if ((v & HPTE_V_VALID) == 0 ||
+        ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
+        ((flags & H_ANDCOND) && (v & avpn) != 0)) {
+        return REMOVE_NOT_FOUND;
+    }
+    *vp = v;
+    *rp = r;
+    stq_p(hpte, 0);
+    rb = compute_tlbie_rb(v, r, ptex);
+    ppc_tlb_invalidate_one(env, rb);
+    return REMOVE_SUCCESS;
+}
+
+static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                             target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong flags = args[0];
+    target_ulong pte_index = args[1];
+    target_ulong avpn = args[2];
+    int ret;
+
+    ret = remove_hpte(env, pte_index, avpn, flags,
+                      &args[0], &args[1]);
+
+    switch (ret) {
+    case REMOVE_SUCCESS:
+        return H_SUCCESS;
+
+    case REMOVE_NOT_FOUND:
+        return H_NOT_FOUND;
+
+    case REMOVE_PARM:
+        return H_PARAMETER;
+
+    case REMOVE_HW:
+        return H_HARDWARE;
+    }
+
+    assert(0);
+}
+
+#define H_BULK_REMOVE_TYPE             0xc000000000000000ULL
+#define   H_BULK_REMOVE_REQUEST        0x4000000000000000ULL
+#define   H_BULK_REMOVE_RESPONSE       0x8000000000000000ULL
+#define   H_BULK_REMOVE_END            0xc000000000000000ULL
+#define H_BULK_REMOVE_CODE             0x3000000000000000ULL
+#define   H_BULK_REMOVE_SUCCESS        0x0000000000000000ULL
+#define   H_BULK_REMOVE_NOT_FOUND      0x1000000000000000ULL
+#define   H_BULK_REMOVE_PARM           0x2000000000000000ULL
+#define   H_BULK_REMOVE_HW             0x3000000000000000ULL
+#define H_BULK_REMOVE_RC               0x0c00000000000000ULL
+#define H_BULK_REMOVE_FLAGS            0x0300000000000000ULL
+#define   H_BULK_REMOVE_ABSOLUTE       0x0000000000000000ULL
+#define   H_BULK_REMOVE_ANDCOND        0x0100000000000000ULL
+#define   H_BULK_REMOVE_AVPN           0x0200000000000000ULL
+#define H_BULK_REMOVE_PTEX             0x00ffffffffffffffULL
+
+#define H_BULK_REMOVE_MAX_BATCH        4
+
+static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                  target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    int i;
+
+    for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
+        target_ulong *tsh = &args[i*2];
+        target_ulong tsl = args[i*2 + 1];
+        target_ulong v, r, ret;
+
+        if ((*tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) {
+            break;
+        } else if ((*tsh & H_BULK_REMOVE_TYPE) != H_BULK_REMOVE_REQUEST) {
+            return H_PARAMETER;
+        }
+
+        *tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS;
+        *tsh |= H_BULK_REMOVE_RESPONSE;
+
+        if ((*tsh & H_BULK_REMOVE_ANDCOND) && (*tsh & H_BULK_REMOVE_AVPN)) {
+            *tsh |= H_BULK_REMOVE_PARM;
+            return H_PARAMETER;
+        }
+
+        ret = remove_hpte(env, *tsh & H_BULK_REMOVE_PTEX, tsl,
+                          (*tsh & H_BULK_REMOVE_FLAGS) >> 26,
+                          &v, &r);
+
+        *tsh |= ret << 60;
+
+        switch (ret) {
+        case REMOVE_SUCCESS:
+            *tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43;
+            break;
+
+        case REMOVE_PARM:
+            return H_PARAMETER;
+
+        case REMOVE_HW:
+            return H_HARDWARE;
+        }
+    }
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                              target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong flags = args[0];
+    target_ulong pte_index = args[1];
+    target_ulong avpn = args[2];
+    uint8_t *hpte;
+    target_ulong v, r, rb;
+
+    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
+        return H_PARAMETER;
+    }
+
+    hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+
+    v = ldq_p(hpte);
+    r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
+
+    if ((v & HPTE_V_VALID) == 0 ||
+        ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
+        return H_NOT_FOUND;
+    }
+
+    r &= ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
+           HPTE_R_KEY_HI | HPTE_R_KEY_LO);
+    r |= (flags << 55) & HPTE_R_PP0;
+    r |= (flags << 48) & HPTE_R_KEY_HI;
+    r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
+    rb = compute_tlbie_rb(v, r, pte_index);
+    stq_p(hpte, v & ~HPTE_V_VALID);
+    ppc_tlb_invalidate_one(env, rb);
+    stq_p(hpte + (HASH_PTE_SIZE_64/2), r);
+    /* Don't need a memory barrier, due to qemu's global lock */
+    stq_p(hpte, v);
+    return H_SUCCESS;
+}
+
+static target_ulong h_read(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong flags = args[0];
+    target_ulong pte_index = args[1];
+    uint8_t *hpte;
+    int i, ridx, n_entries = 1;
+
+    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
+        return H_PARAMETER;
+    }
+
+    if (flags & H_READ_4) {
+        /* Clear the two low order bits */
+        pte_index &= ~(3ULL);
+        n_entries = 4;
+    }
+
+    hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+
+    for (i = 0, ridx = 0; i < n_entries; i++) {
+        args[ridx++] = ldq_p(hpte);
+        args[ridx++] = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
+        hpte += HASH_PTE_SIZE_64;
+    }
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                               target_ulong opcode, target_ulong *args)
+{
+    /* FIXME: actually implement this */
+    return H_HARDWARE;
+}
+
+#define FLAGS_REGISTER_VPA         0x0000200000000000ULL
+#define FLAGS_REGISTER_DTL         0x0000400000000000ULL
+#define FLAGS_REGISTER_SLBSHADOW   0x0000600000000000ULL
+#define FLAGS_DEREGISTER_VPA       0x0000a00000000000ULL
+#define FLAGS_DEREGISTER_DTL       0x0000c00000000000ULL
+#define FLAGS_DEREGISTER_SLBSHADOW 0x0000e00000000000ULL
+
+#define VPA_MIN_SIZE           640
+#define VPA_SIZE_OFFSET        0x4
+#define VPA_SHARED_PROC_OFFSET 0x9
+#define VPA_SHARED_PROC_VAL    0x2
+
+static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa)
+{
+    uint16_t size;
+    uint8_t tmp;
+
+    if (vpa == 0) {
+        hcall_dprintf("Can't cope with registering a VPA at logical 0\n");
+        return H_HARDWARE;
+    }
+
+    if (vpa % env->dcache_line_size) {
+        return H_PARAMETER;
+    }
+    /* FIXME: bounds check the address */
+
+    size = lduw_be_phys(vpa + 0x4);
+
+    if (size < VPA_MIN_SIZE) {
+        return H_PARAMETER;
+    }
+
+    /* VPA is not allowed to cross a page boundary */
+    if ((vpa / 4096) != ((vpa + size - 1) / 4096)) {
+        return H_PARAMETER;
+    }
+
+    env->vpa_addr = vpa;
+
+    tmp = ldub_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET);
+    tmp |= VPA_SHARED_PROC_VAL;
+    stb_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp);
+
+    return H_SUCCESS;
+}
+
+static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa)
+{
+    if (env->slb_shadow_addr) {
+        return H_RESOURCE;
+    }
+
+    if (env->dtl_addr) {
+        return H_RESOURCE;
+    }
+
+    env->vpa_addr = 0;
+    return H_SUCCESS;
+}
+
+static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr)
+{
+    uint32_t size;
+
+    if (addr == 0) {
+        hcall_dprintf("Can't cope with SLB shadow at logical 0\n");
+        return H_HARDWARE;
+    }
+
+    size = ldl_be_phys(addr + 0x4);
+    if (size < 0x8) {
+        return H_PARAMETER;
+    }
+
+    if ((addr / 4096) != ((addr + size - 1) / 4096)) {
+        return H_PARAMETER;
+    }
+
+    if (!env->vpa_addr) {
+        return H_RESOURCE;
+    }
+
+    env->slb_shadow_addr = addr;
+    env->slb_shadow_size = size;
+
+    return H_SUCCESS;
+}
+
+static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr)
+{
+    env->slb_shadow_addr = 0;
+    env->slb_shadow_size = 0;
+    return H_SUCCESS;
+}
+
+static target_ulong register_dtl(CPUPPCState *env, target_ulong addr)
+{
+    uint32_t size;
+
+    if (addr == 0) {
+        hcall_dprintf("Can't cope with DTL at logical 0\n");
+        return H_HARDWARE;
+    }
+
+    size = ldl_be_phys(addr + 0x4);
+
+    if (size < 48) {
+        return H_PARAMETER;
+    }
+
+    if (!env->vpa_addr) {
+        return H_RESOURCE;
+    }
+
+    env->dtl_addr = addr;
+    env->dtl_size = size;
+
+    return H_SUCCESS;
+}
+
+static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr)
+{
+    env->dtl_addr = 0;
+    env->dtl_size = 0;
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                   target_ulong opcode, target_ulong *args)
+{
+    target_ulong flags = args[0];
+    target_ulong procno = args[1];
+    target_ulong vpa = args[2];
+    target_ulong ret = H_PARAMETER;
+    CPUPPCState *tenv;
+    CPUState *tcpu;
+
+    tcpu = qemu_get_cpu(procno);
+    if (!tcpu) {
+        return H_PARAMETER;
+    }
+    tenv = tcpu->env_ptr;
+
+    switch (flags) {
+    case FLAGS_REGISTER_VPA:
+        ret = register_vpa(tenv, vpa);
+        break;
+
+    case FLAGS_DEREGISTER_VPA:
+        ret = deregister_vpa(tenv, vpa);
+        break;
+
+    case FLAGS_REGISTER_SLBSHADOW:
+        ret = register_slb_shadow(tenv, vpa);
+        break;
+
+    case FLAGS_DEREGISTER_SLBSHADOW:
+        ret = deregister_slb_shadow(tenv, vpa);
+        break;
+
+    case FLAGS_REGISTER_DTL:
+        ret = register_dtl(tenv, vpa);
+        break;
+
+    case FLAGS_DEREGISTER_DTL:
+        ret = deregister_dtl(tenv, vpa);
+        break;
+    }
+
+    return ret;
+}
+
+static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
+
+    env->msr |= (1ULL << MSR_EE);
+    hreg_compute_hflags(env);
+    if (!cpu_has_work(cs)) {
+        env->halted = 1;
+        env->exception_index = EXCP_HLT;
+        cs->exit_request = 1;
+    }
+    return H_SUCCESS;
+}
+
+static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    target_ulong rtas_r3 = args[0];
+    uint32_t token = ldl_be_phys(rtas_r3);
+    uint32_t nargs = ldl_be_phys(rtas_r3 + 4);
+    uint32_t nret = ldl_be_phys(rtas_r3 + 8);
+
+    return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12,
+                           nret, rtas_r3 + 12 + 4*nargs);
+}
+
+static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                   target_ulong opcode, target_ulong *args)
+{
+    target_ulong size = args[0];
+    target_ulong addr = args[1];
+
+    switch (size) {
+    case 1:
+        args[0] = ldub_phys(addr);
+        return H_SUCCESS;
+    case 2:
+        args[0] = lduw_phys(addr);
+        return H_SUCCESS;
+    case 4:
+        args[0] = ldl_phys(addr);
+        return H_SUCCESS;
+    case 8:
+        args[0] = ldq_phys(addr);
+        return H_SUCCESS;
+    }
+    return H_PARAMETER;
+}
+
+static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                    target_ulong opcode, target_ulong *args)
+{
+    target_ulong size = args[0];
+    target_ulong addr = args[1];
+    target_ulong val  = args[2];
+
+    switch (size) {
+    case 1:
+        stb_phys(addr, val);
+        return H_SUCCESS;
+    case 2:
+        stw_phys(addr, val);
+        return H_SUCCESS;
+    case 4:
+        stl_phys(addr, val);
+        return H_SUCCESS;
+    case 8:
+        stq_phys(addr, val);
+        return H_SUCCESS;
+    }
+    return H_PARAMETER;
+}
+
+static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                    target_ulong opcode, target_ulong *args)
+{
+    target_ulong dst   = args[0]; /* Destination address */
+    target_ulong src   = args[1]; /* Source address */
+    target_ulong esize = args[2]; /* Element size (0=1,1=2,2=4,3=8) */
+    target_ulong count = args[3]; /* Element count */
+    target_ulong op    = args[4]; /* 0 = copy, 1 = invert */
+    uint64_t tmp;
+    unsigned int mask = (1 << esize) - 1;
+    int step = 1 << esize;
+
+    if (count > 0x80000000) {
+        return H_PARAMETER;
+    }
+
+    if ((dst & mask) || (src & mask) || (op > 1)) {
+        return H_PARAMETER;
+    }
+
+    if (dst >= src && dst < (src + (count << esize))) {
+            dst = dst + ((count - 1) << esize);
+            src = src + ((count - 1) << esize);
+            step = -step;
+    }
+
+    while (count--) {
+        switch (esize) {
+        case 0:
+            tmp = ldub_phys(src);
+            break;
+        case 1:
+            tmp = lduw_phys(src);
+            break;
+        case 2:
+            tmp = ldl_phys(src);
+            break;
+        case 3:
+            tmp = ldq_phys(src);
+            break;
+        default:
+            return H_PARAMETER;
+        }
+        if (op == 1) {
+            tmp = ~tmp;
+        }
+        switch (esize) {
+        case 0:
+            stb_phys(dst, tmp);
+            break;
+        case 1:
+            stw_phys(dst, tmp);
+            break;
+        case 2:
+            stl_phys(dst, tmp);
+            break;
+        case 3:
+            stq_phys(dst, tmp);
+            break;
+        }
+        dst = dst + step;
+        src = src + step;
+    }
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                   target_ulong opcode, target_ulong *args)
+{
+    /* Nothing to do on emulation, KVM will trap this in the kernel */
+    return H_SUCCESS;
+}
+
+static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                   target_ulong opcode, target_ulong *args)
+{
+    /* Nothing to do on emulation, KVM will trap this in the kernel */
+    return H_SUCCESS;
+}
+
+static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
+static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
+
+void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
+{
+    spapr_hcall_fn *slot;
+
+    if (opcode <= MAX_HCALL_OPCODE) {
+        assert((opcode & 0x3) == 0);
+
+        slot = &papr_hypercall_table[opcode / 4];
+    } else {
+        assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
+
+        slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
+    }
+
+    assert(!(*slot));
+    *slot = fn;
+}
+
+target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
+                             target_ulong *args)
+{
+    if ((opcode <= MAX_HCALL_OPCODE)
+        && ((opcode & 0x3) == 0)) {
+        spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
+
+        if (fn) {
+            return fn(cpu, spapr, opcode, args);
+        }
+    } else if ((opcode >= KVMPPC_HCALL_BASE) &&
+               (opcode <= KVMPPC_HCALL_MAX)) {
+        spapr_hcall_fn fn = kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
+
+        if (fn) {
+            return fn(cpu, spapr, opcode, args);
+        }
+    }
+
+    hcall_dprintf("Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode);
+    return H_FUNCTION;
+}
+
+static void hypercall_register_types(void)
+{
+    /* hcall-pft */
+    spapr_register_hypercall(H_ENTER, h_enter);
+    spapr_register_hypercall(H_REMOVE, h_remove);
+    spapr_register_hypercall(H_PROTECT, h_protect);
+    spapr_register_hypercall(H_READ, h_read);
+
+    /* hcall-bulk */
+    spapr_register_hypercall(H_BULK_REMOVE, h_bulk_remove);
+
+    /* hcall-dabr */
+    spapr_register_hypercall(H_SET_DABR, h_set_dabr);
+
+    /* hcall-splpar */
+    spapr_register_hypercall(H_REGISTER_VPA, h_register_vpa);
+    spapr_register_hypercall(H_CEDE, h_cede);
+
+    /* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate
+     * here between the "CI" and the "CACHE" variants, they will use whatever
+     * mapping attributes qemu is using. When using KVM, the kernel will
+     * enforce the attributes more strongly
+     */
+    spapr_register_hypercall(H_LOGICAL_CI_LOAD, h_logical_load);
+    spapr_register_hypercall(H_LOGICAL_CI_STORE, h_logical_store);
+    spapr_register_hypercall(H_LOGICAL_CACHE_LOAD, h_logical_load);
+    spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store);
+    spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi);
+    spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
+    spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP, h_logical_memop);
+
+    /* qemu/KVM-PPC specific hcalls */
+    spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
+}
+
+type_init(hypercall_register_types)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
new file mode 100644 (file)
index 0000000..8d500bf
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * QEMU sPAPR IOMMU (TCE) code
+ *
+ * Copyright (c) 2010 David Gibson, IBM Corporation <dwg@au1.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw/hw.h"
+#include "sysemu/kvm.h"
+#include "hw/qdev.h"
+#include "kvm_ppc.h"
+#include "sysemu/dma.h"
+#include "exec/address-spaces.h"
+
+#include "hw/spapr.h"
+
+#include <libfdt.h>
+
+/* #define DEBUG_TCE */
+
+enum sPAPRTCEAccess {
+    SPAPR_TCE_FAULT = 0,
+    SPAPR_TCE_RO = 1,
+    SPAPR_TCE_WO = 2,
+    SPAPR_TCE_RW = 3,
+};
+
+typedef struct sPAPRTCETable sPAPRTCETable;
+
+struct sPAPRTCETable {
+    DMAContext dma;
+    uint32_t liobn;
+    uint32_t window_size;
+    sPAPRTCE *table;
+    bool bypass;
+    int fd;
+    QLIST_ENTRY(sPAPRTCETable) list;
+};
+
+
+QLIST_HEAD(spapr_tce_tables, sPAPRTCETable) spapr_tce_tables;
+
+static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
+{
+    sPAPRTCETable *tcet;
+
+    QLIST_FOREACH(tcet, &spapr_tce_tables, list) {
+        if (tcet->liobn == liobn) {
+            return tcet;
+        }
+    }
+
+    return NULL;
+}
+
+static int spapr_tce_translate(DMAContext *dma,
+                               dma_addr_t addr,
+                               hwaddr *paddr,
+                               hwaddr *len,
+                               DMADirection dir)
+{
+    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+    enum sPAPRTCEAccess access = (dir == DMA_DIRECTION_FROM_DEVICE)
+        ? SPAPR_TCE_WO : SPAPR_TCE_RO;
+    uint64_t tce;
+
+#ifdef DEBUG_TCE
+    fprintf(stderr, "spapr_tce_translate liobn=0x%" PRIx32 " addr=0x"
+            DMA_ADDR_FMT "\n", tcet->liobn, addr);
+#endif
+
+    if (tcet->bypass) {
+        *paddr = addr;
+        *len = (hwaddr)-1;
+        return 0;
+    }
+
+    /* Check if we are in bound */
+    if (addr >= tcet->window_size) {
+#ifdef DEBUG_TCE
+        fprintf(stderr, "spapr_tce_translate out of bounds\n");
+#endif
+        return -EFAULT;
+    }
+
+    tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT].tce;
+
+    /* Check TCE */
+    if (!(tce & access)) {
+        return -EPERM;
+    }
+
+    /* How much til end of page ? */
+    *len = ((~addr) & SPAPR_TCE_PAGE_MASK) + 1;
+
+    /* Translate */
+    *paddr = (tce & ~SPAPR_TCE_PAGE_MASK) |
+        (addr & SPAPR_TCE_PAGE_MASK);
+
+#ifdef DEBUG_TCE
+    fprintf(stderr, " ->  *paddr=0x" TARGET_FMT_plx ", *len=0x"
+            TARGET_FMT_plx "\n", *paddr, *len);
+#endif
+
+    return 0;
+}
+
+DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size)
+{
+    sPAPRTCETable *tcet;
+
+    if (spapr_tce_find_by_liobn(liobn)) {
+        fprintf(stderr, "Attempted to create TCE table with duplicate"
+                " LIOBN 0x%x\n", liobn);
+        return NULL;
+    }
+
+    if (!window_size) {
+        return NULL;
+    }
+
+    tcet = g_malloc0(sizeof(*tcet));
+    dma_context_init(&tcet->dma, &address_space_memory, spapr_tce_translate, NULL, NULL);
+
+    tcet->liobn = liobn;
+    tcet->window_size = window_size;
+
+    if (kvm_enabled()) {
+        tcet->table = kvmppc_create_spapr_tce(liobn,
+                                              window_size,
+                                              &tcet->fd);
+    }
+
+    if (!tcet->table) {
+        size_t table_size = (window_size >> SPAPR_TCE_PAGE_SHIFT)
+            * sizeof(sPAPRTCE);
+        tcet->table = g_malloc0(table_size);
+    }
+
+#ifdef DEBUG_TCE
+    fprintf(stderr, "spapr_iommu: New TCE table, liobn=0x%x, context @ %p, "
+            "table @ %p, fd=%d\n", liobn, &tcet->dma, tcet->table, tcet->fd);
+#endif
+
+    QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
+
+    return &tcet->dma;
+}
+
+void spapr_tce_free(DMAContext *dma)
+{
+
+    if (dma) {
+        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+
+        QLIST_REMOVE(tcet, list);
+
+        if (!kvm_enabled() ||
+            (kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
+                                     tcet->window_size) != 0)) {
+            g_free(tcet->table);
+        }
+
+        g_free(tcet);
+    }
+}
+
+void spapr_tce_set_bypass(DMAContext *dma, bool bypass)
+{
+    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+
+    tcet->bypass = bypass;
+}
+
+void spapr_tce_reset(DMAContext *dma)
+{
+    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+    size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
+        * sizeof(sPAPRTCE);
+
+    tcet->bypass = false;
+    memset(tcet->table, 0, table_size);
+}
+
+static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
+                                target_ulong tce)
+{
+    sPAPRTCE *tcep;
+
+    if (ioba >= tcet->window_size) {
+        hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
+                      TARGET_FMT_lx "\n", ioba);
+        return H_PARAMETER;
+    }
+
+    tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT);
+    tcep->tce = tce;
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                              target_ulong opcode, target_ulong *args)
+{
+    target_ulong liobn = args[0];
+    target_ulong ioba = args[1];
+    target_ulong tce = args[2];
+    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+
+    if (liobn & 0xFFFFFFFF00000000ULL) {
+        hcall_dprintf("spapr_vio_put_tce on out-of-boundsw LIOBN "
+                      TARGET_FMT_lx "\n", liobn);
+        return H_PARAMETER;
+    }
+
+    ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
+
+    if (tcet) {
+        return put_tce_emu(tcet, ioba, tce);
+    }
+#ifdef DEBUG_TCE
+    fprintf(stderr, "%s on liobn=" TARGET_FMT_lx /*%s*/
+            "  ioba 0x" TARGET_FMT_lx "  TCE 0x" TARGET_FMT_lx "\n",
+            __func__, liobn, /*dev->qdev.id, */ioba, tce);
+#endif
+
+    return H_PARAMETER;
+}
+
+void spapr_iommu_init(void)
+{
+    QLIST_INIT(&spapr_tce_tables);
+
+    /* hcall-tce */
+    spapr_register_hypercall(H_PUT_TCE, h_put_tce);
+}
+
+int spapr_dma_dt(void *fdt, int node_off, const char *propname,
+                 uint32_t liobn, uint64_t window, uint32_t size)
+{
+    uint32_t dma_prop[5];
+    int ret;
+
+    dma_prop[0] = cpu_to_be32(liobn);
+    dma_prop[1] = cpu_to_be32(window >> 32);
+    dma_prop[2] = cpu_to_be32(window & 0xFFFFFFFF);
+    dma_prop[3] = 0; /* window size is 32 bits */
+    dma_prop[4] = cpu_to_be32(size);
+
+    ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2);
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2);
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = fdt_setprop(fdt, node_off, propname, dma_prop, sizeof(dma_prop));
+    if (ret < 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
+                      DMAContext *iommu)
+{
+    if (!iommu) {
+        return 0;
+    }
+
+    if (iommu->translate == spapr_tce_translate) {
+        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, iommu);
+        return spapr_dma_dt(fdt, node_off, propname,
+                tcet->liobn, 0, tcet->window_size);
+    }
+
+    return -1;
+}
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
new file mode 100644 (file)
index 0000000..5ec787f
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * Hypercall based emulated RTAS
+ *
+ * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+#include "cpu.h"
+#include "sysemu/sysemu.h"
+#include "char/char.h"
+#include "hw/qdev.h"
+#include "sysemu/device_tree.h"
+
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+
+#include <libfdt.h>
+
+#define TOKEN_BASE      0x2000
+#define TOKEN_MAX       0x100
+
+static void rtas_display_character(sPAPREnvironment *spapr,
+                                   uint32_t token, uint32_t nargs,
+                                   target_ulong args,
+                                   uint32_t nret, target_ulong rets)
+{
+    uint8_t c = rtas_ld(args, 0);
+    VIOsPAPRDevice *sdev = vty_lookup(spapr, 0);
+
+    if (!sdev) {
+        rtas_st(rets, 0, -1);
+    } else {
+        vty_putchars(sdev, &c, sizeof(c));
+        rtas_st(rets, 0, 0);
+    }
+}
+
+static void rtas_get_time_of_day(sPAPREnvironment *spapr,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+    struct tm tm;
+
+    if (nret != 8) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    qemu_get_timedate(&tm, spapr->rtc_offset);
+
+    rtas_st(rets, 0, 0); /* Success */
+    rtas_st(rets, 1, tm.tm_year + 1900);
+    rtas_st(rets, 2, tm.tm_mon + 1);
+    rtas_st(rets, 3, tm.tm_mday);
+    rtas_st(rets, 4, tm.tm_hour);
+    rtas_st(rets, 5, tm.tm_min);
+    rtas_st(rets, 6, tm.tm_sec);
+    rtas_st(rets, 7, 0); /* we don't do nanoseconds */
+}
+
+static void rtas_set_time_of_day(sPAPREnvironment *spapr,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+    struct tm tm;
+
+    tm.tm_year = rtas_ld(args, 0) - 1900;
+    tm.tm_mon = rtas_ld(args, 1) - 1;
+    tm.tm_mday = rtas_ld(args, 2);
+    tm.tm_hour = rtas_ld(args, 3);
+    tm.tm_min = rtas_ld(args, 4);
+    tm.tm_sec = rtas_ld(args, 5);
+
+    /* Just generate a monitor event for the change */
+    rtc_change_mon_event(&tm);
+    spapr->rtc_offset = qemu_timedate_diff(&tm);
+
+    rtas_st(rets, 0, 0); /* Success */
+}
+
+static void rtas_power_off(sPAPREnvironment *spapr,
+                           uint32_t token, uint32_t nargs, target_ulong args,
+                           uint32_t nret, target_ulong rets)
+{
+    if (nargs != 2 || nret != 1) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+    qemu_system_shutdown_request();
+    rtas_st(rets, 0, 0);
+}
+
+static void rtas_system_reboot(sPAPREnvironment *spapr,
+                               uint32_t token, uint32_t nargs,
+                               target_ulong args,
+                               uint32_t nret, target_ulong rets)
+{
+    if (nargs != 0 || nret != 1) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+    qemu_system_reset_request();
+    rtas_st(rets, 0, 0);
+}
+
+static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
+                                         uint32_t token, uint32_t nargs,
+                                         target_ulong args,
+                                         uint32_t nret, target_ulong rets)
+{
+    target_ulong id;
+    CPUPPCState *env;
+    CPUState *cpu;
+
+    if (nargs != 1 || nret != 2) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    id = rtas_ld(args, 0);
+    for (env = first_cpu; env; env = env->next_cpu) {
+        cpu = CPU(ppc_env_get_cpu(env));
+        if (cpu->cpu_index != id) {
+            continue;
+        }
+
+        if (env->halted) {
+            rtas_st(rets, 1, 0);
+        } else {
+            rtas_st(rets, 1, 2);
+        }
+
+        rtas_st(rets, 0, 0);
+        return;
+    }
+
+    /* Didn't find a matching cpu */
+    rtas_st(rets, 0, -3);
+}
+
+static void rtas_start_cpu(sPAPREnvironment *spapr,
+                           uint32_t token, uint32_t nargs,
+                           target_ulong args,
+                           uint32_t nret, target_ulong rets)
+{
+    target_ulong id, start, r3;
+    CPUState *cpu;
+    CPUPPCState *env;
+
+    if (nargs != 3 || nret != 1) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    id = rtas_ld(args, 0);
+    start = rtas_ld(args, 1);
+    r3 = rtas_ld(args, 2);
+
+    for (env = first_cpu; env; env = env->next_cpu) {
+        cpu = CPU(ppc_env_get_cpu(env));
+
+        if (cpu->cpu_index != id) {
+            continue;
+        }
+
+        if (!env->halted) {
+            rtas_st(rets, 0, -1);
+            return;
+        }
+
+        /* This will make sure qemu state is up to date with kvm, and
+         * mark it dirty so our changes get flushed back before the
+         * new cpu enters */
+        kvm_cpu_synchronize_state(env);
+
+        env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
+        env->nip = start;
+        env->gpr[3] = r3;
+        env->halted = 0;
+
+        qemu_cpu_kick(cpu);
+
+        rtas_st(rets, 0, 0);
+        return;
+    }
+
+    /* Didn't find a matching cpu */
+    rtas_st(rets, 0, -3);
+}
+
+static struct rtas_call {
+    const char *name;
+    spapr_rtas_fn fn;
+} rtas_table[TOKEN_MAX];
+
+struct rtas_call *rtas_next = rtas_table;
+
+target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
+                             uint32_t token, uint32_t nargs, target_ulong args,
+                             uint32_t nret, target_ulong rets)
+{
+    if ((token >= TOKEN_BASE)
+        && ((token - TOKEN_BASE) < TOKEN_MAX)) {
+        struct rtas_call *call = rtas_table + (token - TOKEN_BASE);
+
+        if (call->fn) {
+            call->fn(spapr, token, nargs, args, nret, rets);
+            return H_SUCCESS;
+        }
+    }
+
+    /* HACK: Some Linux early debug code uses RTAS display-character,
+     * but assumes the token value is 0xa (which it is on some real
+     * machines) without looking it up in the device tree.  This
+     * special case makes this work */
+    if (token == 0xa) {
+        rtas_display_character(spapr, 0xa, nargs, args, nret, rets);
+        return H_SUCCESS;
+    }
+
+    hcall_dprintf("Unknown RTAS token 0x%x\n", token);
+    rtas_st(rets, 0, -3);
+    return H_PARAMETER;
+}
+
+int spapr_rtas_register(const char *name, spapr_rtas_fn fn)
+{
+    int i;
+
+    for (i = 0; i < (rtas_next - rtas_table); i++) {
+        if (strcmp(name, rtas_table[i].name) == 0) {
+            fprintf(stderr, "RTAS call \"%s\" registered twice\n", name);
+            exit(1);
+        }
+    }
+
+    assert(rtas_next < (rtas_table + TOKEN_MAX));
+
+    rtas_next->name = name;
+    rtas_next->fn = fn;
+
+    return (rtas_next++ - rtas_table) + TOKEN_BASE;
+}
+
+int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
+                                 hwaddr rtas_size)
+{
+    int ret;
+    int i;
+
+    ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n",
+                fdt_strerror(ret));
+        return ret;
+    }
+
+    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "linux,rtas-base",
+                                    rtas_addr);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
+                fdt_strerror(ret));
+        return ret;
+    }
+
+    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
+                                    rtas_addr);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
+                fdt_strerror(ret));
+        return ret;
+    }
+
+    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "rtas-size",
+                                    rtas_size);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't add rtas-size property: %s\n",
+                fdt_strerror(ret));
+        return ret;
+    }
+
+    for (i = 0; i < TOKEN_MAX; i++) {
+        struct rtas_call *call = &rtas_table[i];
+
+        if (!call->name) {
+            continue;
+        }
+
+        ret = qemu_devtree_setprop_cell(fdt, "/rtas", call->name,
+                                        i + TOKEN_BASE);
+        if (ret < 0) {
+            fprintf(stderr, "Couldn't add rtas token for %s: %s\n",
+                    call->name, fdt_strerror(ret));
+            return ret;
+        }
+
+    }
+    return 0;
+}
+
+static void core_rtas_register_types(void)
+{
+    spapr_rtas_register("display-character", rtas_display_character);
+    spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
+    spapr_rtas_register("set-time-of-day", rtas_set_time_of_day);
+    spapr_rtas_register("power-off", rtas_power_off);
+    spapr_rtas_register("system-reboot", rtas_system_reboot);
+    spapr_rtas_register("query-cpu-stopped-state",
+                        rtas_query_cpu_stopped_state);
+    spapr_rtas_register("start-cpu", rtas_start_cpu);
+}
+
+type_init(core_rtas_register_types)
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
new file mode 100644 (file)
index 0000000..6eb3ab5
--- /dev/null
@@ -0,0 +1,649 @@
+/*
+ * QEMU sPAPR VIO code
+ *
+ * Copyright (c) 2010 David Gibson, IBM Corporation <dwg@au1.ibm.com>
+ * Based on the s390 virtio bus code:
+ * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/hw.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "monitor/monitor.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/sysbus.h"
+#include "sysemu/kvm.h"
+#include "sysemu/device_tree.h"
+#include "kvm_ppc.h"
+
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+#include "hw/xics.h"
+
+#ifdef CONFIG_FDT
+#include <libfdt.h>
+#endif /* CONFIG_FDT */
+
+/* #define DEBUG_SPAPR */
+
+#ifdef DEBUG_SPAPR
+#define dprintf(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define dprintf(fmt, ...) \
+    do { } while (0)
+#endif
+
+static Property spapr_vio_props[] = {
+    DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, irq, 0), \
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static const TypeInfo spapr_vio_bus_info = {
+    .name = TYPE_SPAPR_VIO_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(VIOsPAPRBus),
+};
+
+VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
+{
+    BusChild *kid;
+    VIOsPAPRDevice *dev = NULL;
+
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        dev = (VIOsPAPRDevice *)kid->child;
+        if (dev->reg == reg) {
+            return dev;
+        }
+    }
+
+    return NULL;
+}
+
+static char *vio_format_dev_name(VIOsPAPRDevice *dev)
+{
+    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+    char *name;
+
+    /* Device tree style name device@reg */
+    name = g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
+
+    return name;
+}
+
+#ifdef CONFIG_FDT
+static int vio_make_devnode(VIOsPAPRDevice *dev,
+                            void *fdt)
+{
+    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+    int vdevice_off, node_off, ret;
+    char *dt_name;
+
+    vdevice_off = fdt_path_offset(fdt, "/vdevice");
+    if (vdevice_off < 0) {
+        return vdevice_off;
+    }
+
+    dt_name = vio_format_dev_name(dev);
+    node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
+    g_free(dt_name);
+    if (node_off < 0) {
+        return node_off;
+    }
+
+    ret = fdt_setprop_cell(fdt, node_off, "reg", dev->reg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (pc->dt_type) {
+        ret = fdt_setprop_string(fdt, node_off, "device_type",
+                                 pc->dt_type);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    if (pc->dt_compatible) {
+        ret = fdt_setprop_string(fdt, node_off, "compatible",
+                                 pc->dt_compatible);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    if (dev->irq) {
+        uint32_t ints_prop[] = {cpu_to_be32(dev->irq), 0};
+
+        ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
+                          sizeof(ints_prop));
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (pc->devnode) {
+        ret = (pc->devnode)(dev, fdt, node_off);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    return node_off;
+}
+#endif /* CONFIG_FDT */
+
+/*
+ * CRQ handling
+ */
+static target_ulong h_reg_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                              target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    target_ulong queue_addr = args[1];
+    target_ulong queue_len = args[2];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+
+    if (!dev) {
+        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
+        return H_PARAMETER;
+    }
+
+    /* We can't grok a queue size bigger than 256M for now */
+    if (queue_len < 0x1000 || queue_len > 0x10000000) {
+        hcall_dprintf("Queue size too small or too big (0x" TARGET_FMT_lx
+                      ")\n", queue_len);
+        return H_PARAMETER;
+    }
+
+    /* Check queue alignment */
+    if (queue_addr & 0xfff) {
+        hcall_dprintf("Queue not aligned (0x" TARGET_FMT_lx ")\n", queue_addr);
+        return H_PARAMETER;
+    }
+
+    /* Check if device supports CRQs */
+    if (!dev->crq.SendFunc) {
+        hcall_dprintf("Device does not support CRQ\n");
+        return H_NOT_FOUND;
+    }
+
+    /* Already a queue ? */
+    if (dev->crq.qsize) {
+        hcall_dprintf("CRQ already registered\n");
+        return H_RESOURCE;
+    }
+    dev->crq.qladdr = queue_addr;
+    dev->crq.qsize = queue_len;
+    dev->crq.qnext = 0;
+
+    dprintf("CRQ for dev 0x" TARGET_FMT_lx " registered at 0x"
+            TARGET_FMT_lx "/0x" TARGET_FMT_lx "\n",
+            reg, queue_addr, queue_len);
+    return H_SUCCESS;
+}
+
+static target_ulong free_crq(VIOsPAPRDevice *dev)
+{
+    dev->crq.qladdr = 0;
+    dev->crq.qsize = 0;
+    dev->crq.qnext = 0;
+
+    dprintf("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_free_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                               target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+
+    if (!dev) {
+        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
+        return H_PARAMETER;
+    }
+
+    return free_crq(dev);
+}
+
+static target_ulong h_send_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                               target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    target_ulong msg_hi = args[1];
+    target_ulong msg_lo = args[2];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    uint64_t crq_mangle[2];
+
+    if (!dev) {
+        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
+        return H_PARAMETER;
+    }
+    crq_mangle[0] = cpu_to_be64(msg_hi);
+    crq_mangle[1] = cpu_to_be64(msg_lo);
+
+    if (dev->crq.SendFunc) {
+        return dev->crq.SendFunc(dev, (uint8_t *)crq_mangle);
+    }
+
+    return H_HARDWARE;
+}
+
+static target_ulong h_enable_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                 target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+
+    if (!dev) {
+        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
+        return H_PARAMETER;
+    }
+
+    return 0;
+}
+
+/* Returns negative error, 0 success, or positive: queue full */
+int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
+{
+    int rc;
+    uint8_t byte;
+
+    if (!dev->crq.qsize) {
+        fprintf(stderr, "spapr_vio_send_creq on uninitialized queue\n");
+        return -1;
+    }
+
+    /* Maybe do a fast path for KVM just writing to the pages */
+    rc = spapr_vio_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
+    if (rc) {
+        return rc;
+    }
+    if (byte != 0) {
+        return 1;
+    }
+
+    rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
+                             &crq[8], 8);
+    if (rc) {
+        return rc;
+    }
+
+    kvmppc_eieio();
+
+    rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext, crq, 8);
+    if (rc) {
+        return rc;
+    }
+
+    dev->crq.qnext = (dev->crq.qnext + 16) % dev->crq.qsize;
+
+    if (dev->signal_state & 1) {
+        qemu_irq_pulse(spapr_vio_qirq(dev));
+    }
+
+    return 0;
+}
+
+/* "quiesce" handling */
+
+static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
+{
+    if (dev->dma) {
+        spapr_tce_reset(dev->dma);
+    }
+    free_crq(dev);
+}
+
+static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
+                                uint32_t nargs, target_ulong args,
+                                uint32_t nret, target_ulong rets)
+{
+    VIOsPAPRBus *bus = spapr->vio_bus;
+    VIOsPAPRDevice *dev;
+    uint32_t unit, enable;
+
+    if (nargs != 2) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+    unit = rtas_ld(args, 0);
+    enable = rtas_ld(args, 1);
+    dev = spapr_vio_find_by_reg(bus, unit);
+    if (!dev) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    if (!dev->dma) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    spapr_tce_set_bypass(dev->dma, !!enable);
+
+    rtas_st(rets, 0, 0);
+}
+
+static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
+                         uint32_t nargs, target_ulong args,
+                         uint32_t nret, target_ulong rets)
+{
+    VIOsPAPRBus *bus = spapr->vio_bus;
+    BusChild *kid;
+    VIOsPAPRDevice *dev = NULL;
+
+    if (nargs != 0) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        dev = (VIOsPAPRDevice *)kid->child;
+        spapr_vio_quiesce_one(dev);
+    }
+
+    rtas_st(rets, 0, 0);
+}
+
+static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
+{
+    VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
+    BusChild *kid;
+    VIOsPAPRDevice *other;
+
+    /*
+     * Check for a device other than the given one which is already
+     * using the requested address. We have to open code this because
+     * the given dev might already be in the list.
+     */
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child);
+
+        if (other != dev && other->reg == dev->reg) {
+            return other;
+        }
+    }
+
+    return 0;
+}
+
+static void spapr_vio_busdev_reset(DeviceState *qdev)
+{
+    VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+
+    /* Shut down the request queue and TCEs if necessary */
+    spapr_vio_quiesce_one(dev);
+
+    dev->signal_state = 0;
+
+    if (pc->reset) {
+        pc->reset(dev);
+    }
+}
+
+static int spapr_vio_busdev_init(DeviceState *qdev)
+{
+    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
+    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+    char *id;
+
+    if (dev->reg != -1) {
+        /*
+         * Explicitly assigned address, just verify that no-one else
+         * is using it.  other mechanism). We have to open code this
+         * rather than using spapr_vio_find_by_reg() because sdev
+         * itself is already in the list.
+         */
+        VIOsPAPRDevice *other = reg_conflict(dev);
+
+        if (other) {
+            fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
+                    object_get_typename(OBJECT(qdev)),
+                    object_get_typename(OBJECT(&other->qdev)),
+                    dev->reg);
+            return -1;
+        }
+    } else {
+        /* Need to assign an address */
+        VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
+
+        do {
+            dev->reg = bus->next_reg++;
+        } while (reg_conflict(dev));
+    }
+
+    /* Don't overwrite ids assigned on the command line */
+    if (!dev->qdev.id) {
+        id = vio_format_dev_name(dev);
+        dev->qdev.id = id;
+    }
+
+    dev->irq = spapr_allocate_msi(dev->irq);
+    if (!dev->irq) {
+        return -1;
+    }
+
+    if (pc->rtce_window_size) {
+        uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
+        dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
+    }
+
+    return pc->init(dev);
+}
+
+static target_ulong h_vio_signal(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                 target_ulong opcode,
+                                 target_ulong *args)
+{
+    target_ulong reg = args[0];
+    target_ulong mode = args[1];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    VIOsPAPRDeviceClass *pc;
+
+    if (!dev) {
+        return H_PARAMETER;
+    }
+
+    pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+
+    if (mode & ~pc->signal_mask) {
+        return H_PARAMETER;
+    }
+
+    dev->signal_state = mode;
+
+    return H_SUCCESS;
+}
+
+VIOsPAPRBus *spapr_vio_bus_init(void)
+{
+    VIOsPAPRBus *bus;
+    BusState *qbus;
+    DeviceState *dev;
+
+    /* Create bridge device */
+    dev = qdev_create(NULL, "spapr-vio-bridge");
+    qdev_init_nofail(dev);
+
+    /* Create bus on bridge device */
+
+    qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
+    bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
+    bus->next_reg = 0x71000000;
+
+    /* hcall-vio */
+    spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
+
+    /* hcall-crq */
+    spapr_register_hypercall(H_REG_CRQ, h_reg_crq);
+    spapr_register_hypercall(H_FREE_CRQ, h_free_crq);
+    spapr_register_hypercall(H_SEND_CRQ, h_send_crq);
+    spapr_register_hypercall(H_ENABLE_CRQ, h_enable_crq);
+
+    /* RTAS calls */
+    spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
+    spapr_rtas_register("quiesce", rtas_quiesce);
+
+    return bus;
+}
+
+/* Represents sPAPR hcall VIO devices */
+
+static int spapr_vio_bridge_init(SysBusDevice *dev)
+{
+    /* nothing */
+    return 0;
+}
+
+static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = spapr_vio_bridge_init;
+    dc->no_user = 1;
+}
+
+static const TypeInfo spapr_vio_bridge_info = {
+    .name          = "spapr-vio-bridge",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SysBusDevice),
+    .class_init    = spapr_vio_bridge_class_init,
+};
+
+static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *k = DEVICE_CLASS(klass);
+    k->init = spapr_vio_busdev_init;
+    k->reset = spapr_vio_busdev_reset;
+    k->bus_type = TYPE_SPAPR_VIO_BUS;
+    k->props = spapr_vio_props;
+}
+
+static const TypeInfo spapr_vio_type_info = {
+    .name = TYPE_VIO_SPAPR_DEVICE,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(VIOsPAPRDevice),
+    .abstract = true,
+    .class_size = sizeof(VIOsPAPRDeviceClass),
+    .class_init = vio_spapr_device_class_init,
+};
+
+static void spapr_vio_register_types(void)
+{
+    type_register_static(&spapr_vio_bus_info);
+    type_register_static(&spapr_vio_bridge_info);
+    type_register_static(&spapr_vio_type_info);
+}
+
+type_init(spapr_vio_register_types)
+
+#ifdef CONFIG_FDT
+static int compare_reg(const void *p1, const void *p2)
+{
+    VIOsPAPRDevice const *dev1, *dev2;
+
+    dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
+    dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
+
+    if (dev1->reg < dev2->reg) {
+        return -1;
+    }
+    if (dev1->reg == dev2->reg) {
+        return 0;
+    }
+
+    /* dev1->reg > dev2->reg */
+    return 1;
+}
+
+int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
+{
+    DeviceState *qdev, **qdevs;
+    BusChild *kid;
+    int i, num, ret = 0;
+
+    /* Count qdevs on the bus list */
+    num = 0;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        num++;
+    }
+
+    /* Copy out into an array of pointers */
+    qdevs = g_malloc(sizeof(qdev) * num);
+    num = 0;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        qdevs[num++] = kid->child;
+    }
+
+    /* Sort the array */
+    qsort(qdevs, num, sizeof(qdev), compare_reg);
+
+    /* Hack alert. Give the devices to libfdt in reverse order, we happen
+     * to know that will mean they are in forward order in the tree. */
+    for (i = num - 1; i >= 0; i--) {
+        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
+
+        ret = vio_make_devnode(dev, fdt);
+
+        if (ret < 0) {
+            goto out;
+        }
+    }
+
+    ret = 0;
+out:
+    free(qdevs);
+
+    return ret;
+}
+
+int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
+{
+    VIOsPAPRDevice *dev;
+    char *name, *path;
+    int ret, offset;
+
+    dev = spapr_vty_get_default(bus);
+    if (!dev)
+        return 0;
+
+    offset = fdt_path_offset(fdt, "/chosen");
+    if (offset < 0) {
+        return offset;
+    }
+
+    name = vio_format_dev_name(dev);
+    path = g_strdup_printf("/vdevice/%s", name);
+
+    ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
+
+    g_free(name);
+    g_free(path);
+
+    return ret;
+}
+#endif /* CONFIG_FDT */
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
new file mode 100644 (file)
index 0000000..41eab16
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * Model of Xilinx Virtex5 ML507 PPC-440 refdesign.
+ *
+ * Copyright (c) 2010 Edgar E. Iglesias.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/serial.h"
+#include "hw/flash.h"
+#include "sysemu/sysemu.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "sysemu/device_tree.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+
+#include "hw/ppc.h"
+#include "hw/ppc4xx.h"
+#include "hw/ppc405.h"
+
+#include "sysemu/blockdev.h"
+#include "hw/xilinx.h"
+
+#define EPAPR_MAGIC    (0x45504150)
+#define FLASH_SIZE     (16 * 1024 * 1024)
+
+static struct boot_info
+{
+    uint32_t bootstrap_pc;
+    uint32_t cmdline;
+    uint32_t fdt;
+    uint32_t ima_size;
+    void *vfdt;
+} boot_info;
+
+/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
+                                     target_ulong va,
+                                     hwaddr pa)
+{
+    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
+
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 1 << 31; /* up to 0x80000000  */
+    tlb->EPN = va & TARGET_PAGE_MASK;
+    tlb->RPN = pa & TARGET_PAGE_MASK;
+    tlb->PID = 0;
+
+    tlb = &env->tlb.tlbe[1];
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 1 << 31; /* up to 0xffffffff  */
+    tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
+    tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
+    tlb->PID = 0;
+}
+
+static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
+                                      int do_init,
+                                      const char *cpu_model,
+                                      uint32_t sysclk)
+{
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    qemu_irq *irqs;
+
+    cpu = cpu_ppc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to initialize CPU!\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    ppc_booke_timers_init(cpu, sysclk, 0/* no flags */);
+
+    ppc_dcr_init(env, NULL, NULL);
+
+    /* interrupt controller */
+    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+    ppcuic_init(env, irqs, 0x0C0, 0, 1);
+    return cpu;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    struct boot_info *bi = env->load_info;
+
+    cpu_reset(CPU(cpu));
+    /* Linux Kernel Parameters (passing device tree):
+       *   r3: pointer to the fdt
+       *   r4: 0
+       *   r5: 0
+       *   r6: epapr magic
+       *   r7: size of IMA in bytes
+       *   r8: 0
+       *   r9: 0
+    */
+    env->gpr[1] = (16<<20) - 8;
+    /* Provide a device-tree.  */
+    env->gpr[3] = bi->fdt;
+    env->nip = bi->bootstrap_pc;
+
+    /* Create a mapping for the kernel.  */
+    mmubooke_create_initial_mapping(env, 0, 0);
+    env->gpr[6] = tswap32(EPAPR_MAGIC);
+    env->gpr[7] = bi->ima_size;
+}
+
+#define BINARY_DEVICE_TREE_FILE "virtex-ml507.dtb"
+static int xilinx_load_device_tree(hwaddr addr,
+                                      uint32_t ramsize,
+                                      hwaddr initrd_base,
+                                      hwaddr initrd_size,
+                                      const char *kernel_cmdline)
+{
+    char *path;
+    int fdt_size;
+#ifdef CONFIG_FDT
+    void *fdt;
+    int r;
+
+    /* Try the local "ppc.dtb" override.  */
+    fdt = load_device_tree("ppc.dtb", &fdt_size);
+    if (!fdt) {
+        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
+        if (path) {
+            fdt = load_device_tree(path, &fdt_size);
+            g_free(path);
+        }
+        if (!fdt) {
+            return 0;
+        }
+    }
+
+    r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
+    if (r < 0)
+        fprintf(stderr, "couldn't set /chosen/bootargs\n");
+    cpu_physical_memory_write (addr, (void *)fdt, fdt_size);
+#else
+    /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
+       to the kernel.  */
+    fdt_size = load_image_targphys("ppc.dtb", addr, 0x10000);
+    if (fdt_size < 0) {
+        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
+        if (path) {
+            fdt_size = load_image_targphys(path, addr, 0x10000);
+            g_free(path);
+        }
+    }
+
+    if (kernel_cmdline) {
+        fprintf(stderr,
+                "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
+    }
+#endif
+    return fdt_size;
+}
+
+static void virtex_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    MemoryRegion *address_space_mem = get_system_memory();
+    DeviceState *dev;
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    hwaddr ram_base = 0;
+    DriveInfo *dinfo;
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    qemu_irq irq[32], *cpu_irq;
+    int kernel_size;
+    int i;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "440-Xilinx";
+    }
+
+    cpu = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
+    env = &cpu->env;
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    memory_region_init_ram(phys_ram, "ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    pflash_cfi01_register(0xfc000000, NULL, "virtex.flash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+                          FLASH_SIZE >> 16,
+                          1, 0x89, 0x18, 0x0000, 0x0, 1);
+
+    cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT];
+    dev = xilinx_intc_create(0x81800000, cpu_irq[0], 0);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    serial_mm_init(address_space_mem, 0x83e01003ULL, 2, irq[9], 115200,
+                   serial_hds[0], DEVICE_LITTLE_ENDIAN);
+
+    /* 2 timers at irq 2 @ 62 Mhz.  */
+    xilinx_timer_create(0x83c00000, irq[3], 0, 62 * 1000000);
+
+    if (kernel_filename) {
+        uint64_t entry, low, high;
+        hwaddr boot_offset;
+
+        /* Boots a kernel elf binary.  */
+        kernel_size = load_elf(kernel_filename, NULL, NULL,
+                               &entry, &low, &high, 1, ELF_MACHINE, 0);
+        boot_info.bootstrap_pc = entry & 0x00ffffff;
+
+        if (kernel_size < 0) {
+            boot_offset = 0x1200000;
+            /* If we failed loading ELF's try a raw image.  */
+            kernel_size = load_image_targphys(kernel_filename,
+                                              boot_offset,
+                                              ram_size);
+            boot_info.bootstrap_pc = boot_offset;
+            high = boot_info.bootstrap_pc + kernel_size + 8192;
+        }
+
+        boot_info.ima_size = kernel_size;
+
+        /* Provide a device-tree.  */
+        boot_info.fdt = high + (8192 * 2);
+        boot_info.fdt &= ~8191;
+        xilinx_load_device_tree(boot_info.fdt, ram_size, 0, 0, kernel_cmdline);
+    }
+    env->load_info = &boot_info;
+}
+
+static QEMUMachine virtex_machine = {
+    .name = "virtex-ml507",
+    .desc = "Xilinx Virtex ML507 reference design",
+    .init = virtex_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void virtex_machine_init(void)
+{
+    qemu_register_machine(&virtex_machine);
+}
+
+machine_init(virtex_machine_init);
diff --git a/hw/ppc/xics.c b/hw/ppc/xics.c
new file mode 100644 (file)
index 0000000..c3ef12f
--- /dev/null
@@ -0,0 +1,588 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
+ *
+ * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "hw/hw.h"
+#include "trace.h"
+#include "hw/spapr.h"
+#include "hw/xics.h"
+
+/*
+ * ICP: Presentation layer
+ */
+
+struct icp_server_state {
+    uint32_t xirr;
+    uint8_t pending_priority;
+    uint8_t mfrr;
+    qemu_irq output;
+};
+
+#define XISR_MASK  0x00ffffff
+#define CPPR_MASK  0xff000000
+
+#define XISR(ss)   (((ss)->xirr) & XISR_MASK)
+#define CPPR(ss)   (((ss)->xirr) >> 24)
+
+struct ics_state;
+
+struct icp_state {
+    long nr_servers;
+    struct icp_server_state *ss;
+    struct ics_state *ics;
+};
+
+static void ics_reject(struct ics_state *ics, int nr);
+static void ics_resend(struct ics_state *ics);
+static void ics_eoi(struct ics_state *ics, int nr);
+
+static void icp_check_ipi(struct icp_state *icp, int server)
+{
+    struct icp_server_state *ss = icp->ss + server;
+
+    if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
+        return;
+    }
+
+    trace_xics_icp_check_ipi(server, ss->mfrr);
+
+    if (XISR(ss)) {
+        ics_reject(icp->ics, XISR(ss));
+    }
+
+    ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
+    ss->pending_priority = ss->mfrr;
+    qemu_irq_raise(ss->output);
+}
+
+static void icp_resend(struct icp_state *icp, int server)
+{
+    struct icp_server_state *ss = icp->ss + server;
+
+    if (ss->mfrr < CPPR(ss)) {
+        icp_check_ipi(icp, server);
+    }
+    ics_resend(icp->ics);
+}
+
+static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr)
+{
+    struct icp_server_state *ss = icp->ss + server;
+    uint8_t old_cppr;
+    uint32_t old_xisr;
+
+    old_cppr = CPPR(ss);
+    ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24);
+
+    if (cppr < old_cppr) {
+        if (XISR(ss) && (cppr <= ss->pending_priority)) {
+            old_xisr = XISR(ss);
+            ss->xirr &= ~XISR_MASK; /* Clear XISR */
+            qemu_irq_lower(ss->output);
+            ics_reject(icp->ics, old_xisr);
+        }
+    } else {
+        if (!XISR(ss)) {
+            icp_resend(icp, server);
+        }
+    }
+}
+
+static void icp_set_mfrr(struct icp_state *icp, int server, uint8_t mfrr)
+{
+    struct icp_server_state *ss = icp->ss + server;
+
+    ss->mfrr = mfrr;
+    if (mfrr < CPPR(ss)) {
+        icp_check_ipi(icp, server);
+    }
+}
+
+static uint32_t icp_accept(struct icp_server_state *ss)
+{
+    uint32_t xirr = ss->xirr;
+
+    qemu_irq_lower(ss->output);
+    ss->xirr = ss->pending_priority << 24;
+
+    trace_xics_icp_accept(xirr, ss->xirr);
+
+    return xirr;
+}
+
+static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
+{
+    struct icp_server_state *ss = icp->ss + server;
+
+    /* Send EOI -> ICS */
+    ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
+    trace_xics_icp_eoi(server, xirr, ss->xirr);
+    ics_eoi(icp->ics, xirr & XISR_MASK);
+    if (!XISR(ss)) {
+        icp_resend(icp, server);
+    }
+}
+
+static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority)
+{
+    struct icp_server_state *ss = icp->ss + server;
+
+    trace_xics_icp_irq(server, nr, priority);
+
+    if ((priority >= CPPR(ss))
+        || (XISR(ss) && (ss->pending_priority <= priority))) {
+        ics_reject(icp->ics, nr);
+    } else {
+        if (XISR(ss)) {
+            ics_reject(icp->ics, XISR(ss));
+        }
+        ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
+        ss->pending_priority = priority;
+        trace_xics_icp_raise(ss->xirr, ss->pending_priority);
+        qemu_irq_raise(ss->output);
+    }
+}
+
+/*
+ * ICS: Source layer
+ */
+
+struct ics_irq_state {
+    int server;
+    uint8_t priority;
+    uint8_t saved_priority;
+#define XICS_STATUS_ASSERTED           0x1
+#define XICS_STATUS_SENT               0x2
+#define XICS_STATUS_REJECTED           0x4
+#define XICS_STATUS_MASKED_PENDING     0x8
+    uint8_t status;
+};
+
+struct ics_state {
+    int nr_irqs;
+    int offset;
+    qemu_irq *qirqs;
+    bool *islsi;
+    struct ics_irq_state *irqs;
+    struct icp_state *icp;
+};
+
+static int ics_valid_irq(struct ics_state *ics, uint32_t nr)
+{
+    return (nr >= ics->offset)
+        && (nr < (ics->offset + ics->nr_irqs));
+}
+
+static void resend_msi(struct ics_state *ics, int srcno)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    /* FIXME: filter by server#? */
+    if (irq->status & XICS_STATUS_REJECTED) {
+        irq->status &= ~XICS_STATUS_REJECTED;
+        if (irq->priority != 0xff) {
+            icp_irq(ics->icp, irq->server, srcno + ics->offset,
+                    irq->priority);
+        }
+    }
+}
+
+static void resend_lsi(struct ics_state *ics, int srcno)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    if ((irq->priority != 0xff)
+        && (irq->status & XICS_STATUS_ASSERTED)
+        && !(irq->status & XICS_STATUS_SENT)) {
+        irq->status |= XICS_STATUS_SENT;
+        icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
+    }
+}
+
+static void set_irq_msi(struct ics_state *ics, int srcno, int val)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    trace_xics_set_irq_msi(srcno, srcno + ics->offset);
+
+    if (val) {
+        if (irq->priority == 0xff) {
+            irq->status |= XICS_STATUS_MASKED_PENDING;
+            trace_xics_masked_pending();
+        } else  {
+            icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
+        }
+    }
+}
+
+static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
+    if (val) {
+        irq->status |= XICS_STATUS_ASSERTED;
+    } else {
+        irq->status &= ~XICS_STATUS_ASSERTED;
+    }
+    resend_lsi(ics, srcno);
+}
+
+static void ics_set_irq(void *opaque, int srcno, int val)
+{
+    struct ics_state *ics = (struct ics_state *)opaque;
+
+    if (ics->islsi[srcno]) {
+        set_irq_lsi(ics, srcno, val);
+    } else {
+        set_irq_msi(ics, srcno, val);
+    }
+}
+
+static void write_xive_msi(struct ics_state *ics, int srcno)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    if (!(irq->status & XICS_STATUS_MASKED_PENDING)
+        || (irq->priority == 0xff)) {
+        return;
+    }
+
+    irq->status &= ~XICS_STATUS_MASKED_PENDING;
+    icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
+}
+
+static void write_xive_lsi(struct ics_state *ics, int srcno)
+{
+    resend_lsi(ics, srcno);
+}
+
+static void ics_write_xive(struct ics_state *ics, int nr, int server,
+                           uint8_t priority, uint8_t saved_priority)
+{
+    int srcno = nr - ics->offset;
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    irq->server = server;
+    irq->priority = priority;
+    irq->saved_priority = saved_priority;
+
+    trace_xics_ics_write_xive(nr, srcno, server, priority);
+
+    if (ics->islsi[srcno]) {
+        write_xive_lsi(ics, srcno);
+    } else {
+        write_xive_msi(ics, srcno);
+    }
+}
+
+static void ics_reject(struct ics_state *ics, int nr)
+{
+    struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+
+    trace_xics_ics_reject(nr, nr - ics->offset);
+    irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
+    irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
+}
+
+static void ics_resend(struct ics_state *ics)
+{
+    int i;
+
+    for (i = 0; i < ics->nr_irqs; i++) {
+        /* FIXME: filter by server#? */
+        if (ics->islsi[i]) {
+            resend_lsi(ics, i);
+        } else {
+            resend_msi(ics, i);
+        }
+    }
+}
+
+static void ics_eoi(struct ics_state *ics, int nr)
+{
+    int srcno = nr - ics->offset;
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    trace_xics_ics_eoi(nr);
+
+    if (ics->islsi[srcno]) {
+        irq->status &= ~XICS_STATUS_SENT;
+    }
+}
+
+/*
+ * Exported functions
+ */
+
+qemu_irq xics_get_qirq(struct icp_state *icp, int irq)
+{
+    if (!ics_valid_irq(icp->ics, irq)) {
+        return NULL;
+    }
+
+    return icp->ics->qirqs[irq - icp->ics->offset];
+}
+
+void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi)
+{
+    assert(ics_valid_irq(icp->ics, irq));
+
+    icp->ics->islsi[irq - icp->ics->offset] = lsi;
+}
+
+static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    CPUState *cs = CPU(cpu);
+    target_ulong cppr = args[0];
+
+    icp_set_cppr(spapr->icp, cs->cpu_index, cppr);
+    return H_SUCCESS;
+}
+
+static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                          target_ulong opcode, target_ulong *args)
+{
+    target_ulong server = args[0];
+    target_ulong mfrr = args[1];
+
+    if (server >= spapr->icp->nr_servers) {
+        return H_PARAMETER;
+    }
+
+    icp_set_mfrr(spapr->icp, server, mfrr);
+    return H_SUCCESS;
+}
+
+static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    CPUState *cs = CPU(cpu);
+    uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index);
+
+    args[0] = xirr;
+    return H_SUCCESS;
+}
+
+static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                          target_ulong opcode, target_ulong *args)
+{
+    CPUState *cs = CPU(cpu);
+    target_ulong xirr = args[0];
+
+    icp_eoi(spapr->icp, cs->cpu_index, xirr);
+    return H_SUCCESS;
+}
+
+static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token,
+                          uint32_t nargs, target_ulong args,
+                          uint32_t nret, target_ulong rets)
+{
+    struct ics_state *ics = spapr->icp->ics;
+    uint32_t nr, server, priority;
+
+    if ((nargs != 3) || (nret != 1)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    nr = rtas_ld(args, 0);
+    server = rtas_ld(args, 1);
+    priority = rtas_ld(args, 2);
+
+    if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
+        || (priority > 0xff)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    ics_write_xive(ics, nr, server, priority, priority);
+
+    rtas_st(rets, 0, 0); /* Success */
+}
+
+static void rtas_get_xive(sPAPREnvironment *spapr, uint32_t token,
+                          uint32_t nargs, target_ulong args,
+                          uint32_t nret, target_ulong rets)
+{
+    struct ics_state *ics = spapr->icp->ics;
+    uint32_t nr;
+
+    if ((nargs != 1) || (nret != 3)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    nr = rtas_ld(args, 0);
+
+    if (!ics_valid_irq(ics, nr)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    rtas_st(rets, 0, 0); /* Success */
+    rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
+    rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
+}
+
+static void rtas_int_off(sPAPREnvironment *spapr, uint32_t token,
+                         uint32_t nargs, target_ulong args,
+                         uint32_t nret, target_ulong rets)
+{
+    struct ics_state *ics = spapr->icp->ics;
+    uint32_t nr;
+
+    if ((nargs != 1) || (nret != 1)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    nr = rtas_ld(args, 0);
+
+    if (!ics_valid_irq(ics, nr)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
+                   ics->irqs[nr - ics->offset].priority);
+
+    rtas_st(rets, 0, 0); /* Success */
+}
+
+static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token,
+                        uint32_t nargs, target_ulong args,
+                        uint32_t nret, target_ulong rets)
+{
+    struct ics_state *ics = spapr->icp->ics;
+    uint32_t nr;
+
+    if ((nargs != 1) || (nret != 1)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    nr = rtas_ld(args, 0);
+
+    if (!ics_valid_irq(ics, nr)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
+                   ics->irqs[nr - ics->offset].saved_priority,
+                   ics->irqs[nr - ics->offset].saved_priority);
+
+    rtas_st(rets, 0, 0); /* Success */
+}
+
+static void xics_reset(void *opaque)
+{
+    struct icp_state *icp = (struct icp_state *)opaque;
+    struct ics_state *ics = icp->ics;
+    int i;
+
+    for (i = 0; i < icp->nr_servers; i++) {
+        icp->ss[i].xirr = 0;
+        icp->ss[i].pending_priority = 0xff;
+        icp->ss[i].mfrr = 0xff;
+        /* Make all outputs are deasserted */
+        qemu_set_irq(icp->ss[i].output, 0);
+    }
+
+    memset(ics->irqs, 0, sizeof(struct ics_irq_state) * ics->nr_irqs);
+    for (i = 0; i < ics->nr_irqs; i++) {
+        ics->irqs[i].priority = 0xff;
+        ics->irqs[i].saved_priority = 0xff;
+    }
+}
+
+struct icp_state *xics_system_init(int nr_irqs)
+{
+    CPUPPCState *env;
+    CPUState *cpu;
+    int max_server_num;
+    struct icp_state *icp;
+    struct ics_state *ics;
+
+    max_server_num = -1;
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu = CPU(ppc_env_get_cpu(env));
+        if (cpu->cpu_index > max_server_num) {
+            max_server_num = cpu->cpu_index;
+        }
+    }
+
+    icp = g_malloc0(sizeof(*icp));
+    icp->nr_servers = max_server_num + 1;
+    icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu = CPU(ppc_env_get_cpu(env));
+        struct icp_server_state *ss = &icp->ss[cpu->cpu_index];
+
+        switch (PPC_INPUT(env)) {
+        case PPC_FLAGS_INPUT_POWER7:
+            ss->output = env->irq_inputs[POWER7_INPUT_INT];
+            break;
+
+        case PPC_FLAGS_INPUT_970:
+            ss->output = env->irq_inputs[PPC970_INPUT_INT];
+            break;
+
+        default:
+            hw_error("XICS interrupt model does not support this CPU bus "
+                     "model\n");
+            exit(1);
+        }
+    }
+
+    ics = g_malloc0(sizeof(*ics));
+    ics->nr_irqs = nr_irqs;
+    ics->offset = XICS_IRQ_BASE;
+    ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state));
+    ics->islsi = g_malloc0(nr_irqs * sizeof(bool));
+
+    icp->ics = ics;
+    ics->icp = icp;
+
+    ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs);
+
+    spapr_register_hypercall(H_CPPR, h_cppr);
+    spapr_register_hypercall(H_IPI, h_ipi);
+    spapr_register_hypercall(H_XIRR, h_xirr);
+    spapr_register_hypercall(H_EOI, h_eoi);
+
+    spapr_rtas_register("ibm,set-xive", rtas_set_xive);
+    spapr_rtas_register("ibm,get-xive", rtas_get_xive);
+    spapr_rtas_register("ibm,int-off", rtas_int_off);
+    spapr_rtas_register("ibm,int-on", rtas_int_on);
+
+    qemu_register_reset(xics_reset, icp);
+
+    return icp;
+}
index 535cbfb33903b4c0be2968dd9c87afd47ca1f80c..45c2159aa6ce0b4c3de5c31cc50647fec136177c 100644 (file)
@@ -25,7 +25,7 @@
 #if !defined(PPC_405_H)
 #define PPC_405_H
 
-#include "ppc4xx.h"
+#include "hw/ppc4xx.h"
 
 /* Bootinfo as set-up by u-boot */
 typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t;
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
deleted file mode 100644 (file)
index cf371db..0000000
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * QEMU PowerPC 405 evaluation boards emulation
- *
- * Copyright (c) 2007 Jocelyn Mayer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "ppc.h"
-#include "ppc405.h"
-#include "nvram.h"
-#include "flash.h"
-#include "sysemu/sysemu.h"
-#include "block/block.h"
-#include "boards.h"
-#include "qemu/log.h"
-#include "loader.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define BIOS_FILENAME "ppc405_rom.bin"
-#define BIOS_SIZE (2048 * 1024)
-
-#define KERNEL_LOAD_ADDR 0x00000000
-#define INITRD_LOAD_ADDR 0x01800000
-
-#define USE_FLASH_BIOS
-
-#define DEBUG_BOARD_INIT
-
-/*****************************************************************************/
-/* PPC405EP reference board (IBM) */
-/* Standalone board with:
- * - PowerPC 405EP CPU
- * - SDRAM (0x00000000)
- * - Flash (0xFFF80000)
- * - SRAM  (0xFFF00000)
- * - NVRAM (0xF0000000)
- * - FPGA  (0xF0300000)
- */
-typedef struct ref405ep_fpga_t ref405ep_fpga_t;
-struct ref405ep_fpga_t {
-    uint8_t reg0;
-    uint8_t reg1;
-};
-
-static uint32_t ref405ep_fpga_readb (void *opaque, hwaddr addr)
-{
-    ref405ep_fpga_t *fpga;
-    uint32_t ret;
-
-    fpga = opaque;
-    switch (addr) {
-    case 0x0:
-        ret = fpga->reg0;
-        break;
-    case 0x1:
-        ret = fpga->reg1;
-        break;
-    default:
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void ref405ep_fpga_writeb (void *opaque,
-                                  hwaddr addr, uint32_t value)
-{
-    ref405ep_fpga_t *fpga;
-
-    fpga = opaque;
-    switch (addr) {
-    case 0x0:
-        /* Read only */
-        break;
-    case 0x1:
-        fpga->reg1 = value;
-        break;
-    default:
-        break;
-    }
-}
-
-static uint32_t ref405ep_fpga_readw (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-    ret = ref405ep_fpga_readb(opaque, addr) << 8;
-    ret |= ref405ep_fpga_readb(opaque, addr + 1);
-
-    return ret;
-}
-
-static void ref405ep_fpga_writew (void *opaque,
-                                  hwaddr addr, uint32_t value)
-{
-    ref405ep_fpga_writeb(opaque, addr, (value >> 8) & 0xFF);
-    ref405ep_fpga_writeb(opaque, addr + 1, value & 0xFF);
-}
-
-static uint32_t ref405ep_fpga_readl (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-    ret = ref405ep_fpga_readb(opaque, addr) << 24;
-    ret |= ref405ep_fpga_readb(opaque, addr + 1) << 16;
-    ret |= ref405ep_fpga_readb(opaque, addr + 2) << 8;
-    ret |= ref405ep_fpga_readb(opaque, addr + 3);
-
-    return ret;
-}
-
-static void ref405ep_fpga_writel (void *opaque,
-                                  hwaddr addr, uint32_t value)
-{
-    ref405ep_fpga_writeb(opaque, addr, (value >> 24) & 0xFF);
-    ref405ep_fpga_writeb(opaque, addr + 1, (value >> 16) & 0xFF);
-    ref405ep_fpga_writeb(opaque, addr + 2, (value >> 8) & 0xFF);
-    ref405ep_fpga_writeb(opaque, addr + 3, value & 0xFF);
-}
-
-static const MemoryRegionOps ref405ep_fpga_ops = {
-    .old_mmio = {
-        .read = {
-            ref405ep_fpga_readb, ref405ep_fpga_readw, ref405ep_fpga_readl,
-        },
-        .write = {
-            ref405ep_fpga_writeb, ref405ep_fpga_writew, ref405ep_fpga_writel,
-        },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ref405ep_fpga_reset (void *opaque)
-{
-    ref405ep_fpga_t *fpga;
-
-    fpga = opaque;
-    fpga->reg0 = 0x00;
-    fpga->reg1 = 0x0F;
-}
-
-static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base)
-{
-    ref405ep_fpga_t *fpga;
-    MemoryRegion *fpga_memory = g_new(MemoryRegion, 1);
-
-    fpga = g_malloc0(sizeof(ref405ep_fpga_t));
-    memory_region_init_io(fpga_memory, &ref405ep_fpga_ops, fpga,
-                          "fpga", 0x00000100);
-    memory_region_add_subregion(sysmem, base, fpga_memory);
-    qemu_register_reset(&ref405ep_fpga_reset, fpga);
-}
-
-static void ref405ep_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    ppc4xx_bd_info_t bd;
-    CPUPPCState *env;
-    qemu_irq *pic;
-    MemoryRegion *bios;
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    ram_addr_t bdloc;
-    MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
-    hwaddr ram_bases[2], ram_sizes[2];
-    target_ulong sram_size;
-    long bios_size;
-    //int phy_addr = 0;
-    //static int phy_addr = 1;
-    target_ulong kernel_base, initrd_base;
-    long kernel_size, initrd_size;
-    int linux_boot;
-    int fl_idx, fl_sectors, len;
-    DriveInfo *dinfo;
-    MemoryRegion *sysmem = get_system_memory();
-
-    /* XXX: fix this */
-    memory_region_init_ram(&ram_memories[0], "ef405ep.ram", 0x08000000);
-    vmstate_register_ram_global(&ram_memories[0]);
-    ram_bases[0] = 0;
-    ram_sizes[0] = 0x08000000;
-    memory_region_init(&ram_memories[1], "ef405ep.ram1", 0);
-    ram_bases[1] = 0x00000000;
-    ram_sizes[1] = 0x00000000;
-    ram_size = 128 * 1024 * 1024;
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register cpu\n", __func__);
-#endif
-    env = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
-                        33333333, &pic, kernel_filename == NULL ? 0 : 1);
-    /* allocate SRAM */
-    sram_size = 512 * 1024;
-    memory_region_init_ram(sram, "ef405ep.sram", sram_size);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(sysmem, 0xFFF00000, sram);
-    /* allocate and load BIOS */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register BIOS\n", __func__);
-#endif
-    fl_idx = 0;
-#ifdef USE_FLASH_BIOS
-    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
-    if (dinfo) {
-        bios_size = bdrv_getlength(dinfo->bdrv);
-        fl_sectors = (bios_size + 65535) >> 16;
-#ifdef DEBUG_BOARD_INIT
-        printf("Register parallel flash %d size %lx"
-               " at addr %lx '%s' %d\n",
-               fl_idx, bios_size, -bios_size,
-               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
-#endif
-        pflash_cfi02_register((uint32_t)(-bios_size),
-                              NULL, "ef405ep.bios", bios_size,
-                              dinfo->bdrv, 65536, fl_sectors, 1,
-                              2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
-                              1);
-        fl_idx++;
-    } else
-#endif
-    {
-#ifdef DEBUG_BOARD_INIT
-        printf("Load BIOS from file\n");
-#endif
-        bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, "ef405ep.bios", BIOS_SIZE);
-        vmstate_register_ram_global(bios);
-        if (bios_name == NULL)
-            bios_name = BIOS_FILENAME;
-        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-        if (filename) {
-            bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
-            g_free(filename);
-        } else {
-            bios_size = -1;
-        }
-        if (bios_size < 0 || bios_size > BIOS_SIZE) {
-            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n",
-                    bios_name);
-            exit(1);
-        }
-        bios_size = (bios_size + 0xfff) & ~0xfff;
-        memory_region_set_readonly(bios, true);
-        memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
-    }
-    /* Register FPGA */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register FPGA\n", __func__);
-#endif
-    ref405ep_fpga_init(sysmem, 0xF0300000);
-    /* Register NVRAM */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register NVRAM\n", __func__);
-#endif
-    m48t59_init(NULL, 0xF0000000, 0, 8192, 8);
-    /* Load kernel */
-    linux_boot = (kernel_filename != NULL);
-    if (linux_boot) {
-#ifdef DEBUG_BOARD_INIT
-        printf("%s: load kernel\n", __func__);
-#endif
-        memset(&bd, 0, sizeof(bd));
-        bd.bi_memstart = 0x00000000;
-        bd.bi_memsize = ram_size;
-        bd.bi_flashstart = -bios_size;
-        bd.bi_flashsize = -bios_size;
-        bd.bi_flashoffset = 0;
-        bd.bi_sramstart = 0xFFF00000;
-        bd.bi_sramsize = sram_size;
-        bd.bi_bootflags = 0;
-        bd.bi_intfreq = 133333333;
-        bd.bi_busfreq = 33333333;
-        bd.bi_baudrate = 115200;
-        bd.bi_s_version[0] = 'Q';
-        bd.bi_s_version[1] = 'M';
-        bd.bi_s_version[2] = 'U';
-        bd.bi_s_version[3] = '\0';
-        bd.bi_r_version[0] = 'Q';
-        bd.bi_r_version[1] = 'E';
-        bd.bi_r_version[2] = 'M';
-        bd.bi_r_version[3] = 'U';
-        bd.bi_r_version[4] = '\0';
-        bd.bi_procfreq = 133333333;
-        bd.bi_plb_busfreq = 33333333;
-        bd.bi_pci_busfreq = 33333333;
-        bd.bi_opbfreq = 33333333;
-        bdloc = ppc405_set_bootinfo(env, &bd, 0x00000001);
-        env->gpr[3] = bdloc;
-        kernel_base = KERNEL_LOAD_ADDR;
-        /* now we can load the kernel */
-        kernel_size = load_image_targphys(kernel_filename, kernel_base,
-                                          ram_size - kernel_base);
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-        printf("Load kernel size %ld at " TARGET_FMT_lx,
-               kernel_size, kernel_base);
-        /* load initrd */
-        if (initrd_filename) {
-            initrd_base = INITRD_LOAD_ADDR;
-            initrd_size = load_image_targphys(initrd_filename, initrd_base,
-                                              ram_size - initrd_base);
-            if (initrd_size < 0) {
-                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                        initrd_filename);
-                exit(1);
-            }
-        } else {
-            initrd_base = 0;
-            initrd_size = 0;
-        }
-        env->gpr[4] = initrd_base;
-        env->gpr[5] = initrd_size;
-        if (kernel_cmdline != NULL) {
-            len = strlen(kernel_cmdline);
-            bdloc -= ((len + 255) & ~255);
-            cpu_physical_memory_write(bdloc, (void *)kernel_cmdline, len + 1);
-            env->gpr[6] = bdloc;
-            env->gpr[7] = bdloc + len;
-        } else {
-            env->gpr[6] = 0;
-            env->gpr[7] = 0;
-        }
-        env->nip = KERNEL_LOAD_ADDR;
-    } else {
-        kernel_base = 0;
-        kernel_size = 0;
-        initrd_base = 0;
-        initrd_size = 0;
-        bdloc = 0;
-    }
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: Done\n", __func__);
-#endif
-    printf("bdloc " RAM_ADDR_FMT "\n", bdloc);
-}
-
-static QEMUMachine ref405ep_machine = {
-    .name = "ref405ep",
-    .desc = "ref405ep",
-    .init = ref405ep_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-/*****************************************************************************/
-/* AMCC Taihu evaluation board */
-/* - PowerPC 405EP processor
- * - SDRAM               128 MB at 0x00000000
- * - Boot flash          2 MB   at 0xFFE00000
- * - Application flash   32 MB  at 0xFC000000
- * - 2 serial ports
- * - 2 ethernet PHY
- * - 1 USB 1.1 device    0x50000000
- * - 1 LCD display       0x50100000
- * - 1 CPLD              0x50100000
- * - 1 I2C EEPROM
- * - 1 I2C thermal sensor
- * - a set of LEDs
- * - bit-bang SPI port using GPIOs
- * - 1 EBC interface connector 0 0x50200000
- * - 1 cardbus controller + expansion slot.
- * - 1 PCI expansion slot.
- */
-typedef struct taihu_cpld_t taihu_cpld_t;
-struct taihu_cpld_t {
-    uint8_t reg0;
-    uint8_t reg1;
-};
-
-static uint32_t taihu_cpld_readb (void *opaque, hwaddr addr)
-{
-    taihu_cpld_t *cpld;
-    uint32_t ret;
-
-    cpld = opaque;
-    switch (addr) {
-    case 0x0:
-        ret = cpld->reg0;
-        break;
-    case 0x1:
-        ret = cpld->reg1;
-        break;
-    default:
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void taihu_cpld_writeb (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    taihu_cpld_t *cpld;
-
-    cpld = opaque;
-    switch (addr) {
-    case 0x0:
-        /* Read only */
-        break;
-    case 0x1:
-        cpld->reg1 = value;
-        break;
-    default:
-        break;
-    }
-}
-
-static uint32_t taihu_cpld_readw (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-    ret = taihu_cpld_readb(opaque, addr) << 8;
-    ret |= taihu_cpld_readb(opaque, addr + 1);
-
-    return ret;
-}
-
-static void taihu_cpld_writew (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    taihu_cpld_writeb(opaque, addr, (value >> 8) & 0xFF);
-    taihu_cpld_writeb(opaque, addr + 1, value & 0xFF);
-}
-
-static uint32_t taihu_cpld_readl (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-    ret = taihu_cpld_readb(opaque, addr) << 24;
-    ret |= taihu_cpld_readb(opaque, addr + 1) << 16;
-    ret |= taihu_cpld_readb(opaque, addr + 2) << 8;
-    ret |= taihu_cpld_readb(opaque, addr + 3);
-
-    return ret;
-}
-
-static void taihu_cpld_writel (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    taihu_cpld_writel(opaque, addr, (value >> 24) & 0xFF);
-    taihu_cpld_writel(opaque, addr + 1, (value >> 16) & 0xFF);
-    taihu_cpld_writel(opaque, addr + 2, (value >> 8) & 0xFF);
-    taihu_cpld_writeb(opaque, addr + 3, value & 0xFF);
-}
-
-static const MemoryRegionOps taihu_cpld_ops = {
-    .old_mmio = {
-        .read = { taihu_cpld_readb, taihu_cpld_readw, taihu_cpld_readl, },
-        .write = { taihu_cpld_writeb, taihu_cpld_writew, taihu_cpld_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void taihu_cpld_reset (void *opaque)
-{
-    taihu_cpld_t *cpld;
-
-    cpld = opaque;
-    cpld->reg0 = 0x01;
-    cpld->reg1 = 0x80;
-}
-
-static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base)
-{
-    taihu_cpld_t *cpld;
-    MemoryRegion *cpld_memory = g_new(MemoryRegion, 1);
-
-    cpld = g_malloc0(sizeof(taihu_cpld_t));
-    memory_region_init_io(cpld_memory, &taihu_cpld_ops, cpld, "cpld", 0x100);
-    memory_region_add_subregion(sysmem, base, cpld_memory);
-    qemu_register_reset(&taihu_cpld_reset, cpld);
-}
-
-static void taihu_405ep_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *kernel_filename = args->kernel_filename;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    qemu_irq *pic;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *bios;
-    MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
-    hwaddr ram_bases[2], ram_sizes[2];
-    long bios_size;
-    target_ulong kernel_base, initrd_base;
-    long kernel_size, initrd_size;
-    int linux_boot;
-    int fl_idx, fl_sectors;
-    DriveInfo *dinfo;
-
-    /* RAM is soldered to the board so the size cannot be changed */
-    memory_region_init_ram(&ram_memories[0],
-                           "taihu_405ep.ram-0", 0x04000000);
-    vmstate_register_ram_global(&ram_memories[0]);
-    ram_bases[0] = 0;
-    ram_sizes[0] = 0x04000000;
-    memory_region_init_ram(&ram_memories[1],
-                           "taihu_405ep.ram-1", 0x04000000);
-    vmstate_register_ram_global(&ram_memories[1]);
-    ram_bases[1] = 0x04000000;
-    ram_sizes[1] = 0x04000000;
-    ram_size = 0x08000000;
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register cpu\n", __func__);
-#endif
-    ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
-                  33333333, &pic, kernel_filename == NULL ? 0 : 1);
-    /* allocate and load BIOS */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register BIOS\n", __func__);
-#endif
-    fl_idx = 0;
-#if defined(USE_FLASH_BIOS)
-    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
-    if (dinfo) {
-        bios_size = bdrv_getlength(dinfo->bdrv);
-        /* XXX: should check that size is 2MB */
-        //        bios_size = 2 * 1024 * 1024;
-        fl_sectors = (bios_size + 65535) >> 16;
-#ifdef DEBUG_BOARD_INIT
-        printf("Register parallel flash %d size %lx"
-               " at addr %lx '%s' %d\n",
-               fl_idx, bios_size, -bios_size,
-               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
-#endif
-        pflash_cfi02_register((uint32_t)(-bios_size),
-                              NULL, "taihu_405ep.bios", bios_size,
-                              dinfo->bdrv, 65536, fl_sectors, 1,
-                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
-                              1);
-        fl_idx++;
-    } else
-#endif
-    {
-#ifdef DEBUG_BOARD_INIT
-        printf("Load BIOS from file\n");
-#endif
-        if (bios_name == NULL)
-            bios_name = BIOS_FILENAME;
-        bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, "taihu_405ep.bios", BIOS_SIZE);
-        vmstate_register_ram_global(bios);
-        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-        if (filename) {
-            bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
-            g_free(filename);
-        } else {
-            bios_size = -1;
-        }
-        if (bios_size < 0 || bios_size > BIOS_SIZE) {
-            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n",
-                    bios_name);
-            exit(1);
-        }
-        bios_size = (bios_size + 0xfff) & ~0xfff;
-        memory_region_set_readonly(bios, true);
-        memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
-    }
-    /* Register Linux flash */
-    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
-    if (dinfo) {
-        bios_size = bdrv_getlength(dinfo->bdrv);
-        /* XXX: should check that size is 32MB */
-        bios_size = 32 * 1024 * 1024;
-        fl_sectors = (bios_size + 65535) >> 16;
-#ifdef DEBUG_BOARD_INIT
-        printf("Register parallel flash %d size %lx"
-               " at addr " TARGET_FMT_lx " '%s'\n",
-               fl_idx, bios_size, (target_ulong)0xfc000000,
-               bdrv_get_device_name(dinfo->bdrv));
-#endif
-        pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size,
-                              dinfo->bdrv, 65536, fl_sectors, 1,
-                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
-                              1);
-        fl_idx++;
-    }
-    /* Register CLPD & LCD display */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register CPLD\n", __func__);
-#endif
-    taihu_cpld_init(sysmem, 0x50100000);
-    /* Load kernel */
-    linux_boot = (kernel_filename != NULL);
-    if (linux_boot) {
-#ifdef DEBUG_BOARD_INIT
-        printf("%s: load kernel\n", __func__);
-#endif
-        kernel_base = KERNEL_LOAD_ADDR;
-        /* now we can load the kernel */
-        kernel_size = load_image_targphys(kernel_filename, kernel_base,
-                                          ram_size - kernel_base);
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-        /* load initrd */
-        if (initrd_filename) {
-            initrd_base = INITRD_LOAD_ADDR;
-            initrd_size = load_image_targphys(initrd_filename, initrd_base,
-                                              ram_size - initrd_base);
-            if (initrd_size < 0) {
-                fprintf(stderr,
-                        "qemu: could not load initial ram disk '%s'\n",
-                        initrd_filename);
-                exit(1);
-            }
-        } else {
-            initrd_base = 0;
-            initrd_size = 0;
-        }
-    } else {
-        kernel_base = 0;
-        kernel_size = 0;
-        initrd_base = 0;
-        initrd_size = 0;
-    }
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: Done\n", __func__);
-#endif
-}
-
-static QEMUMachine taihu_machine = {
-    .name = "taihu",
-    .desc = "taihu",
-    .init = taihu_405ep_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void ppc405_machine_init(void)
-{
-    qemu_register_machine(&ref405ep_machine);
-    qemu_register_machine(&taihu_machine);
-}
-
-machine_init(ppc405_machine_init);
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
deleted file mode 100644 (file)
index d8cbe87..0000000
+++ /dev/null
@@ -1,2548 +0,0 @@
-/*
- * QEMU PowerPC 405 embedded processors emulation
- *
- * Copyright (c) 2007 Jocelyn Mayer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "ppc.h"
-#include "ppc405.h"
-#include "serial.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "qemu/log.h"
-#include "exec/address-spaces.h"
-
-#define DEBUG_OPBA
-#define DEBUG_SDRAM
-#define DEBUG_GPIO
-#define DEBUG_SERIAL
-#define DEBUG_OCM
-//#define DEBUG_I2C
-#define DEBUG_GPT
-#define DEBUG_MAL
-#define DEBUG_CLOCKS
-//#define DEBUG_CLOCKS_LL
-
-ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
-                                uint32_t flags)
-{
-    ram_addr_t bdloc;
-    int i, n;
-
-    /* We put the bd structure at the top of memory */
-    if (bd->bi_memsize >= 0x01000000UL)
-        bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t);
-    else
-        bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t);
-    stl_be_phys(bdloc + 0x00, bd->bi_memstart);
-    stl_be_phys(bdloc + 0x04, bd->bi_memsize);
-    stl_be_phys(bdloc + 0x08, bd->bi_flashstart);
-    stl_be_phys(bdloc + 0x0C, bd->bi_flashsize);
-    stl_be_phys(bdloc + 0x10, bd->bi_flashoffset);
-    stl_be_phys(bdloc + 0x14, bd->bi_sramstart);
-    stl_be_phys(bdloc + 0x18, bd->bi_sramsize);
-    stl_be_phys(bdloc + 0x1C, bd->bi_bootflags);
-    stl_be_phys(bdloc + 0x20, bd->bi_ipaddr);
-    for (i = 0; i < 6; i++) {
-        stb_phys(bdloc + 0x24 + i, bd->bi_enetaddr[i]);
-    }
-    stw_be_phys(bdloc + 0x2A, bd->bi_ethspeed);
-    stl_be_phys(bdloc + 0x2C, bd->bi_intfreq);
-    stl_be_phys(bdloc + 0x30, bd->bi_busfreq);
-    stl_be_phys(bdloc + 0x34, bd->bi_baudrate);
-    for (i = 0; i < 4; i++) {
-        stb_phys(bdloc + 0x38 + i, bd->bi_s_version[i]);
-    }
-    for (i = 0; i < 32; i++) {
-        stb_phys(bdloc + 0x3C + i, bd->bi_r_version[i]);
-    }
-    stl_be_phys(bdloc + 0x5C, bd->bi_plb_busfreq);
-    stl_be_phys(bdloc + 0x60, bd->bi_pci_busfreq);
-    for (i = 0; i < 6; i++) {
-        stb_phys(bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]);
-    }
-    n = 0x6A;
-    if (flags & 0x00000001) {
-        for (i = 0; i < 6; i++)
-            stb_phys(bdloc + n++, bd->bi_pci_enetaddr2[i]);
-    }
-    stl_be_phys(bdloc + n, bd->bi_opbfreq);
-    n += 4;
-    for (i = 0; i < 2; i++) {
-        stl_be_phys(bdloc + n, bd->bi_iic_fast[i]);
-        n += 4;
-    }
-
-    return bdloc;
-}
-
-/*****************************************************************************/
-/* Shared peripherals */
-
-/*****************************************************************************/
-/* Peripheral local bus arbitrer */
-enum {
-    PLB0_BESR = 0x084,
-    PLB0_BEAR = 0x086,
-    PLB0_ACR  = 0x087,
-};
-
-typedef struct ppc4xx_plb_t ppc4xx_plb_t;
-struct ppc4xx_plb_t {
-    uint32_t acr;
-    uint32_t bear;
-    uint32_t besr;
-};
-
-static uint32_t dcr_read_plb (void *opaque, int dcrn)
-{
-    ppc4xx_plb_t *plb;
-    uint32_t ret;
-
-    plb = opaque;
-    switch (dcrn) {
-    case PLB0_ACR:
-        ret = plb->acr;
-        break;
-    case PLB0_BEAR:
-        ret = plb->bear;
-        break;
-    case PLB0_BESR:
-        ret = plb->besr;
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_plb (void *opaque, int dcrn, uint32_t val)
-{
-    ppc4xx_plb_t *plb;
-
-    plb = opaque;
-    switch (dcrn) {
-    case PLB0_ACR:
-        /* We don't care about the actual parameters written as
-         * we don't manage any priorities on the bus
-         */
-        plb->acr = val & 0xF8000000;
-        break;
-    case PLB0_BEAR:
-        /* Read only */
-        break;
-    case PLB0_BESR:
-        /* Write-clear */
-        plb->besr &= ~val;
-        break;
-    }
-}
-
-static void ppc4xx_plb_reset (void *opaque)
-{
-    ppc4xx_plb_t *plb;
-
-    plb = opaque;
-    plb->acr = 0x00000000;
-    plb->bear = 0x00000000;
-    plb->besr = 0x00000000;
-}
-
-static void ppc4xx_plb_init(CPUPPCState *env)
-{
-    ppc4xx_plb_t *plb;
-
-    plb = g_malloc0(sizeof(ppc4xx_plb_t));
-    ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
-    ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
-    ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
-    qemu_register_reset(ppc4xx_plb_reset, plb);
-}
-
-/*****************************************************************************/
-/* PLB to OPB bridge */
-enum {
-    POB0_BESR0 = 0x0A0,
-    POB0_BESR1 = 0x0A2,
-    POB0_BEAR  = 0x0A4,
-};
-
-typedef struct ppc4xx_pob_t ppc4xx_pob_t;
-struct ppc4xx_pob_t {
-    uint32_t bear;
-    uint32_t besr0;
-    uint32_t besr1;
-};
-
-static uint32_t dcr_read_pob (void *opaque, int dcrn)
-{
-    ppc4xx_pob_t *pob;
-    uint32_t ret;
-
-    pob = opaque;
-    switch (dcrn) {
-    case POB0_BEAR:
-        ret = pob->bear;
-        break;
-    case POB0_BESR0:
-        ret = pob->besr0;
-        break;
-    case POB0_BESR1:
-        ret = pob->besr1;
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_pob (void *opaque, int dcrn, uint32_t val)
-{
-    ppc4xx_pob_t *pob;
-
-    pob = opaque;
-    switch (dcrn) {
-    case POB0_BEAR:
-        /* Read only */
-        break;
-    case POB0_BESR0:
-        /* Write-clear */
-        pob->besr0 &= ~val;
-        break;
-    case POB0_BESR1:
-        /* Write-clear */
-        pob->besr1 &= ~val;
-        break;
-    }
-}
-
-static void ppc4xx_pob_reset (void *opaque)
-{
-    ppc4xx_pob_t *pob;
-
-    pob = opaque;
-    /* No error */
-    pob->bear = 0x00000000;
-    pob->besr0 = 0x0000000;
-    pob->besr1 = 0x0000000;
-}
-
-static void ppc4xx_pob_init(CPUPPCState *env)
-{
-    ppc4xx_pob_t *pob;
-
-    pob = g_malloc0(sizeof(ppc4xx_pob_t));
-    ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob);
-    ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob);
-    ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob);
-    qemu_register_reset(ppc4xx_pob_reset, pob);
-}
-
-/*****************************************************************************/
-/* OPB arbitrer */
-typedef struct ppc4xx_opba_t ppc4xx_opba_t;
-struct ppc4xx_opba_t {
-    MemoryRegion io;
-    uint8_t cr;
-    uint8_t pr;
-};
-
-static uint32_t opba_readb (void *opaque, hwaddr addr)
-{
-    ppc4xx_opba_t *opba;
-    uint32_t ret;
-
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    opba = opaque;
-    switch (addr) {
-    case 0x00:
-        ret = opba->cr;
-        break;
-    case 0x01:
-        ret = opba->pr;
-        break;
-    default:
-        ret = 0x00;
-        break;
-    }
-
-    return ret;
-}
-
-static void opba_writeb (void *opaque,
-                         hwaddr addr, uint32_t value)
-{
-    ppc4xx_opba_t *opba;
-
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    opba = opaque;
-    switch (addr) {
-    case 0x00:
-        opba->cr = value & 0xF8;
-        break;
-    case 0x01:
-        opba->pr = value & 0xFF;
-        break;
-    default:
-        break;
-    }
-}
-
-static uint32_t opba_readw (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = opba_readb(opaque, addr) << 8;
-    ret |= opba_readb(opaque, addr + 1);
-
-    return ret;
-}
-
-static void opba_writew (void *opaque,
-                         hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    opba_writeb(opaque, addr, value >> 8);
-    opba_writeb(opaque, addr + 1, value);
-}
-
-static uint32_t opba_readl (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = opba_readb(opaque, addr) << 24;
-    ret |= opba_readb(opaque, addr + 1) << 16;
-
-    return ret;
-}
-
-static void opba_writel (void *opaque,
-                         hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    opba_writeb(opaque, addr, value >> 24);
-    opba_writeb(opaque, addr + 1, value >> 16);
-}
-
-static const MemoryRegionOps opba_ops = {
-    .old_mmio = {
-        .read = { opba_readb, opba_readw, opba_readl, },
-        .write = { opba_writeb, opba_writew, opba_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ppc4xx_opba_reset (void *opaque)
-{
-    ppc4xx_opba_t *opba;
-
-    opba = opaque;
-    opba->cr = 0x00; /* No dynamic priorities - park disabled */
-    opba->pr = 0x11;
-}
-
-static void ppc4xx_opba_init(hwaddr base)
-{
-    ppc4xx_opba_t *opba;
-
-    opba = g_malloc0(sizeof(ppc4xx_opba_t));
-#ifdef DEBUG_OPBA
-    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
-    memory_region_init_io(&opba->io, &opba_ops, opba, "opba", 0x002);
-    memory_region_add_subregion(get_system_memory(), base, &opba->io);
-    qemu_register_reset(ppc4xx_opba_reset, opba);
-}
-
-/*****************************************************************************/
-/* Code decompression controller */
-/* XXX: TODO */
-
-/*****************************************************************************/
-/* Peripheral controller */
-typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
-struct ppc4xx_ebc_t {
-    uint32_t addr;
-    uint32_t bcr[8];
-    uint32_t bap[8];
-    uint32_t bear;
-    uint32_t besr0;
-    uint32_t besr1;
-    uint32_t cfg;
-};
-
-enum {
-    EBC0_CFGADDR = 0x012,
-    EBC0_CFGDATA = 0x013,
-};
-
-static uint32_t dcr_read_ebc (void *opaque, int dcrn)
-{
-    ppc4xx_ebc_t *ebc;
-    uint32_t ret;
-
-    ebc = opaque;
-    switch (dcrn) {
-    case EBC0_CFGADDR:
-        ret = ebc->addr;
-        break;
-    case EBC0_CFGDATA:
-        switch (ebc->addr) {
-        case 0x00: /* B0CR */
-            ret = ebc->bcr[0];
-            break;
-        case 0x01: /* B1CR */
-            ret = ebc->bcr[1];
-            break;
-        case 0x02: /* B2CR */
-            ret = ebc->bcr[2];
-            break;
-        case 0x03: /* B3CR */
-            ret = ebc->bcr[3];
-            break;
-        case 0x04: /* B4CR */
-            ret = ebc->bcr[4];
-            break;
-        case 0x05: /* B5CR */
-            ret = ebc->bcr[5];
-            break;
-        case 0x06: /* B6CR */
-            ret = ebc->bcr[6];
-            break;
-        case 0x07: /* B7CR */
-            ret = ebc->bcr[7];
-            break;
-        case 0x10: /* B0AP */
-            ret = ebc->bap[0];
-            break;
-        case 0x11: /* B1AP */
-            ret = ebc->bap[1];
-            break;
-        case 0x12: /* B2AP */
-            ret = ebc->bap[2];
-            break;
-        case 0x13: /* B3AP */
-            ret = ebc->bap[3];
-            break;
-        case 0x14: /* B4AP */
-            ret = ebc->bap[4];
-            break;
-        case 0x15: /* B5AP */
-            ret = ebc->bap[5];
-            break;
-        case 0x16: /* B6AP */
-            ret = ebc->bap[6];
-            break;
-        case 0x17: /* B7AP */
-            ret = ebc->bap[7];
-            break;
-        case 0x20: /* BEAR */
-            ret = ebc->bear;
-            break;
-        case 0x21: /* BESR0 */
-            ret = ebc->besr0;
-            break;
-        case 0x22: /* BESR1 */
-            ret = ebc->besr1;
-            break;
-        case 0x23: /* CFG */
-            ret = ebc->cfg;
-            break;
-        default:
-            ret = 0x00000000;
-            break;
-        }
-        break;
-    default:
-        ret = 0x00000000;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_ebc (void *opaque, int dcrn, uint32_t val)
-{
-    ppc4xx_ebc_t *ebc;
-
-    ebc = opaque;
-    switch (dcrn) {
-    case EBC0_CFGADDR:
-        ebc->addr = val;
-        break;
-    case EBC0_CFGDATA:
-        switch (ebc->addr) {
-        case 0x00: /* B0CR */
-            break;
-        case 0x01: /* B1CR */
-            break;
-        case 0x02: /* B2CR */
-            break;
-        case 0x03: /* B3CR */
-            break;
-        case 0x04: /* B4CR */
-            break;
-        case 0x05: /* B5CR */
-            break;
-        case 0x06: /* B6CR */
-            break;
-        case 0x07: /* B7CR */
-            break;
-        case 0x10: /* B0AP */
-            break;
-        case 0x11: /* B1AP */
-            break;
-        case 0x12: /* B2AP */
-            break;
-        case 0x13: /* B3AP */
-            break;
-        case 0x14: /* B4AP */
-            break;
-        case 0x15: /* B5AP */
-            break;
-        case 0x16: /* B6AP */
-            break;
-        case 0x17: /* B7AP */
-            break;
-        case 0x20: /* BEAR */
-            break;
-        case 0x21: /* BESR0 */
-            break;
-        case 0x22: /* BESR1 */
-            break;
-        case 0x23: /* CFG */
-            break;
-        default:
-            break;
-        }
-        break;
-    default:
-        break;
-    }
-}
-
-static void ebc_reset (void *opaque)
-{
-    ppc4xx_ebc_t *ebc;
-    int i;
-
-    ebc = opaque;
-    ebc->addr = 0x00000000;
-    ebc->bap[0] = 0x7F8FFE80;
-    ebc->bcr[0] = 0xFFE28000;
-    for (i = 0; i < 8; i++) {
-        ebc->bap[i] = 0x00000000;
-        ebc->bcr[i] = 0x00000000;
-    }
-    ebc->besr0 = 0x00000000;
-    ebc->besr1 = 0x00000000;
-    ebc->cfg = 0x80400000;
-}
-
-static void ppc405_ebc_init(CPUPPCState *env)
-{
-    ppc4xx_ebc_t *ebc;
-
-    ebc = g_malloc0(sizeof(ppc4xx_ebc_t));
-    qemu_register_reset(&ebc_reset, ebc);
-    ppc_dcr_register(env, EBC0_CFGADDR,
-                     ebc, &dcr_read_ebc, &dcr_write_ebc);
-    ppc_dcr_register(env, EBC0_CFGDATA,
-                     ebc, &dcr_read_ebc, &dcr_write_ebc);
-}
-
-/*****************************************************************************/
-/* DMA controller */
-enum {
-    DMA0_CR0 = 0x100,
-    DMA0_CT0 = 0x101,
-    DMA0_DA0 = 0x102,
-    DMA0_SA0 = 0x103,
-    DMA0_SG0 = 0x104,
-    DMA0_CR1 = 0x108,
-    DMA0_CT1 = 0x109,
-    DMA0_DA1 = 0x10A,
-    DMA0_SA1 = 0x10B,
-    DMA0_SG1 = 0x10C,
-    DMA0_CR2 = 0x110,
-    DMA0_CT2 = 0x111,
-    DMA0_DA2 = 0x112,
-    DMA0_SA2 = 0x113,
-    DMA0_SG2 = 0x114,
-    DMA0_CR3 = 0x118,
-    DMA0_CT3 = 0x119,
-    DMA0_DA3 = 0x11A,
-    DMA0_SA3 = 0x11B,
-    DMA0_SG3 = 0x11C,
-    DMA0_SR  = 0x120,
-    DMA0_SGC = 0x123,
-    DMA0_SLP = 0x125,
-    DMA0_POL = 0x126,
-};
-
-typedef struct ppc405_dma_t ppc405_dma_t;
-struct ppc405_dma_t {
-    qemu_irq irqs[4];
-    uint32_t cr[4];
-    uint32_t ct[4];
-    uint32_t da[4];
-    uint32_t sa[4];
-    uint32_t sg[4];
-    uint32_t sr;
-    uint32_t sgc;
-    uint32_t slp;
-    uint32_t pol;
-};
-
-static uint32_t dcr_read_dma (void *opaque, int dcrn)
-{
-    return 0;
-}
-
-static void dcr_write_dma (void *opaque, int dcrn, uint32_t val)
-{
-}
-
-static void ppc405_dma_reset (void *opaque)
-{
-    ppc405_dma_t *dma;
-    int i;
-
-    dma = opaque;
-    for (i = 0; i < 4; i++) {
-        dma->cr[i] = 0x00000000;
-        dma->ct[i] = 0x00000000;
-        dma->da[i] = 0x00000000;
-        dma->sa[i] = 0x00000000;
-        dma->sg[i] = 0x00000000;
-    }
-    dma->sr = 0x00000000;
-    dma->sgc = 0x00000000;
-    dma->slp = 0x7C000000;
-    dma->pol = 0x00000000;
-}
-
-static void ppc405_dma_init(CPUPPCState *env, qemu_irq irqs[4])
-{
-    ppc405_dma_t *dma;
-
-    dma = g_malloc0(sizeof(ppc405_dma_t));
-    memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq));
-    qemu_register_reset(&ppc405_dma_reset, dma);
-    ppc_dcr_register(env, DMA0_CR0,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CT0,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_DA0,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SA0,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SG0,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CR1,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CT1,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_DA1,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SA1,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SG1,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CR2,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CT2,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_DA2,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SA2,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SG2,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CR3,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CT3,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_DA3,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SA3,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SG3,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SR,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SGC,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SLP,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_POL,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-}
-
-/*****************************************************************************/
-/* GPIO */
-typedef struct ppc405_gpio_t ppc405_gpio_t;
-struct ppc405_gpio_t {
-    MemoryRegion io;
-    uint32_t or;
-    uint32_t tcr;
-    uint32_t osrh;
-    uint32_t osrl;
-    uint32_t tsrh;
-    uint32_t tsrl;
-    uint32_t odr;
-    uint32_t ir;
-    uint32_t rr1;
-    uint32_t isr1h;
-    uint32_t isr1l;
-};
-
-static uint32_t ppc405_gpio_readb (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-
-    return 0;
-}
-
-static void ppc405_gpio_writeb (void *opaque,
-                                hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-}
-
-static uint32_t ppc405_gpio_readw (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-
-    return 0;
-}
-
-static void ppc405_gpio_writew (void *opaque,
-                                hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-}
-
-static uint32_t ppc405_gpio_readl (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-
-    return 0;
-}
-
-static void ppc405_gpio_writel (void *opaque,
-                                hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-}
-
-static const MemoryRegionOps ppc405_gpio_ops = {
-    .old_mmio = {
-        .read = { ppc405_gpio_readb, ppc405_gpio_readw, ppc405_gpio_readl, },
-        .write = { ppc405_gpio_writeb, ppc405_gpio_writew, ppc405_gpio_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ppc405_gpio_reset (void *opaque)
-{
-}
-
-static void ppc405_gpio_init(hwaddr base)
-{
-    ppc405_gpio_t *gpio;
-
-    gpio = g_malloc0(sizeof(ppc405_gpio_t));
-#ifdef DEBUG_GPIO
-    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
-    memory_region_init_io(&gpio->io, &ppc405_gpio_ops, gpio, "pgio", 0x038);
-    memory_region_add_subregion(get_system_memory(), base, &gpio->io);
-    qemu_register_reset(&ppc405_gpio_reset, gpio);
-}
-
-/*****************************************************************************/
-/* On Chip Memory */
-enum {
-    OCM0_ISARC   = 0x018,
-    OCM0_ISACNTL = 0x019,
-    OCM0_DSARC   = 0x01A,
-    OCM0_DSACNTL = 0x01B,
-};
-
-typedef struct ppc405_ocm_t ppc405_ocm_t;
-struct ppc405_ocm_t {
-    MemoryRegion ram;
-    MemoryRegion isarc_ram;
-    MemoryRegion dsarc_ram;
-    uint32_t isarc;
-    uint32_t isacntl;
-    uint32_t dsarc;
-    uint32_t dsacntl;
-};
-
-static void ocm_update_mappings (ppc405_ocm_t *ocm,
-                                 uint32_t isarc, uint32_t isacntl,
-                                 uint32_t dsarc, uint32_t dsacntl)
-{
-#ifdef DEBUG_OCM
-    printf("OCM update ISA %08" PRIx32 " %08" PRIx32 " (%08" PRIx32
-           " %08" PRIx32 ") DSA %08" PRIx32 " %08" PRIx32
-           " (%08" PRIx32 " %08" PRIx32 ")\n",
-           isarc, isacntl, dsarc, dsacntl,
-           ocm->isarc, ocm->isacntl, ocm->dsarc, ocm->dsacntl);
-#endif
-    if (ocm->isarc != isarc ||
-        (ocm->isacntl & 0x80000000) != (isacntl & 0x80000000)) {
-        if (ocm->isacntl & 0x80000000) {
-            /* Unmap previously assigned memory region */
-            printf("OCM unmap ISA %08" PRIx32 "\n", ocm->isarc);
-            memory_region_del_subregion(get_system_memory(), &ocm->isarc_ram);
-        }
-        if (isacntl & 0x80000000) {
-            /* Map new instruction memory region */
-#ifdef DEBUG_OCM
-            printf("OCM map ISA %08" PRIx32 "\n", isarc);
-#endif
-            memory_region_add_subregion(get_system_memory(), isarc,
-                                        &ocm->isarc_ram);
-        }
-    }
-    if (ocm->dsarc != dsarc ||
-        (ocm->dsacntl & 0x80000000) != (dsacntl & 0x80000000)) {
-        if (ocm->dsacntl & 0x80000000) {
-            /* Beware not to unmap the region we just mapped */
-            if (!(isacntl & 0x80000000) || ocm->dsarc != isarc) {
-                /* Unmap previously assigned memory region */
-#ifdef DEBUG_OCM
-                printf("OCM unmap DSA %08" PRIx32 "\n", ocm->dsarc);
-#endif
-                memory_region_del_subregion(get_system_memory(),
-                                            &ocm->dsarc_ram);
-            }
-        }
-        if (dsacntl & 0x80000000) {
-            /* Beware not to remap the region we just mapped */
-            if (!(isacntl & 0x80000000) || dsarc != isarc) {
-                /* Map new data memory region */
-#ifdef DEBUG_OCM
-                printf("OCM map DSA %08" PRIx32 "\n", dsarc);
-#endif
-                memory_region_add_subregion(get_system_memory(), dsarc,
-                                            &ocm->dsarc_ram);
-            }
-        }
-    }
-}
-
-static uint32_t dcr_read_ocm (void *opaque, int dcrn)
-{
-    ppc405_ocm_t *ocm;
-    uint32_t ret;
-
-    ocm = opaque;
-    switch (dcrn) {
-    case OCM0_ISARC:
-        ret = ocm->isarc;
-        break;
-    case OCM0_ISACNTL:
-        ret = ocm->isacntl;
-        break;
-    case OCM0_DSARC:
-        ret = ocm->dsarc;
-        break;
-    case OCM0_DSACNTL:
-        ret = ocm->dsacntl;
-        break;
-    default:
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_ocm (void *opaque, int dcrn, uint32_t val)
-{
-    ppc405_ocm_t *ocm;
-    uint32_t isarc, dsarc, isacntl, dsacntl;
-
-    ocm = opaque;
-    isarc = ocm->isarc;
-    dsarc = ocm->dsarc;
-    isacntl = ocm->isacntl;
-    dsacntl = ocm->dsacntl;
-    switch (dcrn) {
-    case OCM0_ISARC:
-        isarc = val & 0xFC000000;
-        break;
-    case OCM0_ISACNTL:
-        isacntl = val & 0xC0000000;
-        break;
-    case OCM0_DSARC:
-        isarc = val & 0xFC000000;
-        break;
-    case OCM0_DSACNTL:
-        isacntl = val & 0xC0000000;
-        break;
-    }
-    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
-    ocm->isarc = isarc;
-    ocm->dsarc = dsarc;
-    ocm->isacntl = isacntl;
-    ocm->dsacntl = dsacntl;
-}
-
-static void ocm_reset (void *opaque)
-{
-    ppc405_ocm_t *ocm;
-    uint32_t isarc, dsarc, isacntl, dsacntl;
-
-    ocm = opaque;
-    isarc = 0x00000000;
-    isacntl = 0x00000000;
-    dsarc = 0x00000000;
-    dsacntl = 0x00000000;
-    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
-    ocm->isarc = isarc;
-    ocm->dsarc = dsarc;
-    ocm->isacntl = isacntl;
-    ocm->dsacntl = dsacntl;
-}
-
-static void ppc405_ocm_init(CPUPPCState *env)
-{
-    ppc405_ocm_t *ocm;
-
-    ocm = g_malloc0(sizeof(ppc405_ocm_t));
-    /* XXX: Size is 4096 or 0x04000000 */
-    memory_region_init_ram(&ocm->isarc_ram, "ppc405.ocm", 4096);
-    vmstate_register_ram_global(&ocm->isarc_ram);
-    memory_region_init_alias(&ocm->dsarc_ram, "ppc405.dsarc", &ocm->isarc_ram,
-                             0, 4096);
-    qemu_register_reset(&ocm_reset, ocm);
-    ppc_dcr_register(env, OCM0_ISARC,
-                     ocm, &dcr_read_ocm, &dcr_write_ocm);
-    ppc_dcr_register(env, OCM0_ISACNTL,
-                     ocm, &dcr_read_ocm, &dcr_write_ocm);
-    ppc_dcr_register(env, OCM0_DSARC,
-                     ocm, &dcr_read_ocm, &dcr_write_ocm);
-    ppc_dcr_register(env, OCM0_DSACNTL,
-                     ocm, &dcr_read_ocm, &dcr_write_ocm);
-}
-
-/*****************************************************************************/
-/* I2C controller */
-typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
-struct ppc4xx_i2c_t {
-    qemu_irq irq;
-    MemoryRegion iomem;
-    uint8_t mdata;
-    uint8_t lmadr;
-    uint8_t hmadr;
-    uint8_t cntl;
-    uint8_t mdcntl;
-    uint8_t sts;
-    uint8_t extsts;
-    uint8_t sdata;
-    uint8_t lsadr;
-    uint8_t hsadr;
-    uint8_t clkdiv;
-    uint8_t intrmsk;
-    uint8_t xfrcnt;
-    uint8_t xtcntlss;
-    uint8_t directcntl;
-};
-
-static uint32_t ppc4xx_i2c_readb (void *opaque, hwaddr addr)
-{
-    ppc4xx_i2c_t *i2c;
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    i2c = opaque;
-    switch (addr) {
-    case 0x00:
-        //        i2c_readbyte(&i2c->mdata);
-        ret = i2c->mdata;
-        break;
-    case 0x02:
-        ret = i2c->sdata;
-        break;
-    case 0x04:
-        ret = i2c->lmadr;
-        break;
-    case 0x05:
-        ret = i2c->hmadr;
-        break;
-    case 0x06:
-        ret = i2c->cntl;
-        break;
-    case 0x07:
-        ret = i2c->mdcntl;
-        break;
-    case 0x08:
-        ret = i2c->sts;
-        break;
-    case 0x09:
-        ret = i2c->extsts;
-        break;
-    case 0x0A:
-        ret = i2c->lsadr;
-        break;
-    case 0x0B:
-        ret = i2c->hsadr;
-        break;
-    case 0x0C:
-        ret = i2c->clkdiv;
-        break;
-    case 0x0D:
-        ret = i2c->intrmsk;
-        break;
-    case 0x0E:
-        ret = i2c->xfrcnt;
-        break;
-    case 0x0F:
-        ret = i2c->xtcntlss;
-        break;
-    case 0x10:
-        ret = i2c->directcntl;
-        break;
-    default:
-        ret = 0x00;
-        break;
-    }
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
-#endif
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writeb (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    ppc4xx_i2c_t *i2c;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    i2c = opaque;
-    switch (addr) {
-    case 0x00:
-        i2c->mdata = value;
-        //        i2c_sendbyte(&i2c->mdata);
-        break;
-    case 0x02:
-        i2c->sdata = value;
-        break;
-    case 0x04:
-        i2c->lmadr = value;
-        break;
-    case 0x05:
-        i2c->hmadr = value;
-        break;
-    case 0x06:
-        i2c->cntl = value;
-        break;
-    case 0x07:
-        i2c->mdcntl = value & 0xDF;
-        break;
-    case 0x08:
-        i2c->sts &= ~(value & 0x0A);
-        break;
-    case 0x09:
-        i2c->extsts &= ~(value & 0x8F);
-        break;
-    case 0x0A:
-        i2c->lsadr = value;
-        break;
-    case 0x0B:
-        i2c->hsadr = value;
-        break;
-    case 0x0C:
-        i2c->clkdiv = value;
-        break;
-    case 0x0D:
-        i2c->intrmsk = value;
-        break;
-    case 0x0E:
-        i2c->xfrcnt = value & 0x77;
-        break;
-    case 0x0F:
-        i2c->xtcntlss = value;
-        break;
-    case 0x10:
-        i2c->directcntl = value & 0x7;
-        break;
-    }
-}
-
-static uint32_t ppc4xx_i2c_readw (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writew (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value);
-}
-
-static uint32_t ppc4xx_i2c_readl (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writel (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
-    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 3, value);
-}
-
-static const MemoryRegionOps i2c_ops = {
-    .old_mmio = {
-        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
-        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ppc4xx_i2c_reset (void *opaque)
-{
-    ppc4xx_i2c_t *i2c;
-
-    i2c = opaque;
-    i2c->mdata = 0x00;
-    i2c->sdata = 0x00;
-    i2c->cntl = 0x00;
-    i2c->mdcntl = 0x00;
-    i2c->sts = 0x00;
-    i2c->extsts = 0x00;
-    i2c->clkdiv = 0x00;
-    i2c->xfrcnt = 0x00;
-    i2c->directcntl = 0x0F;
-}
-
-static void ppc405_i2c_init(hwaddr base, qemu_irq irq)
-{
-    ppc4xx_i2c_t *i2c;
-
-    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
-    i2c->irq = irq;
-#ifdef DEBUG_I2C
-    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
-    memory_region_init_io(&i2c->iomem, &i2c_ops, i2c, "i2c", 0x011);
-    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
-    qemu_register_reset(ppc4xx_i2c_reset, i2c);
-}
-
-/*****************************************************************************/
-/* General purpose timers */
-typedef struct ppc4xx_gpt_t ppc4xx_gpt_t;
-struct ppc4xx_gpt_t {
-    MemoryRegion iomem;
-    int64_t tb_offset;
-    uint32_t tb_freq;
-    struct QEMUTimer *timer;
-    qemu_irq irqs[5];
-    uint32_t oe;
-    uint32_t ol;
-    uint32_t im;
-    uint32_t is;
-    uint32_t ie;
-    uint32_t comp[5];
-    uint32_t mask[5];
-};
-
-static uint32_t ppc4xx_gpt_readb (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPT
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    /* XXX: generate a bus fault */
-    return -1;
-}
-
-static void ppc4xx_gpt_writeb (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    /* XXX: generate a bus fault */
-}
-
-static uint32_t ppc4xx_gpt_readw (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPT
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    /* XXX: generate a bus fault */
-    return -1;
-}
-
-static void ppc4xx_gpt_writew (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    /* XXX: generate a bus fault */
-}
-
-static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n)
-{
-    /* XXX: TODO */
-    return 0;
-}
-
-static void ppc4xx_gpt_set_output (ppc4xx_gpt_t *gpt, int n, int level)
-{
-    /* XXX: TODO */
-}
-
-static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt)
-{
-    uint32_t mask;
-    int i;
-
-    mask = 0x80000000;
-    for (i = 0; i < 5; i++) {
-        if (gpt->oe & mask) {
-            /* Output is enabled */
-            if (ppc4xx_gpt_compare(gpt, i)) {
-                /* Comparison is OK */
-                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask);
-            } else {
-                /* Comparison is KO */
-                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask ? 0 : 1);
-            }
-        }
-        mask = mask >> 1;
-    }
-}
-
-static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt)
-{
-    uint32_t mask;
-    int i;
-
-    mask = 0x00008000;
-    for (i = 0; i < 5; i++) {
-        if (gpt->is & gpt->im & mask)
-            qemu_irq_raise(gpt->irqs[i]);
-        else
-            qemu_irq_lower(gpt->irqs[i]);
-        mask = mask >> 1;
-    }
-}
-
-static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt)
-{
-    /* XXX: TODO */
-}
-
-static uint32_t ppc4xx_gpt_readl (void *opaque, hwaddr addr)
-{
-    ppc4xx_gpt_t *gpt;
-    uint32_t ret;
-    int idx;
-
-#ifdef DEBUG_GPT
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    gpt = opaque;
-    switch (addr) {
-    case 0x00:
-        /* Time base counter */
-        ret = muldiv64(qemu_get_clock_ns(vm_clock) + gpt->tb_offset,
-                       gpt->tb_freq, get_ticks_per_sec());
-        break;
-    case 0x10:
-        /* Output enable */
-        ret = gpt->oe;
-        break;
-    case 0x14:
-        /* Output level */
-        ret = gpt->ol;
-        break;
-    case 0x18:
-        /* Interrupt mask */
-        ret = gpt->im;
-        break;
-    case 0x1C:
-    case 0x20:
-        /* Interrupt status */
-        ret = gpt->is;
-        break;
-    case 0x24:
-        /* Interrupt enable */
-        ret = gpt->ie;
-        break;
-    case 0x80 ... 0x90:
-        /* Compare timer */
-        idx = (addr - 0x80) >> 2;
-        ret = gpt->comp[idx];
-        break;
-    case 0xC0 ... 0xD0:
-        /* Compare mask */
-        idx = (addr - 0xC0) >> 2;
-        ret = gpt->mask[idx];
-        break;
-    default:
-        ret = -1;
-        break;
-    }
-
-    return ret;
-}
-
-static void ppc4xx_gpt_writel (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    ppc4xx_gpt_t *gpt;
-    int idx;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    gpt = opaque;
-    switch (addr) {
-    case 0x00:
-        /* Time base counter */
-        gpt->tb_offset = muldiv64(value, get_ticks_per_sec(), gpt->tb_freq)
-            - qemu_get_clock_ns(vm_clock);
-        ppc4xx_gpt_compute_timer(gpt);
-        break;
-    case 0x10:
-        /* Output enable */
-        gpt->oe = value & 0xF8000000;
-        ppc4xx_gpt_set_outputs(gpt);
-        break;
-    case 0x14:
-        /* Output level */
-        gpt->ol = value & 0xF8000000;
-        ppc4xx_gpt_set_outputs(gpt);
-        break;
-    case 0x18:
-        /* Interrupt mask */
-        gpt->im = value & 0x0000F800;
-        break;
-    case 0x1C:
-        /* Interrupt status set */
-        gpt->is |= value & 0x0000F800;
-        ppc4xx_gpt_set_irqs(gpt);
-        break;
-    case 0x20:
-        /* Interrupt status clear */
-        gpt->is &= ~(value & 0x0000F800);
-        ppc4xx_gpt_set_irqs(gpt);
-        break;
-    case 0x24:
-        /* Interrupt enable */
-        gpt->ie = value & 0x0000F800;
-        ppc4xx_gpt_set_irqs(gpt);
-        break;
-    case 0x80 ... 0x90:
-        /* Compare timer */
-        idx = (addr - 0x80) >> 2;
-        gpt->comp[idx] = value & 0xF8000000;
-        ppc4xx_gpt_compute_timer(gpt);
-        break;
-    case 0xC0 ... 0xD0:
-        /* Compare mask */
-        idx = (addr - 0xC0) >> 2;
-        gpt->mask[idx] = value & 0xF8000000;
-        ppc4xx_gpt_compute_timer(gpt);
-        break;
-    }
-}
-
-static const MemoryRegionOps gpt_ops = {
-    .old_mmio = {
-        .read = { ppc4xx_gpt_readb, ppc4xx_gpt_readw, ppc4xx_gpt_readl, },
-        .write = { ppc4xx_gpt_writeb, ppc4xx_gpt_writew, ppc4xx_gpt_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ppc4xx_gpt_cb (void *opaque)
-{
-    ppc4xx_gpt_t *gpt;
-
-    gpt = opaque;
-    ppc4xx_gpt_set_irqs(gpt);
-    ppc4xx_gpt_set_outputs(gpt);
-    ppc4xx_gpt_compute_timer(gpt);
-}
-
-static void ppc4xx_gpt_reset (void *opaque)
-{
-    ppc4xx_gpt_t *gpt;
-    int i;
-
-    gpt = opaque;
-    qemu_del_timer(gpt->timer);
-    gpt->oe = 0x00000000;
-    gpt->ol = 0x00000000;
-    gpt->im = 0x00000000;
-    gpt->is = 0x00000000;
-    gpt->ie = 0x00000000;
-    for (i = 0; i < 5; i++) {
-        gpt->comp[i] = 0x00000000;
-        gpt->mask[i] = 0x00000000;
-    }
-}
-
-static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5])
-{
-    ppc4xx_gpt_t *gpt;
-    int i;
-
-    gpt = g_malloc0(sizeof(ppc4xx_gpt_t));
-    for (i = 0; i < 5; i++) {
-        gpt->irqs[i] = irqs[i];
-    }
-    gpt->timer = qemu_new_timer_ns(vm_clock, &ppc4xx_gpt_cb, gpt);
-#ifdef DEBUG_GPT
-    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
-    memory_region_init_io(&gpt->iomem, &gpt_ops, gpt, "gpt", 0x0d4);
-    memory_region_add_subregion(get_system_memory(), base, &gpt->iomem);
-    qemu_register_reset(ppc4xx_gpt_reset, gpt);
-}
-
-/*****************************************************************************/
-/* MAL */
-enum {
-    MAL0_CFG      = 0x180,
-    MAL0_ESR      = 0x181,
-    MAL0_IER      = 0x182,
-    MAL0_TXCASR   = 0x184,
-    MAL0_TXCARR   = 0x185,
-    MAL0_TXEOBISR = 0x186,
-    MAL0_TXDEIR   = 0x187,
-    MAL0_RXCASR   = 0x190,
-    MAL0_RXCARR   = 0x191,
-    MAL0_RXEOBISR = 0x192,
-    MAL0_RXDEIR   = 0x193,
-    MAL0_TXCTP0R  = 0x1A0,
-    MAL0_TXCTP1R  = 0x1A1,
-    MAL0_TXCTP2R  = 0x1A2,
-    MAL0_TXCTP3R  = 0x1A3,
-    MAL0_RXCTP0R  = 0x1C0,
-    MAL0_RXCTP1R  = 0x1C1,
-    MAL0_RCBS0    = 0x1E0,
-    MAL0_RCBS1    = 0x1E1,
-};
-
-typedef struct ppc40x_mal_t ppc40x_mal_t;
-struct ppc40x_mal_t {
-    qemu_irq irqs[4];
-    uint32_t cfg;
-    uint32_t esr;
-    uint32_t ier;
-    uint32_t txcasr;
-    uint32_t txcarr;
-    uint32_t txeobisr;
-    uint32_t txdeir;
-    uint32_t rxcasr;
-    uint32_t rxcarr;
-    uint32_t rxeobisr;
-    uint32_t rxdeir;
-    uint32_t txctpr[4];
-    uint32_t rxctpr[2];
-    uint32_t rcbs[2];
-};
-
-static void ppc40x_mal_reset (void *opaque);
-
-static uint32_t dcr_read_mal (void *opaque, int dcrn)
-{
-    ppc40x_mal_t *mal;
-    uint32_t ret;
-
-    mal = opaque;
-    switch (dcrn) {
-    case MAL0_CFG:
-        ret = mal->cfg;
-        break;
-    case MAL0_ESR:
-        ret = mal->esr;
-        break;
-    case MAL0_IER:
-        ret = mal->ier;
-        break;
-    case MAL0_TXCASR:
-        ret = mal->txcasr;
-        break;
-    case MAL0_TXCARR:
-        ret = mal->txcarr;
-        break;
-    case MAL0_TXEOBISR:
-        ret = mal->txeobisr;
-        break;
-    case MAL0_TXDEIR:
-        ret = mal->txdeir;
-        break;
-    case MAL0_RXCASR:
-        ret = mal->rxcasr;
-        break;
-    case MAL0_RXCARR:
-        ret = mal->rxcarr;
-        break;
-    case MAL0_RXEOBISR:
-        ret = mal->rxeobisr;
-        break;
-    case MAL0_RXDEIR:
-        ret = mal->rxdeir;
-        break;
-    case MAL0_TXCTP0R:
-        ret = mal->txctpr[0];
-        break;
-    case MAL0_TXCTP1R:
-        ret = mal->txctpr[1];
-        break;
-    case MAL0_TXCTP2R:
-        ret = mal->txctpr[2];
-        break;
-    case MAL0_TXCTP3R:
-        ret = mal->txctpr[3];
-        break;
-    case MAL0_RXCTP0R:
-        ret = mal->rxctpr[0];
-        break;
-    case MAL0_RXCTP1R:
-        ret = mal->rxctpr[1];
-        break;
-    case MAL0_RCBS0:
-        ret = mal->rcbs[0];
-        break;
-    case MAL0_RCBS1:
-        ret = mal->rcbs[1];
-        break;
-    default:
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_mal (void *opaque, int dcrn, uint32_t val)
-{
-    ppc40x_mal_t *mal;
-    int idx;
-
-    mal = opaque;
-    switch (dcrn) {
-    case MAL0_CFG:
-        if (val & 0x80000000)
-            ppc40x_mal_reset(mal);
-        mal->cfg = val & 0x00FFC087;
-        break;
-    case MAL0_ESR:
-        /* Read/clear */
-        mal->esr &= ~val;
-        break;
-    case MAL0_IER:
-        mal->ier = val & 0x0000001F;
-        break;
-    case MAL0_TXCASR:
-        mal->txcasr = val & 0xF0000000;
-        break;
-    case MAL0_TXCARR:
-        mal->txcarr = val & 0xF0000000;
-        break;
-    case MAL0_TXEOBISR:
-        /* Read/clear */
-        mal->txeobisr &= ~val;
-        break;
-    case MAL0_TXDEIR:
-        /* Read/clear */
-        mal->txdeir &= ~val;
-        break;
-    case MAL0_RXCASR:
-        mal->rxcasr = val & 0xC0000000;
-        break;
-    case MAL0_RXCARR:
-        mal->rxcarr = val & 0xC0000000;
-        break;
-    case MAL0_RXEOBISR:
-        /* Read/clear */
-        mal->rxeobisr &= ~val;
-        break;
-    case MAL0_RXDEIR:
-        /* Read/clear */
-        mal->rxdeir &= ~val;
-        break;
-    case MAL0_TXCTP0R:
-        idx = 0;
-        goto update_tx_ptr;
-    case MAL0_TXCTP1R:
-        idx = 1;
-        goto update_tx_ptr;
-    case MAL0_TXCTP2R:
-        idx = 2;
-        goto update_tx_ptr;
-    case MAL0_TXCTP3R:
-        idx = 3;
-    update_tx_ptr:
-        mal->txctpr[idx] = val;
-        break;
-    case MAL0_RXCTP0R:
-        idx = 0;
-        goto update_rx_ptr;
-    case MAL0_RXCTP1R:
-        idx = 1;
-    update_rx_ptr:
-        mal->rxctpr[idx] = val;
-        break;
-    case MAL0_RCBS0:
-        idx = 0;
-        goto update_rx_size;
-    case MAL0_RCBS1:
-        idx = 1;
-    update_rx_size:
-        mal->rcbs[idx] = val & 0x000000FF;
-        break;
-    }
-}
-
-static void ppc40x_mal_reset (void *opaque)
-{
-    ppc40x_mal_t *mal;
-
-    mal = opaque;
-    mal->cfg = 0x0007C000;
-    mal->esr = 0x00000000;
-    mal->ier = 0x00000000;
-    mal->rxcasr = 0x00000000;
-    mal->rxdeir = 0x00000000;
-    mal->rxeobisr = 0x00000000;
-    mal->txcasr = 0x00000000;
-    mal->txdeir = 0x00000000;
-    mal->txeobisr = 0x00000000;
-}
-
-static void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
-{
-    ppc40x_mal_t *mal;
-    int i;
-
-    mal = g_malloc0(sizeof(ppc40x_mal_t));
-    for (i = 0; i < 4; i++)
-        mal->irqs[i] = irqs[i];
-    qemu_register_reset(&ppc40x_mal_reset, mal);
-    ppc_dcr_register(env, MAL0_CFG,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_ESR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_IER,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCASR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCARR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXEOBISR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXDEIR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCASR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCARR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXEOBISR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXDEIR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP2R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP3R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS0,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS1,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-}
-
-/*****************************************************************************/
-/* SPR */
-void ppc40x_core_reset(PowerPCCPU *cpu)
-{
-    CPUPPCState *env = &cpu->env;
-    target_ulong dbsr;
-
-    printf("Reset PowerPC core\n");
-    cpu_interrupt(env, CPU_INTERRUPT_RESET);
-    dbsr = env->spr[SPR_40x_DBSR];
-    dbsr &= ~0x00000300;
-    dbsr |= 0x00000100;
-    env->spr[SPR_40x_DBSR] = dbsr;
-}
-
-void ppc40x_chip_reset(PowerPCCPU *cpu)
-{
-    CPUPPCState *env = &cpu->env;
-    target_ulong dbsr;
-
-    printf("Reset PowerPC chip\n");
-    cpu_interrupt(env, CPU_INTERRUPT_RESET);
-    /* XXX: TODO reset all internal peripherals */
-    dbsr = env->spr[SPR_40x_DBSR];
-    dbsr &= ~0x00000300;
-    dbsr |= 0x00000200;
-    env->spr[SPR_40x_DBSR] = dbsr;
-}
-
-void ppc40x_system_reset(PowerPCCPU *cpu)
-{
-    printf("Reset PowerPC system\n");
-    qemu_system_reset_request();
-}
-
-void store_40x_dbcr0 (CPUPPCState *env, uint32_t val)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    switch ((val >> 28) & 0x3) {
-    case 0x0:
-        /* No action */
-        break;
-    case 0x1:
-        /* Core reset */
-        ppc40x_core_reset(cpu);
-        break;
-    case 0x2:
-        /* Chip reset */
-        ppc40x_chip_reset(cpu);
-        break;
-    case 0x3:
-        /* System reset */
-        ppc40x_system_reset(cpu);
-        break;
-    }
-}
-
-/*****************************************************************************/
-/* PowerPC 405CR */
-enum {
-    PPC405CR_CPC0_PLLMR  = 0x0B0,
-    PPC405CR_CPC0_CR0    = 0x0B1,
-    PPC405CR_CPC0_CR1    = 0x0B2,
-    PPC405CR_CPC0_PSR    = 0x0B4,
-    PPC405CR_CPC0_JTAGID = 0x0B5,
-    PPC405CR_CPC0_ER     = 0x0B9,
-    PPC405CR_CPC0_FR     = 0x0BA,
-    PPC405CR_CPC0_SR     = 0x0BB,
-};
-
-enum {
-    PPC405CR_CPU_CLK   = 0,
-    PPC405CR_TMR_CLK   = 1,
-    PPC405CR_PLB_CLK   = 2,
-    PPC405CR_SDRAM_CLK = 3,
-    PPC405CR_OPB_CLK   = 4,
-    PPC405CR_EXT_CLK   = 5,
-    PPC405CR_UART_CLK  = 6,
-    PPC405CR_CLK_NB    = 7,
-};
-
-typedef struct ppc405cr_cpc_t ppc405cr_cpc_t;
-struct ppc405cr_cpc_t {
-    clk_setup_t clk_setup[PPC405CR_CLK_NB];
-    uint32_t sysclk;
-    uint32_t psr;
-    uint32_t cr0;
-    uint32_t cr1;
-    uint32_t jtagid;
-    uint32_t pllmr;
-    uint32_t er;
-    uint32_t fr;
-};
-
-static void ppc405cr_clk_setup (ppc405cr_cpc_t *cpc)
-{
-    uint64_t VCO_out, PLL_out;
-    uint32_t CPU_clk, TMR_clk, SDRAM_clk, PLB_clk, OPB_clk, EXT_clk, UART_clk;
-    int M, D0, D1, D2;
-
-    D0 = ((cpc->pllmr >> 26) & 0x3) + 1; /* CBDV */
-    if (cpc->pllmr & 0x80000000) {
-        D1 = (((cpc->pllmr >> 20) - 1) & 0xF) + 1; /* FBDV */
-        D2 = 8 - ((cpc->pllmr >> 16) & 0x7); /* FWDVA */
-        M = D0 * D1 * D2;
-        VCO_out = cpc->sysclk * M;
-        if (VCO_out < 400000000 || VCO_out > 800000000) {
-            /* PLL cannot lock */
-            cpc->pllmr &= ~0x80000000;
-            goto bypass_pll;
-        }
-        PLL_out = VCO_out / D2;
-    } else {
-        /* Bypass PLL */
-    bypass_pll:
-        M = D0;
-        PLL_out = cpc->sysclk * M;
-    }
-    CPU_clk = PLL_out;
-    if (cpc->cr1 & 0x00800000)
-        TMR_clk = cpc->sysclk; /* Should have a separate clock */
-    else
-        TMR_clk = CPU_clk;
-    PLB_clk = CPU_clk / D0;
-    SDRAM_clk = PLB_clk;
-    D0 = ((cpc->pllmr >> 10) & 0x3) + 1;
-    OPB_clk = PLB_clk / D0;
-    D0 = ((cpc->pllmr >> 24) & 0x3) + 2;
-    EXT_clk = PLB_clk / D0;
-    D0 = ((cpc->cr0 >> 1) & 0x1F) + 1;
-    UART_clk = CPU_clk / D0;
-    /* Setup CPU clocks */
-    clk_setup(&cpc->clk_setup[PPC405CR_CPU_CLK], CPU_clk);
-    /* Setup time-base clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_TMR_CLK], TMR_clk);
-    /* Setup PLB clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_PLB_CLK], PLB_clk);
-    /* Setup SDRAM clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_SDRAM_CLK], SDRAM_clk);
-    /* Setup OPB clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_OPB_CLK], OPB_clk);
-    /* Setup external clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_EXT_CLK], EXT_clk);
-    /* Setup UART clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_UART_CLK], UART_clk);
-}
-
-static uint32_t dcr_read_crcpc (void *opaque, int dcrn)
-{
-    ppc405cr_cpc_t *cpc;
-    uint32_t ret;
-
-    cpc = opaque;
-    switch (dcrn) {
-    case PPC405CR_CPC0_PLLMR:
-        ret = cpc->pllmr;
-        break;
-    case PPC405CR_CPC0_CR0:
-        ret = cpc->cr0;
-        break;
-    case PPC405CR_CPC0_CR1:
-        ret = cpc->cr1;
-        break;
-    case PPC405CR_CPC0_PSR:
-        ret = cpc->psr;
-        break;
-    case PPC405CR_CPC0_JTAGID:
-        ret = cpc->jtagid;
-        break;
-    case PPC405CR_CPC0_ER:
-        ret = cpc->er;
-        break;
-    case PPC405CR_CPC0_FR:
-        ret = cpc->fr;
-        break;
-    case PPC405CR_CPC0_SR:
-        ret = ~(cpc->er | cpc->fr) & 0xFFFF0000;
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_crcpc (void *opaque, int dcrn, uint32_t val)
-{
-    ppc405cr_cpc_t *cpc;
-
-    cpc = opaque;
-    switch (dcrn) {
-    case PPC405CR_CPC0_PLLMR:
-        cpc->pllmr = val & 0xFFF77C3F;
-        break;
-    case PPC405CR_CPC0_CR0:
-        cpc->cr0 = val & 0x0FFFFFFE;
-        break;
-    case PPC405CR_CPC0_CR1:
-        cpc->cr1 = val & 0x00800000;
-        break;
-    case PPC405CR_CPC0_PSR:
-        /* Read-only */
-        break;
-    case PPC405CR_CPC0_JTAGID:
-        /* Read-only */
-        break;
-    case PPC405CR_CPC0_ER:
-        cpc->er = val & 0xBFFC0000;
-        break;
-    case PPC405CR_CPC0_FR:
-        cpc->fr = val & 0xBFFC0000;
-        break;
-    case PPC405CR_CPC0_SR:
-        /* Read-only */
-        break;
-    }
-}
-
-static void ppc405cr_cpc_reset (void *opaque)
-{
-    ppc405cr_cpc_t *cpc;
-    int D;
-
-    cpc = opaque;
-    /* Compute PLLMR value from PSR settings */
-    cpc->pllmr = 0x80000000;
-    /* PFWD */
-    switch ((cpc->psr >> 30) & 3) {
-    case 0:
-        /* Bypass */
-        cpc->pllmr &= ~0x80000000;
-        break;
-    case 1:
-        /* Divide by 3 */
-        cpc->pllmr |= 5 << 16;
-        break;
-    case 2:
-        /* Divide by 4 */
-        cpc->pllmr |= 4 << 16;
-        break;
-    case 3:
-        /* Divide by 6 */
-        cpc->pllmr |= 2 << 16;
-        break;
-    }
-    /* PFBD */
-    D = (cpc->psr >> 28) & 3;
-    cpc->pllmr |= (D + 1) << 20;
-    /* PT   */
-    D = (cpc->psr >> 25) & 7;
-    switch (D) {
-    case 0x2:
-        cpc->pllmr |= 0x13;
-        break;
-    case 0x4:
-        cpc->pllmr |= 0x15;
-        break;
-    case 0x5:
-        cpc->pllmr |= 0x16;
-        break;
-    default:
-        break;
-    }
-    /* PDC  */
-    D = (cpc->psr >> 23) & 3;
-    cpc->pllmr |= D << 26;
-    /* ODP  */
-    D = (cpc->psr >> 21) & 3;
-    cpc->pllmr |= D << 10;
-    /* EBPD */
-    D = (cpc->psr >> 17) & 3;
-    cpc->pllmr |= D << 24;
-    cpc->cr0 = 0x0000003C;
-    cpc->cr1 = 0x2B0D8800;
-    cpc->er = 0x00000000;
-    cpc->fr = 0x00000000;
-    ppc405cr_clk_setup(cpc);
-}
-
-static void ppc405cr_clk_init (ppc405cr_cpc_t *cpc)
-{
-    int D;
-
-    /* XXX: this should be read from IO pins */
-    cpc->psr = 0x00000000; /* 8 bits ROM */
-    /* PFWD */
-    D = 0x2; /* Divide by 4 */
-    cpc->psr |= D << 30;
-    /* PFBD */
-    D = 0x1; /* Divide by 2 */
-    cpc->psr |= D << 28;
-    /* PDC */
-    D = 0x1; /* Divide by 2 */
-    cpc->psr |= D << 23;
-    /* PT */
-    D = 0x5; /* M = 16 */
-    cpc->psr |= D << 25;
-    /* ODP */
-    D = 0x1; /* Divide by 2 */
-    cpc->psr |= D << 21;
-    /* EBDP */
-    D = 0x2; /* Divide by 4 */
-    cpc->psr |= D << 17;
-}
-
-static void ppc405cr_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[7],
-                               uint32_t sysclk)
-{
-    ppc405cr_cpc_t *cpc;
-
-    cpc = g_malloc0(sizeof(ppc405cr_cpc_t));
-    memcpy(cpc->clk_setup, clk_setup,
-           PPC405CR_CLK_NB * sizeof(clk_setup_t));
-    cpc->sysclk = sysclk;
-    cpc->jtagid = 0x42051049;
-    ppc_dcr_register(env, PPC405CR_CPC0_PSR, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_CR0, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_CR1, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_JTAGID, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_PLLMR, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_ER, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_FR, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_SR, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc405cr_clk_init(cpc);
-    qemu_register_reset(ppc405cr_cpc_reset, cpc);
-}
-
-CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
-                        MemoryRegion ram_memories[4],
-                        hwaddr ram_bases[4],
-                        hwaddr ram_sizes[4],
-                        uint32_t sysclk, qemu_irq **picp,
-                        int do_init)
-{
-    clk_setup_t clk_setup[PPC405CR_CLK_NB];
-    qemu_irq dma_irqs[4];
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    qemu_irq *pic, *irqs;
-
-    memset(clk_setup, 0, sizeof(clk_setup));
-    cpu = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
-                      &clk_setup[PPC405CR_TMR_CLK], sysclk);
-    env = &cpu->env;
-    /* Memory mapped devices registers */
-    /* PLB arbitrer */
-    ppc4xx_plb_init(env);
-    /* PLB to OPB bridge */
-    ppc4xx_pob_init(env);
-    /* OBP arbitrer */
-    ppc4xx_opba_init(0xef600600);
-    /* Universal interrupt controller */
-    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
-    irqs[PPCUIC_OUTPUT_INT] =
-        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
-    irqs[PPCUIC_OUTPUT_CINT] =
-        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
-    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
-    *picp = pic;
-    /* SDRAM controller */
-    ppc4xx_sdram_init(env, pic[14], 1, ram_memories,
-                      ram_bases, ram_sizes, do_init);
-    /* External bus controller */
-    ppc405_ebc_init(env);
-    /* DMA controller */
-    dma_irqs[0] = pic[26];
-    dma_irqs[1] = pic[25];
-    dma_irqs[2] = pic[24];
-    dma_irqs[3] = pic[23];
-    ppc405_dma_init(env, dma_irqs);
-    /* Serial ports */
-    if (serial_hds[0] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
-                       DEVICE_BIG_ENDIAN);
-    }
-    if (serial_hds[1] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
-                       DEVICE_BIG_ENDIAN);
-    }
-    /* IIC controller */
-    ppc405_i2c_init(0xef600500, pic[2]);
-    /* GPIO */
-    ppc405_gpio_init(0xef600700);
-    /* CPU control */
-    ppc405cr_cpc_init(env, clk_setup, sysclk);
-
-    return env;
-}
-
-/*****************************************************************************/
-/* PowerPC 405EP */
-/* CPU control */
-enum {
-    PPC405EP_CPC0_PLLMR0 = 0x0F0,
-    PPC405EP_CPC0_BOOT   = 0x0F1,
-    PPC405EP_CPC0_EPCTL  = 0x0F3,
-    PPC405EP_CPC0_PLLMR1 = 0x0F4,
-    PPC405EP_CPC0_UCR    = 0x0F5,
-    PPC405EP_CPC0_SRR    = 0x0F6,
-    PPC405EP_CPC0_JTAGID = 0x0F7,
-    PPC405EP_CPC0_PCI    = 0x0F9,
-#if 0
-    PPC405EP_CPC0_ER     = xxx,
-    PPC405EP_CPC0_FR     = xxx,
-    PPC405EP_CPC0_SR     = xxx,
-#endif
-};
-
-enum {
-    PPC405EP_CPU_CLK   = 0,
-    PPC405EP_PLB_CLK   = 1,
-    PPC405EP_OPB_CLK   = 2,
-    PPC405EP_EBC_CLK   = 3,
-    PPC405EP_MAL_CLK   = 4,
-    PPC405EP_PCI_CLK   = 5,
-    PPC405EP_UART0_CLK = 6,
-    PPC405EP_UART1_CLK = 7,
-    PPC405EP_CLK_NB    = 8,
-};
-
-typedef struct ppc405ep_cpc_t ppc405ep_cpc_t;
-struct ppc405ep_cpc_t {
-    uint32_t sysclk;
-    clk_setup_t clk_setup[PPC405EP_CLK_NB];
-    uint32_t boot;
-    uint32_t epctl;
-    uint32_t pllmr[2];
-    uint32_t ucr;
-    uint32_t srr;
-    uint32_t jtagid;
-    uint32_t pci;
-    /* Clock and power management */
-    uint32_t er;
-    uint32_t fr;
-    uint32_t sr;
-};
-
-static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc)
-{
-    uint32_t CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk;
-    uint32_t UART0_clk, UART1_clk;
-    uint64_t VCO_out, PLL_out;
-    int M, D;
-
-    VCO_out = 0;
-    if ((cpc->pllmr[1] & 0x80000000) && !(cpc->pllmr[1] & 0x40000000)) {
-        M = (((cpc->pllmr[1] >> 20) - 1) & 0xF) + 1; /* FBMUL */
-#ifdef DEBUG_CLOCKS_LL
-        printf("FBMUL %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 20) & 0xF, M);
-#endif
-        D = 8 - ((cpc->pllmr[1] >> 16) & 0x7); /* FWDA */
-#ifdef DEBUG_CLOCKS_LL
-        printf("FWDA %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 16) & 0x7, D);
-#endif
-        VCO_out = cpc->sysclk * M * D;
-        if (VCO_out < 500000000UL || VCO_out > 1000000000UL) {
-            /* Error - unlock the PLL */
-            printf("VCO out of range %" PRIu64 "\n", VCO_out);
-#if 0
-            cpc->pllmr[1] &= ~0x80000000;
-            goto pll_bypass;
-#endif
-        }
-        PLL_out = VCO_out / D;
-        /* Pretend the PLL is locked */
-        cpc->boot |= 0x00000001;
-    } else {
-#if 0
-    pll_bypass:
-#endif
-        PLL_out = cpc->sysclk;
-        if (cpc->pllmr[1] & 0x40000000) {
-            /* Pretend the PLL is not locked */
-            cpc->boot &= ~0x00000001;
-        }
-    }
-    /* Now, compute all other clocks */
-    D = ((cpc->pllmr[0] >> 20) & 0x3) + 1; /* CCDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("CCDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 20) & 0x3, D);
-#endif
-    CPU_clk = PLL_out / D;
-    D = ((cpc->pllmr[0] >> 16) & 0x3) + 1; /* CBDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("CBDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 16) & 0x3, D);
-#endif
-    PLB_clk = CPU_clk / D;
-    D = ((cpc->pllmr[0] >> 12) & 0x3) + 1; /* OPDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("OPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 12) & 0x3, D);
-#endif
-    OPB_clk = PLB_clk / D;
-    D = ((cpc->pllmr[0] >> 8) & 0x3) + 2; /* EPDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("EPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 8) & 0x3, D);
-#endif
-    EBC_clk = PLB_clk / D;
-    D = ((cpc->pllmr[0] >> 4) & 0x3) + 1; /* MPDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("MPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 4) & 0x3, D);
-#endif
-    MAL_clk = PLB_clk / D;
-    D = (cpc->pllmr[0] & 0x3) + 1; /* PPDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("PPDV %01" PRIx32 " %d\n", cpc->pllmr[0] & 0x3, D);
-#endif
-    PCI_clk = PLB_clk / D;
-    D = ((cpc->ucr - 1) & 0x7F) + 1; /* U0DIV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("U0DIV %01" PRIx32 " %d\n", cpc->ucr & 0x7F, D);
-#endif
-    UART0_clk = PLL_out / D;
-    D = (((cpc->ucr >> 8) - 1) & 0x7F) + 1; /* U1DIV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("U1DIV %01" PRIx32 " %d\n", (cpc->ucr >> 8) & 0x7F, D);
-#endif
-    UART1_clk = PLL_out / D;
-#ifdef DEBUG_CLOCKS
-    printf("Setup PPC405EP clocks - sysclk %" PRIu32 " VCO %" PRIu64
-           " PLL out %" PRIu64 " Hz\n", cpc->sysclk, VCO_out, PLL_out);
-    printf("CPU %" PRIu32 " PLB %" PRIu32 " OPB %" PRIu32 " EBC %" PRIu32
-           " MAL %" PRIu32 " PCI %" PRIu32 " UART0 %" PRIu32
-           " UART1 %" PRIu32 "\n",
-           CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk,
-           UART0_clk, UART1_clk);
-#endif
-    /* Setup CPU clocks */
-    clk_setup(&cpc->clk_setup[PPC405EP_CPU_CLK], CPU_clk);
-    /* Setup PLB clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_PLB_CLK], PLB_clk);
-    /* Setup OPB clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_OPB_CLK], OPB_clk);
-    /* Setup external clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_EBC_CLK], EBC_clk);
-    /* Setup MAL clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_MAL_CLK], MAL_clk);
-    /* Setup PCI clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_PCI_CLK], PCI_clk);
-    /* Setup UART0 clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_UART0_CLK], UART0_clk);
-    /* Setup UART1 clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_UART1_CLK], UART1_clk);
-}
-
-static uint32_t dcr_read_epcpc (void *opaque, int dcrn)
-{
-    ppc405ep_cpc_t *cpc;
-    uint32_t ret;
-
-    cpc = opaque;
-    switch (dcrn) {
-    case PPC405EP_CPC0_BOOT:
-        ret = cpc->boot;
-        break;
-    case PPC405EP_CPC0_EPCTL:
-        ret = cpc->epctl;
-        break;
-    case PPC405EP_CPC0_PLLMR0:
-        ret = cpc->pllmr[0];
-        break;
-    case PPC405EP_CPC0_PLLMR1:
-        ret = cpc->pllmr[1];
-        break;
-    case PPC405EP_CPC0_UCR:
-        ret = cpc->ucr;
-        break;
-    case PPC405EP_CPC0_SRR:
-        ret = cpc->srr;
-        break;
-    case PPC405EP_CPC0_JTAGID:
-        ret = cpc->jtagid;
-        break;
-    case PPC405EP_CPC0_PCI:
-        ret = cpc->pci;
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_epcpc (void *opaque, int dcrn, uint32_t val)
-{
-    ppc405ep_cpc_t *cpc;
-
-    cpc = opaque;
-    switch (dcrn) {
-    case PPC405EP_CPC0_BOOT:
-        /* Read-only register */
-        break;
-    case PPC405EP_CPC0_EPCTL:
-        /* Don't care for now */
-        cpc->epctl = val & 0xC00000F3;
-        break;
-    case PPC405EP_CPC0_PLLMR0:
-        cpc->pllmr[0] = val & 0x00633333;
-        ppc405ep_compute_clocks(cpc);
-        break;
-    case PPC405EP_CPC0_PLLMR1:
-        cpc->pllmr[1] = val & 0xC0F73FFF;
-        ppc405ep_compute_clocks(cpc);
-        break;
-    case PPC405EP_CPC0_UCR:
-        /* UART control - don't care for now */
-        cpc->ucr = val & 0x003F7F7F;
-        break;
-    case PPC405EP_CPC0_SRR:
-        cpc->srr = val;
-        break;
-    case PPC405EP_CPC0_JTAGID:
-        /* Read-only */
-        break;
-    case PPC405EP_CPC0_PCI:
-        cpc->pci = val;
-        break;
-    }
-}
-
-static void ppc405ep_cpc_reset (void *opaque)
-{
-    ppc405ep_cpc_t *cpc = opaque;
-
-    cpc->boot = 0x00000010;     /* Boot from PCI - IIC EEPROM disabled */
-    cpc->epctl = 0x00000000;
-    cpc->pllmr[0] = 0x00011010;
-    cpc->pllmr[1] = 0x40000000;
-    cpc->ucr = 0x00000000;
-    cpc->srr = 0x00040000;
-    cpc->pci = 0x00000000;
-    cpc->er = 0x00000000;
-    cpc->fr = 0x00000000;
-    cpc->sr = 0x00000000;
-    ppc405ep_compute_clocks(cpc);
-}
-
-/* XXX: sysclk should be between 25 and 100 MHz */
-static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8],
-                               uint32_t sysclk)
-{
-    ppc405ep_cpc_t *cpc;
-
-    cpc = g_malloc0(sizeof(ppc405ep_cpc_t));
-    memcpy(cpc->clk_setup, clk_setup,
-           PPC405EP_CLK_NB * sizeof(clk_setup_t));
-    cpc->jtagid = 0x20267049;
-    cpc->sysclk = sysclk;
-    qemu_register_reset(&ppc405ep_cpc_reset, cpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_BOOT, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_EPCTL, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_PLLMR0, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_PLLMR1, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_UCR, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_SRR, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_JTAGID, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-#if 0
-    ppc_dcr_register(env, PPC405EP_CPC0_ER, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_FR, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_SR, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-#endif
-}
-
-CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
-                        MemoryRegion ram_memories[2],
-                        hwaddr ram_bases[2],
-                        hwaddr ram_sizes[2],
-                        uint32_t sysclk, qemu_irq **picp,
-                        int do_init)
-{
-    clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
-    qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    qemu_irq *pic, *irqs;
-
-    memset(clk_setup, 0, sizeof(clk_setup));
-    /* init CPUs */
-    cpu = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
-                      &tlb_clk_setup, sysclk);
-    env = &cpu->env;
-    clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
-    clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
-    /* Internal devices init */
-    /* Memory mapped devices registers */
-    /* PLB arbitrer */
-    ppc4xx_plb_init(env);
-    /* PLB to OPB bridge */
-    ppc4xx_pob_init(env);
-    /* OBP arbitrer */
-    ppc4xx_opba_init(0xef600600);
-    /* Initialize timers */
-    ppc_booke_timers_init(cpu, sysclk, 0);
-    /* Universal interrupt controller */
-    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
-    irqs[PPCUIC_OUTPUT_INT] =
-        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
-    irqs[PPCUIC_OUTPUT_CINT] =
-        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
-    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
-    *picp = pic;
-    /* SDRAM controller */
-       /* XXX 405EP has no ECC interrupt */
-    ppc4xx_sdram_init(env, pic[17], 2, ram_memories,
-                      ram_bases, ram_sizes, do_init);
-    /* External bus controller */
-    ppc405_ebc_init(env);
-    /* DMA controller */
-    dma_irqs[0] = pic[5];
-    dma_irqs[1] = pic[6];
-    dma_irqs[2] = pic[7];
-    dma_irqs[3] = pic[8];
-    ppc405_dma_init(env, dma_irqs);
-    /* IIC controller */
-    ppc405_i2c_init(0xef600500, pic[2]);
-    /* GPIO */
-    ppc405_gpio_init(0xef600700);
-    /* Serial ports */
-    if (serial_hds[0] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
-                       DEVICE_BIG_ENDIAN);
-    }
-    if (serial_hds[1] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
-                       DEVICE_BIG_ENDIAN);
-    }
-    /* OCM */
-    ppc405_ocm_init(env);
-    /* GPT */
-    gpt_irqs[0] = pic[19];
-    gpt_irqs[1] = pic[20];
-    gpt_irqs[2] = pic[21];
-    gpt_irqs[3] = pic[22];
-    gpt_irqs[4] = pic[23];
-    ppc4xx_gpt_init(0xef600000, gpt_irqs);
-    /* PCI */
-    /* Uses pic[3], pic[16], pic[18] */
-    /* MAL */
-    mal_irqs[0] = pic[11];
-    mal_irqs[1] = pic[12];
-    mal_irqs[2] = pic[13];
-    mal_irqs[3] = pic[14];
-    ppc405_mal_init(env, mal_irqs);
-    /* Ethernet */
-    /* Uses pic[9], pic[15], pic[17] */
-    /* CPU control */
-    ppc405ep_cpc_init(env, clk_setup, sysclk);
-
-    return env;
-}
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
deleted file mode 100644 (file)
index 73b5ac7..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * QEMU PowerPC 440 Bamboo board emulation
- *
- * Copyright 2007 IBM Corporation.
- * Authors:
- *     Jerone Young <jyoung5@us.ibm.com>
- *     Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
- *     Hollis Blanchard <hollisb@us.ibm.com>
- *
- * This work is licensed under the GNU GPL license version 2 or later.
- *
- */
-
-#include "config.h"
-#include "qemu-common.h"
-#include "net/net.h"
-#include "hw.h"
-#include "pci/pci.h"
-#include "boards.h"
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
-#include "sysemu/device_tree.h"
-#include "loader.h"
-#include "elf.h"
-#include "exec/address-spaces.h"
-#include "serial.h"
-#include "ppc.h"
-#include "ppc405.h"
-#include "sysemu/sysemu.h"
-#include "sysbus.h"
-
-#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
-
-/* from u-boot */
-#define KERNEL_ADDR  0x1000000
-#define FDT_ADDR     0x1800000
-#define RAMDISK_ADDR 0x1900000
-
-#define PPC440EP_PCI_CONFIG     0xeec00000
-#define PPC440EP_PCI_INTACK     0xeed00000
-#define PPC440EP_PCI_SPECIAL    0xeed00000
-#define PPC440EP_PCI_REGS       0xef400000
-#define PPC440EP_PCI_IO         0xe8000000
-#define PPC440EP_PCI_IOLEN      0x00010000
-
-#define PPC440EP_SDRAM_NR_BANKS 4
-
-static const unsigned int ppc440ep_sdram_bank_sizes[] = {
-    256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0
-};
-
-static hwaddr entry;
-
-static int bamboo_load_device_tree(hwaddr addr,
-                                     uint32_t ramsize,
-                                     hwaddr initrd_base,
-                                     hwaddr initrd_size,
-                                     const char *kernel_cmdline)
-{
-    int ret = -1;
-#ifdef CONFIG_FDT
-    uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
-    char *filename;
-    int fdt_size;
-    void *fdt;
-    uint32_t tb_freq = 400000000;
-    uint32_t clock_freq = 400000000;
-
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
-    if (!filename) {
-        goto out;
-    }
-    fdt = load_device_tree(filename, &fdt_size);
-    g_free(filename);
-    if (fdt == NULL) {
-        goto out;
-    }
-
-    /* Manipulate device tree in memory. */
-
-    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
-                               sizeof(mem_reg_property));
-    if (ret < 0)
-        fprintf(stderr, "couldn't set /memory/reg\n");
-
-    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
-                                    initrd_base);
-    if (ret < 0)
-        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
-
-    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
-                                    (initrd_base + initrd_size));
-    if (ret < 0)
-        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
-
-    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
-                                      kernel_cmdline);
-    if (ret < 0)
-        fprintf(stderr, "couldn't set /chosen/bootargs\n");
-
-    /* Copy data from the host device tree into the guest. Since the guest can
-     * directly access the timebase without host involvement, we must expose
-     * the correct frequencies. */
-    if (kvm_enabled()) {
-        tb_freq = kvmppc_get_tbfreq();
-        clock_freq = kvmppc_get_clockfreq();
-    }
-
-    qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
-                              clock_freq);
-    qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
-                              tb_freq);
-
-    ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
-    g_free(fdt);
-
-out:
-#endif
-
-    return ret;
-}
-
-/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
-static void mmubooke_create_initial_mapping(CPUPPCState *env,
-                                     target_ulong va,
-                                     hwaddr pa)
-{
-    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
-
-    tlb->attr = 0;
-    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
-    tlb->size = 1 << 31; /* up to 0x80000000  */
-    tlb->EPN = va & TARGET_PAGE_MASK;
-    tlb->RPN = pa & TARGET_PAGE_MASK;
-    tlb->PID = 0;
-
-    tlb = &env->tlb.tlbe[1];
-    tlb->attr = 0;
-    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
-    tlb->size = 1 << 31; /* up to 0xffffffff  */
-    tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
-    tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
-    tlb->PID = 0;
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-    env->gpr[1] = (16<<20) - 8;
-    env->gpr[3] = FDT_ADDR;
-    env->nip = entry;
-
-    /* Create a mapping for the kernel.  */
-    mmubooke_create_initial_mapping(env, 0, 0);
-}
-
-static void bamboo_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram_memories
-        = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
-    hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
-    hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS];
-    qemu_irq *pic;
-    qemu_irq *irqs;
-    PCIBus *pcibus;
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    uint64_t elf_entry;
-    uint64_t elf_lowaddr;
-    hwaddr loadaddr = 0;
-    target_long initrd_size = 0;
-    DeviceState *dev;
-    int success;
-    int i;
-
-    /* Setup CPU. */
-    if (cpu_model == NULL) {
-        cpu_model = "440EP";
-    }
-    cpu = cpu_ppc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to initialize CPU!\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    qemu_register_reset(main_cpu_reset, cpu);
-    ppc_booke_timers_init(cpu, 400000000, 0);
-    ppc_dcr_init(env, NULL, NULL);
-
-    /* interrupt controller */
-    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
-    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
-    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
-    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
-
-    /* SDRAM controller */
-    memset(ram_bases, 0, sizeof(ram_bases));
-    memset(ram_sizes, 0, sizeof(ram_sizes));
-    ram_size = ppc4xx_sdram_adjust(ram_size, PPC440EP_SDRAM_NR_BANKS,
-                                   ram_memories,
-                                   ram_bases, ram_sizes,
-                                   ppc440ep_sdram_bank_sizes);
-    /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
-    ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_memories,
-                      ram_bases, ram_sizes, 1);
-
-    /* PCI */
-    dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
-                                PPC440EP_PCI_CONFIG,
-                                pic[pci_irq_nrs[0]], pic[pci_irq_nrs[1]],
-                                pic[pci_irq_nrs[2]], pic[pci_irq_nrs[3]],
-                                NULL);
-    pcibus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
-    if (!pcibus) {
-        fprintf(stderr, "couldn't create PCI controller!\n");
-        exit(1);
-    }
-
-    isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
-
-    if (serial_hds[0] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
-                       DEVICE_BIG_ENDIAN);
-    }
-    if (serial_hds[1] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
-                       DEVICE_BIG_ENDIAN);
-    }
-
-    if (pcibus) {
-        /* Register network interfaces. */
-        for (i = 0; i < nb_nics; i++) {
-            /* There are no PCI NICs on the Bamboo board, but there are
-             * PCI slots, so we can pick whatever default model we want. */
-            pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
-        }
-    }
-
-    /* Load kernel. */
-    if (kernel_filename) {
-        success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
-        if (success < 0) {
-            success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                               &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
-            entry = elf_entry;
-            loadaddr = elf_lowaddr;
-        }
-        /* XXX try again as binary */
-        if (success < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-    }
-
-    /* Load initrd. */
-    if (initrd_filename) {
-        initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR,
-                                          ram_size - RAMDISK_ADDR);
-
-        if (initrd_size < 0) {
-            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
-                    initrd_filename, RAMDISK_ADDR);
-            exit(1);
-        }
-    }
-
-    /* If we're loading a kernel directly, we must load the device tree too. */
-    if (kernel_filename) {
-        if (bamboo_load_device_tree(FDT_ADDR, ram_size, RAMDISK_ADDR,
-                                    initrd_size, kernel_cmdline) < 0) {
-            fprintf(stderr, "couldn't load device tree\n");
-            exit(1);
-        }
-    }
-
-    if (kvm_enabled())
-        kvmppc_init();
-}
-
-static QEMUMachine bamboo_machine = {
-    .name = "bamboo",
-    .desc = "bamboo",
-    .init = bamboo_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void bamboo_machine_init(void)
-{
-    qemu_register_machine(&bamboo_machine);
-}
-
-machine_init(bamboo_machine_init);
index 59dba9e29269a1fd4ae6004ddbc22a1faa5d14cf..91d84bad638c9b1d10559183e42c55d911a288d8 100644 (file)
@@ -25,7 +25,7 @@
 #if !defined(PPC_4XX_H)
 #define PPC_4XX_H
 
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 
 /* PowerPC 4xx core initialization */
 PowerPCCPU *ppc4xx_init(const char *cpu_model,
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
deleted file mode 100644 (file)
index b6bb0e1..0000000
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- * QEMU PowerPC 4xx embedded processors shared devices emulation
- *
- * Copyright (c) 2007 Jocelyn Mayer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "ppc.h"
-#include "ppc4xx.h"
-#include "qemu/log.h"
-#include "exec/address-spaces.h"
-
-//#define DEBUG_MMIO
-//#define DEBUG_UNASSIGNED
-#define DEBUG_UIC
-
-
-#ifdef DEBUG_UIC
-#  define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
-#else
-#  define LOG_UIC(...) do { } while (0)
-#endif
-
-static void ppc4xx_reset(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-/*****************************************************************************/
-/* Generic PowerPC 4xx processor instantiation */
-PowerPCCPU *ppc4xx_init(const char *cpu_model,
-                        clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
-                        uint32_t sysclk)
-{
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-
-    /* init CPUs */
-    cpu = cpu_ppc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find PowerPC %s CPU definition\n",
-                cpu_model);
-        exit(1);
-    }
-    env = &cpu->env;
-
-    cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
-    cpu_clk->opaque = env;
-    /* Set time-base frequency to sysclk */
-    tb_clk->cb = ppc_40x_timers_init(env, sysclk, PPC_INTERRUPT_PIT);
-    tb_clk->opaque = env;
-    ppc_dcr_init(env, NULL, NULL);
-    /* Register qemu callbacks */
-    qemu_register_reset(ppc4xx_reset, cpu);
-
-    return cpu;
-}
-
-/*****************************************************************************/
-/* "Universal" Interrupt controller */
-enum {
-    DCR_UICSR  = 0x000,
-    DCR_UICSRS = 0x001,
-    DCR_UICER  = 0x002,
-    DCR_UICCR  = 0x003,
-    DCR_UICPR  = 0x004,
-    DCR_UICTR  = 0x005,
-    DCR_UICMSR = 0x006,
-    DCR_UICVR  = 0x007,
-    DCR_UICVCR = 0x008,
-    DCR_UICMAX = 0x009,
-};
-
-#define UIC_MAX_IRQ 32
-typedef struct ppcuic_t ppcuic_t;
-struct ppcuic_t {
-    uint32_t dcr_base;
-    int use_vectors;
-    uint32_t level;  /* Remembers the state of level-triggered interrupts. */
-    uint32_t uicsr;  /* Status register */
-    uint32_t uicer;  /* Enable register */
-    uint32_t uiccr;  /* Critical register */
-    uint32_t uicpr;  /* Polarity register */
-    uint32_t uictr;  /* Triggering register */
-    uint32_t uicvcr; /* Vector configuration register */
-    uint32_t uicvr;
-    qemu_irq *irqs;
-};
-
-static void ppcuic_trigger_irq (ppcuic_t *uic)
-{
-    uint32_t ir, cr;
-    int start, end, inc, i;
-
-    /* Trigger interrupt if any is pending */
-    ir = uic->uicsr & uic->uicer & (~uic->uiccr);
-    cr = uic->uicsr & uic->uicer & uic->uiccr;
-    LOG_UIC("%s: uicsr %08" PRIx32 " uicer %08" PRIx32
-                " uiccr %08" PRIx32 "\n"
-                "   %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
-                __func__, uic->uicsr, uic->uicer, uic->uiccr,
-                uic->uicsr & uic->uicer, ir, cr);
-    if (ir != 0x0000000) {
-        LOG_UIC("Raise UIC interrupt\n");
-        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
-    } else {
-        LOG_UIC("Lower UIC interrupt\n");
-        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
-    }
-    /* Trigger critical interrupt if any is pending and update vector */
-    if (cr != 0x0000000) {
-        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
-        if (uic->use_vectors) {
-            /* Compute critical IRQ vector */
-            if (uic->uicvcr & 1) {
-                start = 31;
-                end = 0;
-                inc = -1;
-            } else {
-                start = 0;
-                end = 31;
-                inc = 1;
-            }
-            uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
-            for (i = start; i <= end; i += inc) {
-                if (cr & (1 << i)) {
-                    uic->uicvr += (i - start) * 512 * inc;
-                    break;
-                }
-            }
-        }
-        LOG_UIC("Raise UIC critical interrupt - "
-                    "vector %08" PRIx32 "\n", uic->uicvr);
-    } else {
-        LOG_UIC("Lower UIC critical interrupt\n");
-        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
-        uic->uicvr = 0x00000000;
-    }
-}
-
-static void ppcuic_set_irq (void *opaque, int irq_num, int level)
-{
-    ppcuic_t *uic;
-    uint32_t mask, sr;
-
-    uic = opaque;
-    mask = 1 << (31-irq_num);
-    LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32
-                " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
-                __func__, irq_num, level,
-                uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
-    if (irq_num < 0 || irq_num > 31)
-        return;
-    sr = uic->uicsr;
-
-    /* Update status register */
-    if (uic->uictr & mask) {
-        /* Edge sensitive interrupt */
-        if (level == 1)
-            uic->uicsr |= mask;
-    } else {
-        /* Level sensitive interrupt */
-        if (level == 1) {
-            uic->uicsr |= mask;
-            uic->level |= mask;
-        } else {
-            uic->uicsr &= ~mask;
-            uic->level &= ~mask;
-        }
-    }
-    LOG_UIC("%s: irq %d level %d sr %" PRIx32 " => "
-                "%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
-    if (sr != uic->uicsr)
-        ppcuic_trigger_irq(uic);
-}
-
-static uint32_t dcr_read_uic (void *opaque, int dcrn)
-{
-    ppcuic_t *uic;
-    uint32_t ret;
-
-    uic = opaque;
-    dcrn -= uic->dcr_base;
-    switch (dcrn) {
-    case DCR_UICSR:
-    case DCR_UICSRS:
-        ret = uic->uicsr;
-        break;
-    case DCR_UICER:
-        ret = uic->uicer;
-        break;
-    case DCR_UICCR:
-        ret = uic->uiccr;
-        break;
-    case DCR_UICPR:
-        ret = uic->uicpr;
-        break;
-    case DCR_UICTR:
-        ret = uic->uictr;
-        break;
-    case DCR_UICMSR:
-        ret = uic->uicsr & uic->uicer;
-        break;
-    case DCR_UICVR:
-        if (!uic->use_vectors)
-            goto no_read;
-        ret = uic->uicvr;
-        break;
-    case DCR_UICVCR:
-        if (!uic->use_vectors)
-            goto no_read;
-        ret = uic->uicvcr;
-        break;
-    default:
-    no_read:
-        ret = 0x00000000;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_uic (void *opaque, int dcrn, uint32_t val)
-{
-    ppcuic_t *uic;
-
-    uic = opaque;
-    dcrn -= uic->dcr_base;
-    LOG_UIC("%s: dcr %d val 0x%x\n", __func__, dcrn, val);
-    switch (dcrn) {
-    case DCR_UICSR:
-        uic->uicsr &= ~val;
-        uic->uicsr |= uic->level;
-        ppcuic_trigger_irq(uic);
-        break;
-    case DCR_UICSRS:
-        uic->uicsr |= val;
-        ppcuic_trigger_irq(uic);
-        break;
-    case DCR_UICER:
-        uic->uicer = val;
-        ppcuic_trigger_irq(uic);
-        break;
-    case DCR_UICCR:
-        uic->uiccr = val;
-        ppcuic_trigger_irq(uic);
-        break;
-    case DCR_UICPR:
-        uic->uicpr = val;
-        break;
-    case DCR_UICTR:
-        uic->uictr = val;
-        ppcuic_trigger_irq(uic);
-        break;
-    case DCR_UICMSR:
-        break;
-    case DCR_UICVR:
-        break;
-    case DCR_UICVCR:
-        uic->uicvcr = val & 0xFFFFFFFD;
-        ppcuic_trigger_irq(uic);
-        break;
-    }
-}
-
-static void ppcuic_reset (void *opaque)
-{
-    ppcuic_t *uic;
-
-    uic = opaque;
-    uic->uiccr = 0x00000000;
-    uic->uicer = 0x00000000;
-    uic->uicpr = 0x00000000;
-    uic->uicsr = 0x00000000;
-    uic->uictr = 0x00000000;
-    if (uic->use_vectors) {
-        uic->uicvcr = 0x00000000;
-        uic->uicvr = 0x0000000;
-    }
-}
-
-qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs,
-                       uint32_t dcr_base, int has_ssr, int has_vr)
-{
-    ppcuic_t *uic;
-    int i;
-
-    uic = g_malloc0(sizeof(ppcuic_t));
-    uic->dcr_base = dcr_base;
-    uic->irqs = irqs;
-    if (has_vr)
-        uic->use_vectors = 1;
-    for (i = 0; i < DCR_UICMAX; i++) {
-        ppc_dcr_register(env, dcr_base + i, uic,
-                         &dcr_read_uic, &dcr_write_uic);
-    }
-    qemu_register_reset(ppcuic_reset, uic);
-
-    return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
-}
-
-/*****************************************************************************/
-/* SDRAM controller */
-typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
-struct ppc4xx_sdram_t {
-    uint32_t addr;
-    int nbanks;
-    MemoryRegion containers[4]; /* used for clipping */
-    MemoryRegion *ram_memories;
-    hwaddr ram_bases[4];
-    hwaddr ram_sizes[4];
-    uint32_t besr0;
-    uint32_t besr1;
-    uint32_t bear;
-    uint32_t cfg;
-    uint32_t status;
-    uint32_t rtr;
-    uint32_t pmit;
-    uint32_t bcr[4];
-    uint32_t tr;
-    uint32_t ecccfg;
-    uint32_t eccesr;
-    qemu_irq irq;
-};
-
-enum {
-    SDRAM0_CFGADDR = 0x010,
-    SDRAM0_CFGDATA = 0x011,
-};
-
-/* XXX: TOFIX: some patches have made this code become inconsistent:
- *      there are type inconsistencies, mixing hwaddr, target_ulong
- *      and uint32_t
- */
-static uint32_t sdram_bcr (hwaddr ram_base,
-                           hwaddr ram_size)
-{
-    uint32_t bcr;
-
-    switch (ram_size) {
-    case (4 * 1024 * 1024):
-        bcr = 0x00000000;
-        break;
-    case (8 * 1024 * 1024):
-        bcr = 0x00020000;
-        break;
-    case (16 * 1024 * 1024):
-        bcr = 0x00040000;
-        break;
-    case (32 * 1024 * 1024):
-        bcr = 0x00060000;
-        break;
-    case (64 * 1024 * 1024):
-        bcr = 0x00080000;
-        break;
-    case (128 * 1024 * 1024):
-        bcr = 0x000A0000;
-        break;
-    case (256 * 1024 * 1024):
-        bcr = 0x000C0000;
-        break;
-    default:
-        printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__,
-               ram_size);
-        return 0x00000000;
-    }
-    bcr |= ram_base & 0xFF800000;
-    bcr |= 1;
-
-    return bcr;
-}
-
-static inline hwaddr sdram_base(uint32_t bcr)
-{
-    return bcr & 0xFF800000;
-}
-
-static target_ulong sdram_size (uint32_t bcr)
-{
-    target_ulong size;
-    int sh;
-
-    sh = (bcr >> 17) & 0x7;
-    if (sh == 7)
-        size = -1;
-    else
-        size = (4 * 1024 * 1024) << sh;
-
-    return size;
-}
-
-static void sdram_set_bcr(ppc4xx_sdram_t *sdram,
-                          uint32_t *bcrp, uint32_t bcr, int enabled)
-{
-    unsigned n = bcrp - sdram->bcr;
-
-    if (*bcrp & 0x00000001) {
-        /* Unmap RAM */
-#ifdef DEBUG_SDRAM
-        printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
-               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
-#endif
-        memory_region_del_subregion(get_system_memory(),
-                                    &sdram->containers[n]);
-        memory_region_del_subregion(&sdram->containers[n],
-                                    &sdram->ram_memories[n]);
-        memory_region_destroy(&sdram->containers[n]);
-    }
-    *bcrp = bcr & 0xFFDEE001;
-    if (enabled && (bcr & 0x00000001)) {
-#ifdef DEBUG_SDRAM
-        printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
-               __func__, sdram_base(bcr), sdram_size(bcr));
-#endif
-        memory_region_init(&sdram->containers[n], "sdram-containers",
-                           sdram_size(bcr));
-        memory_region_add_subregion(&sdram->containers[n], 0,
-                                    &sdram->ram_memories[n]);
-        memory_region_add_subregion(get_system_memory(),
-                                    sdram_base(bcr),
-                                    &sdram->containers[n]);
-    }
-}
-
-static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
-{
-    int i;
-
-    for (i = 0; i < sdram->nbanks; i++) {
-        if (sdram->ram_sizes[i] != 0) {
-            sdram_set_bcr(sdram,
-                          &sdram->bcr[i],
-                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
-                          1);
-        } else {
-            sdram_set_bcr(sdram, &sdram->bcr[i], 0x00000000, 0);
-        }
-    }
-}
-
-static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
-{
-    int i;
-
-    for (i = 0; i < sdram->nbanks; i++) {
-#ifdef DEBUG_SDRAM
-        printf("%s: Unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
-               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
-#endif
-        memory_region_del_subregion(get_system_memory(),
-                                    &sdram->ram_memories[i]);
-    }
-}
-
-static uint32_t dcr_read_sdram (void *opaque, int dcrn)
-{
-    ppc4xx_sdram_t *sdram;
-    uint32_t ret;
-
-    sdram = opaque;
-    switch (dcrn) {
-    case SDRAM0_CFGADDR:
-        ret = sdram->addr;
-        break;
-    case SDRAM0_CFGDATA:
-        switch (sdram->addr) {
-        case 0x00: /* SDRAM_BESR0 */
-            ret = sdram->besr0;
-            break;
-        case 0x08: /* SDRAM_BESR1 */
-            ret = sdram->besr1;
-            break;
-        case 0x10: /* SDRAM_BEAR */
-            ret = sdram->bear;
-            break;
-        case 0x20: /* SDRAM_CFG */
-            ret = sdram->cfg;
-            break;
-        case 0x24: /* SDRAM_STATUS */
-            ret = sdram->status;
-            break;
-        case 0x30: /* SDRAM_RTR */
-            ret = sdram->rtr;
-            break;
-        case 0x34: /* SDRAM_PMIT */
-            ret = sdram->pmit;
-            break;
-        case 0x40: /* SDRAM_B0CR */
-            ret = sdram->bcr[0];
-            break;
-        case 0x44: /* SDRAM_B1CR */
-            ret = sdram->bcr[1];
-            break;
-        case 0x48: /* SDRAM_B2CR */
-            ret = sdram->bcr[2];
-            break;
-        case 0x4C: /* SDRAM_B3CR */
-            ret = sdram->bcr[3];
-            break;
-        case 0x80: /* SDRAM_TR */
-            ret = -1; /* ? */
-            break;
-        case 0x94: /* SDRAM_ECCCFG */
-            ret = sdram->ecccfg;
-            break;
-        case 0x98: /* SDRAM_ECCESR */
-            ret = sdram->eccesr;
-            break;
-        default: /* Error */
-            ret = -1;
-            break;
-        }
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0x00000000;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = opaque;
-    switch (dcrn) {
-    case SDRAM0_CFGADDR:
-        sdram->addr = val;
-        break;
-    case SDRAM0_CFGDATA:
-        switch (sdram->addr) {
-        case 0x00: /* SDRAM_BESR0 */
-            sdram->besr0 &= ~val;
-            break;
-        case 0x08: /* SDRAM_BESR1 */
-            sdram->besr1 &= ~val;
-            break;
-        case 0x10: /* SDRAM_BEAR */
-            sdram->bear = val;
-            break;
-        case 0x20: /* SDRAM_CFG */
-            val &= 0xFFE00000;
-            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
-#ifdef DEBUG_SDRAM
-                printf("%s: enable SDRAM controller\n", __func__);
-#endif
-                /* validate all RAM mappings */
-                sdram_map_bcr(sdram);
-                sdram->status &= ~0x80000000;
-            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
-#ifdef DEBUG_SDRAM
-                printf("%s: disable SDRAM controller\n", __func__);
-#endif
-                /* invalidate all RAM mappings */
-                sdram_unmap_bcr(sdram);
-                sdram->status |= 0x80000000;
-            }
-            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
-                sdram->status |= 0x40000000;
-            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
-                sdram->status &= ~0x40000000;
-            sdram->cfg = val;
-            break;
-        case 0x24: /* SDRAM_STATUS */
-            /* Read-only register */
-            break;
-        case 0x30: /* SDRAM_RTR */
-            sdram->rtr = val & 0x3FF80000;
-            break;
-        case 0x34: /* SDRAM_PMIT */
-            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
-            break;
-        case 0x40: /* SDRAM_B0CR */
-            sdram_set_bcr(sdram, &sdram->bcr[0], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x44: /* SDRAM_B1CR */
-            sdram_set_bcr(sdram, &sdram->bcr[1], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x48: /* SDRAM_B2CR */
-            sdram_set_bcr(sdram, &sdram->bcr[2], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x4C: /* SDRAM_B3CR */
-            sdram_set_bcr(sdram, &sdram->bcr[3], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x80: /* SDRAM_TR */
-            sdram->tr = val & 0x018FC01F;
-            break;
-        case 0x94: /* SDRAM_ECCCFG */
-            sdram->ecccfg = val & 0x00F00000;
-            break;
-        case 0x98: /* SDRAM_ECCESR */
-            val &= 0xFFF0F000;
-            if (sdram->eccesr == 0 && val != 0)
-                qemu_irq_raise(sdram->irq);
-            else if (sdram->eccesr != 0 && val == 0)
-                qemu_irq_lower(sdram->irq);
-            sdram->eccesr = val;
-            break;
-        default: /* Error */
-            break;
-        }
-        break;
-    }
-}
-
-static void sdram_reset (void *opaque)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = opaque;
-    sdram->addr = 0x00000000;
-    sdram->bear = 0x00000000;
-    sdram->besr0 = 0x00000000; /* No error */
-    sdram->besr1 = 0x00000000; /* No error */
-    sdram->cfg = 0x00000000;
-    sdram->ecccfg = 0x00000000; /* No ECC */
-    sdram->eccesr = 0x00000000; /* No error */
-    sdram->pmit = 0x07C00000;
-    sdram->rtr = 0x05F00000;
-    sdram->tr = 0x00854009;
-    /* We pre-initialize RAM banks */
-    sdram->status = 0x00000000;
-    sdram->cfg = 0x00800000;
-}
-
-void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
-                        MemoryRegion *ram_memories,
-                        hwaddr *ram_bases,
-                        hwaddr *ram_sizes,
-                        int do_init)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = g_malloc0(sizeof(ppc4xx_sdram_t));
-    sdram->irq = irq;
-    sdram->nbanks = nbanks;
-    sdram->ram_memories = ram_memories;
-    memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr));
-    memcpy(sdram->ram_bases, ram_bases,
-           nbanks * sizeof(hwaddr));
-    memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr));
-    memcpy(sdram->ram_sizes, ram_sizes,
-           nbanks * sizeof(hwaddr));
-    qemu_register_reset(&sdram_reset, sdram);
-    ppc_dcr_register(env, SDRAM0_CFGADDR,
-                     sdram, &dcr_read_sdram, &dcr_write_sdram);
-    ppc_dcr_register(env, SDRAM0_CFGDATA,
-                     sdram, &dcr_read_sdram, &dcr_write_sdram);
-    if (do_init)
-        sdram_map_bcr(sdram);
-}
-
-/* Fill in consecutive SDRAM banks with 'ram_size' bytes of memory.
- *
- * sdram_bank_sizes[] must be 0-terminated.
- *
- * The 4xx SDRAM controller supports a small number of banks, and each bank
- * must be one of a small set of sizes. The number of banks and the supported
- * sizes varies by SoC. */
-ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
-                               MemoryRegion ram_memories[],
-                               hwaddr ram_bases[],
-                               hwaddr ram_sizes[],
-                               const unsigned int sdram_bank_sizes[])
-{
-    ram_addr_t size_left = ram_size;
-    ram_addr_t base = 0;
-    int i;
-    int j;
-
-    for (i = 0; i < nr_banks; i++) {
-        for (j = 0; sdram_bank_sizes[j] != 0; j++) {
-            unsigned int bank_size = sdram_bank_sizes[j];
-
-            if (bank_size <= size_left) {
-                char name[32];
-                snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
-                memory_region_init_ram(&ram_memories[i], name, bank_size);
-                vmstate_register_ram_global(&ram_memories[i]);
-                ram_bases[i] = base;
-                ram_sizes[i] = bank_size;
-                base += bank_size;
-                size_left -= bank_size;
-                break;
-            }
-        }
-
-        if (!size_left) {
-            /* No need to use the remaining banks. */
-            break;
-        }
-    }
-
-    ram_size -= size_left;
-    if (size_left)
-        printf("Truncating memory to %d MiB to fit SDRAM controller limits.\n",
-               (int)(ram_size >> 20));
-
-    return ram_size;
-}
index ba2d669b8346306bd159c323bee88e2f083a8a46..f3bbe88529a7bf5a1e3dd758d082e89bef6a3543 100644 (file)
 /* This file implements emulation of the 32-bit PCI controller found in some
  * 4xx SoCs, such as the 440EP. */
 
-#include "hw.h"
-#include "ppc.h"
-#include "ppc4xx.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
+#include "hw/hw.h"
+#include "hw/ppc.h"
+#include "hw/ppc4xx.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
 #include "exec/address-spaces.h"
 
 #undef DEBUG
diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c
deleted file mode 100644 (file)
index 25a4e91..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * QEMU PowerPC Booke hardware System Emulator
- *
- * Copyright (c) 2011 AdaCore
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "ppc.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "nvram.h"
-#include "qemu/log.h"
-#include "loader.h"
-
-
-/* Timer Control Register */
-
-#define TCR_WP_SHIFT  30        /* Watchdog Timer Period */
-#define TCR_WP_MASK   (0x3 << TCR_WP_SHIFT)
-#define TCR_WRC_SHIFT 28        /* Watchdog Timer Reset Control */
-#define TCR_WRC_MASK  (0x3 << TCR_WRC_SHIFT)
-#define TCR_WIE       (1 << 27) /* Watchdog Timer Interrupt Enable */
-#define TCR_DIE       (1 << 26) /* Decrementer Interrupt Enable */
-#define TCR_FP_SHIFT  24        /* Fixed-Interval Timer Period */
-#define TCR_FP_MASK   (0x3 << TCR_FP_SHIFT)
-#define TCR_FIE       (1 << 23) /* Fixed-Interval Timer Interrupt Enable */
-#define TCR_ARE       (1 << 22) /* Auto-Reload Enable */
-
-/* Timer Control Register (e500 specific fields) */
-
-#define TCR_E500_FPEXT_SHIFT 13 /* Fixed-Interval Timer Period Extension */
-#define TCR_E500_FPEXT_MASK  (0xf << TCR_E500_FPEXT_SHIFT)
-#define TCR_E500_WPEXT_SHIFT 17 /* Watchdog Timer Period Extension */
-#define TCR_E500_WPEXT_MASK  (0xf << TCR_E500_WPEXT_SHIFT)
-
-/* Timer Status Register  */
-
-#define TSR_FIS       (1 << 26) /* Fixed-Interval Timer Interrupt Status */
-#define TSR_DIS       (1 << 27) /* Decrementer Interrupt Status */
-#define TSR_WRS_SHIFT 28        /* Watchdog Timer Reset Status */
-#define TSR_WRS_MASK  (0x3 << TSR_WRS_SHIFT)
-#define TSR_WIS       (1 << 30) /* Watchdog Timer Interrupt Status */
-#define TSR_ENW       (1 << 31) /* Enable Next Watchdog Timer */
-
-typedef struct booke_timer_t booke_timer_t;
-struct booke_timer_t {
-
-    uint64_t fit_next;
-    struct QEMUTimer *fit_timer;
-
-    uint64_t wdt_next;
-    struct QEMUTimer *wdt_timer;
-
-    uint32_t flags;
-};
-
-static void booke_update_irq(PowerPCCPU *cpu)
-{
-    CPUPPCState *env = &cpu->env;
-
-    ppc_set_irq(cpu, PPC_INTERRUPT_DECR,
-                (env->spr[SPR_BOOKE_TSR] & TSR_DIS
-                 && env->spr[SPR_BOOKE_TCR] & TCR_DIE));
-
-    ppc_set_irq(cpu, PPC_INTERRUPT_WDT,
-                (env->spr[SPR_BOOKE_TSR] & TSR_WIS
-                 && env->spr[SPR_BOOKE_TCR] & TCR_WIE));
-
-    ppc_set_irq(cpu, PPC_INTERRUPT_FIT,
-                (env->spr[SPR_BOOKE_TSR] & TSR_FIS
-                 && env->spr[SPR_BOOKE_TCR] & TCR_FIE));
-}
-
-/* Return the location of the bit of time base at which the FIT will raise an
-   interrupt */
-static uint8_t booke_get_fit_target(CPUPPCState *env, ppc_tb_t *tb_env)
-{
-    uint8_t fp = (env->spr[SPR_BOOKE_TCR] & TCR_FP_MASK) >> TCR_FP_SHIFT;
-
-    if (tb_env->flags & PPC_TIMER_E500) {
-        /* e500 Fixed-interval timer period extension */
-        uint32_t fpext = (env->spr[SPR_BOOKE_TCR] & TCR_E500_FPEXT_MASK)
-            >> TCR_E500_FPEXT_SHIFT;
-        fp = 63 - (fp | fpext << 2);
-    } else {
-        fp = env->fit_period[fp];
-    }
-
-    return fp;
-}
-
-/* Return the location of the bit of time base at which the WDT will raise an
-   interrupt */
-static uint8_t booke_get_wdt_target(CPUPPCState *env, ppc_tb_t *tb_env)
-{
-    uint8_t wp = (env->spr[SPR_BOOKE_TCR] & TCR_WP_MASK) >> TCR_WP_SHIFT;
-
-    if (tb_env->flags & PPC_TIMER_E500) {
-        /* e500 Watchdog timer period extension */
-        uint32_t wpext = (env->spr[SPR_BOOKE_TCR] & TCR_E500_WPEXT_MASK)
-            >> TCR_E500_WPEXT_SHIFT;
-        wp = 63 - (wp | wpext << 2);
-    } else {
-        wp = env->wdt_period[wp];
-    }
-
-    return wp;
-}
-
-static void booke_update_fixed_timer(CPUPPCState         *env,
-                                     uint8_t           target_bit,
-                                     uint64_t          *next,
-                                     struct QEMUTimer *timer)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t lapse;
-    uint64_t tb;
-    uint64_t period = 1 << (target_bit + 1);
-    uint64_t now;
-
-    now = qemu_get_clock_ns(vm_clock);
-    tb  = cpu_ppc_get_tb(tb_env, now, tb_env->tb_offset);
-
-    lapse = period - ((tb - (1 << target_bit)) & (period - 1));
-
-    *next = now + muldiv64(lapse, get_ticks_per_sec(), tb_env->tb_freq);
-
-    /* XXX: If expire time is now. We can't run the callback because we don't
-     * have access to it. So we just set the timer one nanosecond later.
-     */
-
-    if (*next == now) {
-        (*next)++;
-    }
-
-    qemu_mod_timer(timer, *next);
-}
-
-static void booke_decr_cb(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-
-    env->spr[SPR_BOOKE_TSR] |= TSR_DIS;
-    booke_update_irq(cpu);
-
-    if (env->spr[SPR_BOOKE_TCR] & TCR_ARE) {
-        /* Auto Reload */
-        cpu_ppc_store_decr(env, env->spr[SPR_BOOKE_DECAR]);
-    }
-}
-
-static void booke_fit_cb(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    ppc_tb_t *tb_env;
-    booke_timer_t *booke_timer;
-
-    tb_env = env->tb_env;
-    booke_timer = tb_env->opaque;
-    env->spr[SPR_BOOKE_TSR] |= TSR_FIS;
-
-    booke_update_irq(cpu);
-
-    booke_update_fixed_timer(env,
-                             booke_get_fit_target(env, tb_env),
-                             &booke_timer->fit_next,
-                             booke_timer->fit_timer);
-}
-
-static void booke_wdt_cb(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    ppc_tb_t *tb_env;
-    booke_timer_t *booke_timer;
-
-    tb_env = env->tb_env;
-    booke_timer = tb_env->opaque;
-
-    /* TODO: There's lots of complicated stuff to do here */
-
-    booke_update_irq(cpu);
-
-    booke_update_fixed_timer(env,
-                             booke_get_wdt_target(env, tb_env),
-                             &booke_timer->wdt_next,
-                             booke_timer->wdt_timer);
-}
-
-void store_booke_tsr(CPUPPCState *env, target_ulong val)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->spr[SPR_BOOKE_TSR] &= ~val;
-    booke_update_irq(cpu);
-}
-
-void store_booke_tcr(CPUPPCState *env, target_ulong val)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-    ppc_tb_t *tb_env = env->tb_env;
-    booke_timer_t *booke_timer = tb_env->opaque;
-
-    tb_env = env->tb_env;
-    env->spr[SPR_BOOKE_TCR] = val;
-
-    booke_update_irq(cpu);
-
-    booke_update_fixed_timer(env,
-                             booke_get_fit_target(env, tb_env),
-                             &booke_timer->fit_next,
-                             booke_timer->fit_timer);
-
-    booke_update_fixed_timer(env,
-                             booke_get_wdt_target(env, tb_env),
-                             &booke_timer->wdt_next,
-                             booke_timer->wdt_timer);
-
-}
-
-static void ppc_booke_timer_reset_handle(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-
-    env->spr[SPR_BOOKE_TSR] = 0;
-    env->spr[SPR_BOOKE_TCR] = 0;
-
-    booke_update_irq(cpu);
-}
-
-void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
-{
-    ppc_tb_t *tb_env;
-    booke_timer_t *booke_timer;
-
-    tb_env      = g_malloc0(sizeof(ppc_tb_t));
-    booke_timer = g_malloc0(sizeof(booke_timer_t));
-
-    cpu->env.tb_env = tb_env;
-    tb_env->flags = flags | PPC_TIMER_BOOKE | PPC_DECR_ZERO_TRIGGERED;
-
-    tb_env->tb_freq    = freq;
-    tb_env->decr_freq  = freq;
-    tb_env->opaque     = booke_timer;
-    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, cpu);
-
-    booke_timer->fit_timer =
-        qemu_new_timer_ns(vm_clock, &booke_fit_cb, cpu);
-    booke_timer->wdt_timer =
-        qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu);
-
-    qemu_register_reset(ppc_booke_timer_reset_handle, cpu);
-}
index 1e1ade3d2eaa45002c16ac06667a20ce83d23479..310ae1c03d8961be5d184481acdca5bf226c0071 100644 (file)
  * (at your option) any later version.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "hw/ppc/e500-ccsr.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
 #include "qemu/bswap.h"
-#include "ppce500_pci.h"
+#include "hw/ppce500_pci.h"
 
 #ifdef DEBUG_PCI
 #define pci_debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
deleted file mode 100644 (file)
index 5bdce52..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * QEMU PowerPC e500v2 ePAPR spinning code
- *
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: Alexander Graf, <agraf@suse.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- * This code is not really a device, but models an interface that usually
- * firmware takes care of. It's used when QEMU plays the role of firmware.
- *
- * Specification:
- *
- * https://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.1.pdf
- *
- */
-
-#include "hw.h"
-#include "sysemu/sysemu.h"
-#include "sysbus.h"
-#include "sysemu/kvm.h"
-
-#define MAX_CPUS 32
-
-typedef struct spin_info {
-    uint64_t addr;
-    uint64_t r3;
-    uint32_t resv;
-    uint32_t pir;
-    uint64_t reserved;
-} QEMU_PACKED SpinInfo;
-
-typedef struct spin_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    SpinInfo spin[MAX_CPUS];
-} SpinState;
-
-typedef struct spin_kick {
-    PowerPCCPU *cpu;
-    SpinInfo *spin;
-} SpinKick;
-
-static void spin_reset(void *opaque)
-{
-    SpinState *s = opaque;
-    int i;
-
-    for (i = 0; i < MAX_CPUS; i++) {
-        SpinInfo *info = &s->spin[i];
-
-        info->pir = i;
-        info->r3 = i;
-        info->addr = 1;
-    }
-}
-
-/* Create -kernel TLB entries for BookE, linearly spanning 256MB.  */
-static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
-{
-    return (ffs(size >> 10) - 1) >> 1;
-}
-
-static void mmubooke_create_initial_mapping(CPUPPCState *env,
-                                     target_ulong va,
-                                     hwaddr pa,
-                                     hwaddr len)
-{
-    ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 1);
-    hwaddr size;
-
-    size = (booke206_page_size_to_tlb(len) << MAS1_TSIZE_SHIFT);
-    tlb->mas1 = MAS1_VALID | size;
-    tlb->mas2 = (va & TARGET_PAGE_MASK) | MAS2_M;
-    tlb->mas7_3 = pa & TARGET_PAGE_MASK;
-    tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
-    env->tlb_dirty = true;
-}
-
-static void spin_kick(void *data)
-{
-    SpinKick *kick = data;
-    CPUState *cpu = CPU(kick->cpu);
-    CPUPPCState *env = &kick->cpu->env;
-    SpinInfo *curspin = kick->spin;
-    hwaddr map_size = 64 * 1024 * 1024;
-    hwaddr map_start;
-
-    cpu_synchronize_state(env);
-    stl_p(&curspin->pir, env->spr[SPR_PIR]);
-    env->nip = ldq_p(&curspin->addr) & (map_size - 1);
-    env->gpr[3] = ldq_p(&curspin->r3);
-    env->gpr[4] = 0;
-    env->gpr[5] = 0;
-    env->gpr[6] = 0;
-    env->gpr[7] = map_size;
-    env->gpr[8] = 0;
-    env->gpr[9] = 0;
-
-    map_start = ldq_p(&curspin->addr) & ~(map_size - 1);
-    mmubooke_create_initial_mapping(env, 0, map_start, map_size);
-
-    env->halted = 0;
-    env->exception_index = -1;
-    cpu->stopped = false;
-    qemu_cpu_kick(cpu);
-}
-
-static void spin_write(void *opaque, hwaddr addr, uint64_t value,
-                       unsigned len)
-{
-    SpinState *s = opaque;
-    int env_idx = addr / sizeof(SpinInfo);
-    CPUState *cpu;
-    SpinInfo *curspin = &s->spin[env_idx];
-    uint8_t *curspin_p = (uint8_t*)curspin;
-
-    cpu = qemu_get_cpu(env_idx);
-    if (cpu == NULL) {
-        /* Unknown CPU */
-        return;
-    }
-
-    if (cpu->cpu_index == 0) {
-        /* primary CPU doesn't spin */
-        return;
-    }
-
-    curspin_p = &curspin_p[addr % sizeof(SpinInfo)];
-    switch (len) {
-    case 1:
-        stb_p(curspin_p, value);
-        break;
-    case 2:
-        stw_p(curspin_p, value);
-        break;
-    case 4:
-        stl_p(curspin_p, value);
-        break;
-    }
-
-    if (!(ldq_p(&curspin->addr) & 1)) {
-        /* run CPU */
-        SpinKick kick = {
-            .cpu = POWERPC_CPU(cpu),
-            .spin = curspin,
-        };
-
-        run_on_cpu(cpu, spin_kick, &kick);
-    }
-}
-
-static uint64_t spin_read(void *opaque, hwaddr addr, unsigned len)
-{
-    SpinState *s = opaque;
-    uint8_t *spin_p = &((uint8_t*)s->spin)[addr];
-
-    switch (len) {
-    case 1:
-        return ldub_p(spin_p);
-    case 2:
-        return lduw_p(spin_p);
-    case 4:
-        return ldl_p(spin_p);
-    default:
-        hw_error("ppce500: unexpected %s with len = %u", __func__, len);
-    }
-}
-
-static const MemoryRegionOps spin_rw_ops = {
-    .read = spin_read,
-    .write = spin_write,
-    .endianness = DEVICE_BIG_ENDIAN,
-};
-
-static int ppce500_spin_initfn(SysBusDevice *dev)
-{
-    SpinState *s;
-
-    s = FROM_SYSBUS(SpinState, SYS_BUS_DEVICE(dev));
-
-    memory_region_init_io(&s->iomem, &spin_rw_ops, s, "e500 spin pv device",
-                          sizeof(SpinInfo) * MAX_CPUS);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    qemu_register_reset(spin_reset, s);
-
-    return 0;
-}
-
-static void ppce500_spin_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = ppce500_spin_initfn;
-}
-
-static const TypeInfo ppce500_spin_info = {
-    .name          = "e500-spin",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SpinState),
-    .class_init    = ppce500_spin_class_init,
-};
-
-static void ppce500_spin_register_types(void)
-{
-    type_register_static(&ppce500_spin_info);
-}
-
-type_init(ppce500_spin_register_types)
index 52ee5d94019c880bd8915fe64f72922e0921f342..d21e87671e858cbb1b594032a082c1a80722de82 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "pci/pci.h"
-#include "pci/pci_bus.h"
-#include "pci/pci_host.h"
-#include "pc.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pc.h"
 #include "exec/address-spaces.h"
 
 #define TYPE_RAVEN_PCI_DEVICE "raven"
index 15cfd5bb76e7c7dfbdd068618d37395b494d2d3d..233a087a5ead3b473b8de4c1277db05d5ad780d9 100644 (file)
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -21,8 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ps2.h"
+#include "hw/hw.h"
+#include "hw/ps2.h"
 #include "ui/console.h"
 #include "sysemu/sysemu.h"
 
index 24af6a2afe30ba3ff7bf5fca0068026210c25be6..4bc96c9fa2e9007cfe4b28b65ab30897aa409510 100644 (file)
@@ -5,9 +5,9 @@
  *
  * This code is licensed under the GNU LGPL.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "qemu/host-utils.h"
 
 struct ptimer_state
diff --git a/hw/puv3.c b/hw/puv3.c
deleted file mode 100644 (file)
index c722510..0000000
--- a/hw/puv3.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Generic PKUnity SoC machine and board descriptor
- *
- * Copyright (C) 2010-2012 Guan Xuetao
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation, or any later version.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu-common.h"
-#include "ui/console.h"
-#include "elf.h"
-#include "exec/address-spaces.h"
-#include "sysbus.h"
-#include "boards.h"
-#include "loader.h"
-#include "pc.h"
-
-#undef DEBUG_PUV3
-#include "puv3.h"
-
-#define KERNEL_LOAD_ADDR        0x03000000
-#define KERNEL_MAX_SIZE         0x00800000 /* Just a guess */
-
-static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
-{
-    CPUUniCore32State *env = opaque;
-
-    assert(irq == 0);
-    if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-static void puv3_soc_init(CPUUniCore32State *env)
-{
-    qemu_irq *cpu_intc, irqs[PUV3_IRQS_NR];
-    DeviceState *dev;
-    MemoryRegion *i8042 = g_new(MemoryRegion, 1);
-    int i;
-
-    /* Initialize interrupt controller */
-    cpu_intc = qemu_allocate_irqs(puv3_intc_cpu_handler, env, 1);
-    dev = sysbus_create_simple("puv3_intc", PUV3_INTC_BASE, *cpu_intc);
-    for (i = 0; i < PUV3_IRQS_NR; i++) {
-        irqs[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    /* Initialize minimal necessary devices for kernel booting */
-    sysbus_create_simple("puv3_pm", PUV3_PM_BASE, NULL);
-    sysbus_create_simple("puv3_dma", PUV3_DMA_BASE, NULL);
-    sysbus_create_simple("puv3_ost", PUV3_OST_BASE, irqs[PUV3_IRQS_OST0]);
-    sysbus_create_varargs("puv3_gpio", PUV3_GPIO_BASE,
-            irqs[PUV3_IRQS_GPIOLOW0], irqs[PUV3_IRQS_GPIOLOW1],
-            irqs[PUV3_IRQS_GPIOLOW2], irqs[PUV3_IRQS_GPIOLOW3],
-            irqs[PUV3_IRQS_GPIOLOW4], irqs[PUV3_IRQS_GPIOLOW5],
-            irqs[PUV3_IRQS_GPIOLOW6], irqs[PUV3_IRQS_GPIOLOW7],
-            irqs[PUV3_IRQS_GPIOHIGH], NULL);
-
-    /* Keyboard (i8042), mouse disabled for nographic */
-    i8042_mm_init(irqs[PUV3_IRQS_PS2_KBD], NULL, i8042, PUV3_REGS_OFFSET, 4);
-    memory_region_add_subregion(get_system_memory(), PUV3_PS2_BASE, i8042);
-}
-
-static void puv3_board_init(CPUUniCore32State *env, ram_addr_t ram_size)
-{
-    MemoryRegion *ram_memory = g_new(MemoryRegion, 1);
-
-    /* SDRAM at address zero.  */
-    memory_region_init_ram(ram_memory, "puv3.ram", ram_size);
-    vmstate_register_ram_global(ram_memory);
-    memory_region_add_subregion(get_system_memory(), 0, ram_memory);
-}
-
-static void puv3_load_kernel(const char *kernel_filename)
-{
-    int size;
-
-    assert(kernel_filename != NULL);
-
-    /* only zImage format supported */
-    size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
-            KERNEL_MAX_SIZE);
-    if (size < 0) {
-        hw_error("Load kernel error: '%s'\n", kernel_filename);
-    }
-
-    /* cheat curses that we have a graphic console, only under ocd console */
-    graphic_console_init(NULL, NULL, NULL, NULL, NULL);
-}
-
-static void puv3_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *initrd_filename = args->initrd_filename;
-    CPUUniCore32State *env;
-
-    if (initrd_filename) {
-        hw_error("Please use kernel built-in initramdisk.\n");
-    }
-
-    if (!cpu_model) {
-        cpu_model = "UniCore-II";
-    }
-
-    env = cpu_init(cpu_model);
-    if (!env) {
-        hw_error("Unable to find CPU definition\n");
-    }
-
-    puv3_soc_init(env);
-    puv3_board_init(env, ram_size);
-    puv3_load_kernel(kernel_filename);
-}
-
-static QEMUMachine puv3_machine = {
-    .name = "puv3",
-    .desc = "PKUnity Version-3 based on UniCore32",
-    .init = puv3_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void puv3_machine_init(void)
-{
-    qemu_register_machine(&puv3_machine);
-}
-
-machine_init(puv3_machine_init)
index 9de63b4c3449b8b060969db4870f2aeb943487d6..c05a14ea16ff2a5e1fbd63b589dcceaffd51e5e3 100644 (file)
@@ -8,11 +8,11 @@
  * published by the Free Software Foundation, or any later version.
  * See the COPYING file in the top-level directory.
  */
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 
 #undef DEBUG_PUV3
-#include "puv3.h"
+#include "hw/puv3.h"
 
 #define PUV3_DMA_CH_NR          (6)
 #define PUV3_DMA_CH_MASK        (0xff)
index 152248d2919a50cb483b9f36616c04740f11424e..b2a790b683bfc25459a3f21054c67f6c73f03aad 100644 (file)
@@ -8,11 +8,11 @@
  * published by the Free Software Foundation, or any later version.
  * See the COPYING file in the top-level directory.
  */
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 
 #undef DEBUG_PUV3
-#include "puv3.h"
+#include "hw/puv3.h"
 
 typedef struct {
     SysBusDevice busdev;
index 07f564906565f2323303127401062e33fcbf0513..6bc9e1a752496e4c19106a19872b669882c597bd 100644 (file)
@@ -8,10 +8,10 @@
  * published by the Free Software Foundation, or any later version.
  * See the COPYING file in the top-level directory.
  */
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #undef DEBUG_PUV3
-#include "puv3.h"
+#include "hw/puv3.h"
 
 typedef struct {
     SysBusDevice busdev;
index 14c6f21a756fd11fc6d60918234a354c46707a45..10a522adbb46d23961a49315f018c7a71b4c7880 100644 (file)
@@ -8,11 +8,11 @@
  * published by the Free Software Foundation, or any later version.
  * See the COPYING file in the top-level directory.
  */
-#include "sysbus.h"
-#include "ptimer.h"
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
 
 #undef DEBUG_PUV3
-#include "puv3.h"
+#include "hw/puv3.h"
 
 /* puv3 ostimer implementation. */
 typedef struct {
index 87a687afaead97a318c9e48c161eca491dd27b9d..6b8d94dd07262d75a98aed8b917540215a54872b 100644 (file)
@@ -8,11 +8,11 @@
  * published by the Free Software Foundation, or any later version.
  * See the COPYING file in the top-level directory.
  */
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 
 #undef DEBUG_PUV3
-#include "puv3.h"
+#include "hw/puv3.h"
 
 typedef struct {
     SysBusDevice busdev;
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
deleted file mode 100644 (file)
index d303320..0000000
+++ /dev/null
@@ -1,2291 +0,0 @@
-/*
- * Intel XScale PXA255/270 processor support.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog@zabor.org>
- *
- * This code is licensed under the GPL.
- */
-
-#include "sysbus.h"
-#include "pxa.h"
-#include "sysemu/sysemu.h"
-#include "serial.h"
-#include "i2c.h"
-#include "ssi.h"
-#include "char/char.h"
-#include "sysemu/blockdev.h"
-
-static struct {
-    hwaddr io_base;
-    int irqn;
-} pxa255_serial[] = {
-    { 0x40100000, PXA2XX_PIC_FFUART },
-    { 0x40200000, PXA2XX_PIC_BTUART },
-    { 0x40700000, PXA2XX_PIC_STUART },
-    { 0x41600000, PXA25X_PIC_HWUART },
-    { 0, 0 }
-}, pxa270_serial[] = {
-    { 0x40100000, PXA2XX_PIC_FFUART },
-    { 0x40200000, PXA2XX_PIC_BTUART },
-    { 0x40700000, PXA2XX_PIC_STUART },
-    { 0, 0 }
-};
-
-typedef struct PXASSPDef {
-    hwaddr io_base;
-    int irqn;
-} PXASSPDef;
-
-#if 0
-static PXASSPDef pxa250_ssp[] = {
-    { 0x41000000, PXA2XX_PIC_SSP },
-    { 0, 0 }
-};
-#endif
-
-static PXASSPDef pxa255_ssp[] = {
-    { 0x41000000, PXA2XX_PIC_SSP },
-    { 0x41400000, PXA25X_PIC_NSSP },
-    { 0, 0 }
-};
-
-#if 0
-static PXASSPDef pxa26x_ssp[] = {
-    { 0x41000000, PXA2XX_PIC_SSP },
-    { 0x41400000, PXA25X_PIC_NSSP },
-    { 0x41500000, PXA26X_PIC_ASSP },
-    { 0, 0 }
-};
-#endif
-
-static PXASSPDef pxa27x_ssp[] = {
-    { 0x41000000, PXA2XX_PIC_SSP },
-    { 0x41700000, PXA27X_PIC_SSP2 },
-    { 0x41900000, PXA2XX_PIC_SSP3 },
-    { 0, 0 }
-};
-
-#define PMCR   0x00    /* Power Manager Control register */
-#define PSSR   0x04    /* Power Manager Sleep Status register */
-#define PSPR   0x08    /* Power Manager Scratch-Pad register */
-#define PWER   0x0c    /* Power Manager Wake-Up Enable register */
-#define PRER   0x10    /* Power Manager Rising-Edge Detect Enable register */
-#define PFER   0x14    /* Power Manager Falling-Edge Detect Enable register */
-#define PEDR   0x18    /* Power Manager Edge-Detect Status register */
-#define PCFR   0x1c    /* Power Manager General Configuration register */
-#define PGSR0  0x20    /* Power Manager GPIO Sleep-State register 0 */
-#define PGSR1  0x24    /* Power Manager GPIO Sleep-State register 1 */
-#define PGSR2  0x28    /* Power Manager GPIO Sleep-State register 2 */
-#define PGSR3  0x2c    /* Power Manager GPIO Sleep-State register 3 */
-#define RCSR   0x30    /* Reset Controller Status register */
-#define PSLR   0x34    /* Power Manager Sleep Configuration register */
-#define PTSR   0x38    /* Power Manager Standby Configuration register */
-#define PVCR   0x40    /* Power Manager Voltage Change Control register */
-#define PUCR   0x4c    /* Power Manager USIM Card Control/Status register */
-#define PKWR   0x50    /* Power Manager Keyboard Wake-Up Enable register */
-#define PKSR   0x54    /* Power Manager Keyboard Level-Detect Status */
-#define PCMD0  0x80    /* Power Manager I2C Command register File 0 */
-#define PCMD31 0xfc    /* Power Manager I2C Command register File 31 */
-
-static uint64_t pxa2xx_pm_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case PMCR ... PCMD31:
-        if (addr & 3)
-            goto fail;
-
-        return s->pm_regs[addr >> 2];
-    default:
-    fail:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_pm_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case PMCR:
-        /* Clear the write-one-to-clear bits... */
-        s->pm_regs[addr >> 2] &= ~(value & 0x2a);
-        /* ...and set the plain r/w bits */
-        s->pm_regs[addr >> 2] &= ~0x15;
-        s->pm_regs[addr >> 2] |= value & 0x15;
-        break;
-
-    case PSSR: /* Read-clean registers */
-    case RCSR:
-    case PKSR:
-        s->pm_regs[addr >> 2] &= ~value;
-        break;
-
-    default:   /* Read-write registers */
-        if (!(addr & 3)) {
-            s->pm_regs[addr >> 2] = value;
-            break;
-        }
-
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static const MemoryRegionOps pxa2xx_pm_ops = {
-    .read = pxa2xx_pm_read,
-    .write = pxa2xx_pm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_pxa2xx_pm = {
-    .name = "pxa2xx_pm",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(pm_regs, PXA2xxState, 0x40),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-#define CCCR   0x00    /* Core Clock Configuration register */
-#define CKEN   0x04    /* Clock Enable register */
-#define OSCC   0x08    /* Oscillator Configuration register */
-#define CCSR   0x0c    /* Core Clock Status register */
-
-static uint64_t pxa2xx_cm_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case CCCR:
-    case CKEN:
-    case OSCC:
-        return s->cm_regs[addr >> 2];
-
-    case CCSR:
-        return s->cm_regs[CCCR >> 2] | (3 << 28);
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_cm_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case CCCR:
-    case CKEN:
-        s->cm_regs[addr >> 2] = value;
-        break;
-
-    case OSCC:
-        s->cm_regs[addr >> 2] &= ~0x6c;
-        s->cm_regs[addr >> 2] |= value & 0x6e;
-        if ((value >> 1) & 1)                  /* OON */
-            s->cm_regs[addr >> 2] |= 1 << 0;   /* Oscillator is now stable */
-        break;
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static const MemoryRegionOps pxa2xx_cm_ops = {
-    .read = pxa2xx_cm_read,
-    .write = pxa2xx_cm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_pxa2xx_cm = {
-    .name = "pxa2xx_cm",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(cm_regs, PXA2xxState, 4),
-        VMSTATE_UINT32(clkcfg, PXA2xxState),
-        VMSTATE_UINT32(pmnc, PXA2xxState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int pxa2xx_clkcfg_read(CPUARMState *env, const ARMCPRegInfo *ri,
-                              uint64_t *value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    *value = s->clkcfg;
-    return 0;
-}
-
-static int pxa2xx_clkcfg_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                               uint64_t value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    s->clkcfg = value & 0xf;
-    if (value & 2) {
-        printf("%s: CPU frequency change attempt\n", __func__);
-    }
-    return 0;
-}
-
-static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                                uint64_t value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    static const char *pwrmode[8] = {
-        "Normal", "Idle", "Deep-idle", "Standby",
-        "Sleep", "reserved (!)", "reserved (!)", "Deep-sleep",
-    };
-
-    if (value & 8) {
-        printf("%s: CPU voltage change attempt\n", __func__);
-    }
-    switch (value & 7) {
-    case 0:
-        /* Do nothing */
-        break;
-
-    case 1:
-        /* Idle */
-        if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */
-            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
-            break;
-        }
-        /* Fall through.  */
-
-    case 2:
-        /* Deep-Idle */
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
-        s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
-        goto message;
-
-    case 3:
-        s->cpu->env.uncached_cpsr =
-            ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
-        s->cpu->env.cp15.c1_sys = 0;
-        s->cpu->env.cp15.c1_coproc = 0;
-        s->cpu->env.cp15.c2_base0 = 0;
-        s->cpu->env.cp15.c3 = 0;
-        s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
-        s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
-
-        /*
-         * The scratch-pad register is almost universally used
-         * for storing the return address on suspend.  For the
-         * lack of a resuming bootloader, perform a jump
-         * directly to that address.
-         */
-        memset(s->cpu->env.regs, 0, 4 * 15);
-        s->cpu->env.regs[15] = s->pm_regs[PSPR >> 2];
-
-#if 0
-        buffer = 0xe59ff000; /* ldr     pc, [pc, #0] */
-        cpu_physical_memory_write(0, &buffer, 4);
-        buffer = s->pm_regs[PSPR >> 2];
-        cpu_physical_memory_write(8, &buffer, 4);
-#endif
-
-        /* Suspend */
-        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
-
-        goto message;
-
-    default:
-    message:
-        printf("%s: machine entered %s mode\n", __func__,
-               pwrmode[value & 7]);
-    }
-
-    return 0;
-}
-
-static int pxa2xx_cppmnc_read(CPUARMState *env, const ARMCPRegInfo *ri,
-                              uint64_t *value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    *value = s->pmnc;
-    return 0;
-}
-
-static int pxa2xx_cppmnc_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                               uint64_t value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    s->pmnc = value;
-    return 0;
-}
-
-static int pxa2xx_cpccnt_read(CPUARMState *env, const ARMCPRegInfo *ri,
-                              uint64_t *value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    if (s->pmnc & 1) {
-        *value = qemu_get_clock_ns(vm_clock);
-    } else {
-        *value = 0;
-    }
-    return 0;
-}
-
-static const ARMCPRegInfo pxa_cp_reginfo[] = {
-    /* cp14 crm==1: perf registers */
-    { .name = "CPPMNC", .cp = 14, .crn = 0, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW,
-      .readfn = pxa2xx_cppmnc_read, .writefn = pxa2xx_cppmnc_write },
-    { .name = "CPCCNT", .cp = 14, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW,
-      .readfn = pxa2xx_cpccnt_read, .writefn = arm_cp_write_ignore },
-    { .name = "CPINTEN", .cp = 14, .crn = 4, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPFLAG", .cp = 14, .crn = 5, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPEVTSEL", .cp = 14, .crn = 8, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    /* cp14 crm==2: performance count registers */
-    { .name = "CPPMN0", .cp = 14, .crn = 0, .crm = 2, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPPMN1", .cp = 14, .crn = 1, .crm = 2, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPPMN2", .cp = 14, .crn = 2, .crm = 2, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPPMN3", .cp = 14, .crn = 2, .crm = 3, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    /* cp14 crn==6: CLKCFG */
-    { .name = "CLKCFG", .cp = 14, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW,
-      .readfn = pxa2xx_clkcfg_read, .writefn = pxa2xx_clkcfg_write },
-    /* cp14 crn==7: PWRMODE */
-    { .name = "PWRMODE", .cp = 14, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW,
-      .readfn = arm_cp_read_zero, .writefn = pxa2xx_pwrmode_write },
-    REGINFO_SENTINEL
-};
-
-static void pxa2xx_setup_cp14(PXA2xxState *s)
-{
-    define_arm_cp_regs_with_opaque(s->cpu, pxa_cp_reginfo, s);
-}
-
-#define MDCNFG         0x00    /* SDRAM Configuration register */
-#define MDREFR         0x04    /* SDRAM Refresh Control register */
-#define MSC0           0x08    /* Static Memory Control register 0 */
-#define MSC1           0x0c    /* Static Memory Control register 1 */
-#define MSC2           0x10    /* Static Memory Control register 2 */
-#define MECR           0x14    /* Expansion Memory Bus Config register */
-#define SXCNFG         0x1c    /* Synchronous Static Memory Config register */
-#define MCMEM0         0x28    /* PC Card Memory Socket 0 Timing register */
-#define MCMEM1         0x2c    /* PC Card Memory Socket 1 Timing register */
-#define MCATT0         0x30    /* PC Card Attribute Socket 0 register */
-#define MCATT1         0x34    /* PC Card Attribute Socket 1 register */
-#define MCIO0          0x38    /* PC Card I/O Socket 0 Timing register */
-#define MCIO1          0x3c    /* PC Card I/O Socket 1 Timing register */
-#define MDMRS          0x40    /* SDRAM Mode Register Set Config register */
-#define BOOT_DEF       0x44    /* Boot-time Default Configuration register */
-#define ARB_CNTL       0x48    /* Arbiter Control register */
-#define BSCNTR0                0x4c    /* Memory Buffer Strength Control register 0 */
-#define BSCNTR1                0x50    /* Memory Buffer Strength Control register 1 */
-#define LCDBSCNTR      0x54    /* LCD Buffer Strength Control register */
-#define MDMRSLP                0x58    /* Low Power SDRAM Mode Set Config register */
-#define BSCNTR2                0x5c    /* Memory Buffer Strength Control register 2 */
-#define BSCNTR3                0x60    /* Memory Buffer Strength Control register 3 */
-#define SA1110         0x64    /* SA-1110 Memory Compatibility register */
-
-static uint64_t pxa2xx_mm_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case MDCNFG ... SA1110:
-        if ((addr & 3) == 0)
-            return s->mm_regs[addr >> 2];
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_mm_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case MDCNFG ... SA1110:
-        if ((addr & 3) == 0) {
-            s->mm_regs[addr >> 2] = value;
-            break;
-        }
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static const MemoryRegionOps pxa2xx_mm_ops = {
-    .read = pxa2xx_mm_read,
-    .write = pxa2xx_mm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_pxa2xx_mm = {
-    .name = "pxa2xx_mm",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(mm_regs, PXA2xxState, 0x1a),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-/* Synchronous Serial Ports */
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    qemu_irq irq;
-    int enable;
-    SSIBus *bus;
-
-    uint32_t sscr[2];
-    uint32_t sspsp;
-    uint32_t ssto;
-    uint32_t ssitr;
-    uint32_t sssr;
-    uint8_t sstsa;
-    uint8_t ssrsa;
-    uint8_t ssacd;
-
-    uint32_t rx_fifo[16];
-    int rx_level;
-    int rx_start;
-} PXA2xxSSPState;
-
-#define SSCR0  0x00    /* SSP Control register 0 */
-#define SSCR1  0x04    /* SSP Control register 1 */
-#define SSSR   0x08    /* SSP Status register */
-#define SSITR  0x0c    /* SSP Interrupt Test register */
-#define SSDR   0x10    /* SSP Data register */
-#define SSTO   0x28    /* SSP Time-Out register */
-#define SSPSP  0x2c    /* SSP Programmable Serial Protocol register */
-#define SSTSA  0x30    /* SSP TX Time Slot Active register */
-#define SSRSA  0x34    /* SSP RX Time Slot Active register */
-#define SSTSS  0x38    /* SSP Time Slot Status register */
-#define SSACD  0x3c    /* SSP Audio Clock Divider register */
-
-/* Bitfields for above registers */
-#define SSCR0_SPI(x)   (((x) & 0x30) == 0x00)
-#define SSCR0_SSP(x)   (((x) & 0x30) == 0x10)
-#define SSCR0_UWIRE(x) (((x) & 0x30) == 0x20)
-#define SSCR0_PSP(x)   (((x) & 0x30) == 0x30)
-#define SSCR0_SSE      (1 << 7)
-#define SSCR0_RIM      (1 << 22)
-#define SSCR0_TIM      (1 << 23)
-#define SSCR0_MOD      (1 << 31)
-#define SSCR0_DSS(x)   (((((x) >> 16) & 0x10) | ((x) & 0xf)) + 1)
-#define SSCR1_RIE      (1 << 0)
-#define SSCR1_TIE      (1 << 1)
-#define SSCR1_LBM      (1 << 2)
-#define SSCR1_MWDS     (1 << 5)
-#define SSCR1_TFT(x)   ((((x) >> 6) & 0xf) + 1)
-#define SSCR1_RFT(x)   ((((x) >> 10) & 0xf) + 1)
-#define SSCR1_EFWR     (1 << 14)
-#define SSCR1_PINTE    (1 << 18)
-#define SSCR1_TINTE    (1 << 19)
-#define SSCR1_RSRE     (1 << 20)
-#define SSCR1_TSRE     (1 << 21)
-#define SSCR1_EBCEI    (1 << 29)
-#define SSITR_INT      (7 << 5)
-#define SSSR_TNF       (1 << 2)
-#define SSSR_RNE       (1 << 3)
-#define SSSR_TFS       (1 << 5)
-#define SSSR_RFS       (1 << 6)
-#define SSSR_ROR       (1 << 7)
-#define SSSR_PINT      (1 << 18)
-#define SSSR_TINT      (1 << 19)
-#define SSSR_EOC       (1 << 20)
-#define SSSR_TUR       (1 << 21)
-#define SSSR_BCE       (1 << 23)
-#define SSSR_RW                0x00bc0080
-
-static void pxa2xx_ssp_int_update(PXA2xxSSPState *s)
-{
-    int level = 0;
-
-    level |= s->ssitr & SSITR_INT;
-    level |= (s->sssr & SSSR_BCE)  &&  (s->sscr[1] & SSCR1_EBCEI);
-    level |= (s->sssr & SSSR_TUR)  && !(s->sscr[0] & SSCR0_TIM);
-    level |= (s->sssr & SSSR_EOC)  &&  (s->sssr & (SSSR_TINT | SSSR_PINT));
-    level |= (s->sssr & SSSR_TINT) &&  (s->sscr[1] & SSCR1_TINTE);
-    level |= (s->sssr & SSSR_PINT) &&  (s->sscr[1] & SSCR1_PINTE);
-    level |= (s->sssr & SSSR_ROR)  && !(s->sscr[0] & SSCR0_RIM);
-    level |= (s->sssr & SSSR_RFS)  &&  (s->sscr[1] & SSCR1_RIE);
-    level |= (s->sssr & SSSR_TFS)  &&  (s->sscr[1] & SSCR1_TIE);
-    qemu_set_irq(s->irq, !!level);
-}
-
-static void pxa2xx_ssp_fifo_update(PXA2xxSSPState *s)
-{
-    s->sssr &= ~(0xf << 12);   /* Clear RFL */
-    s->sssr &= ~(0xf << 8);    /* Clear TFL */
-    s->sssr &= ~SSSR_TFS;
-    s->sssr &= ~SSSR_TNF;
-    if (s->enable) {
-        s->sssr |= ((s->rx_level - 1) & 0xf) << 12;
-        if (s->rx_level >= SSCR1_RFT(s->sscr[1]))
-            s->sssr |= SSSR_RFS;
-        else
-            s->sssr &= ~SSSR_RFS;
-        if (s->rx_level)
-            s->sssr |= SSSR_RNE;
-        else
-            s->sssr &= ~SSSR_RNE;
-        /* TX FIFO is never filled, so it is always in underrun
-           condition if SSP is enabled */
-        s->sssr |= SSSR_TFS;
-        s->sssr |= SSSR_TNF;
-    }
-
-    pxa2xx_ssp_int_update(s);
-}
-
-static uint64_t pxa2xx_ssp_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
-    uint32_t retval;
-
-    switch (addr) {
-    case SSCR0:
-        return s->sscr[0];
-    case SSCR1:
-        return s->sscr[1];
-    case SSPSP:
-        return s->sspsp;
-    case SSTO:
-        return s->ssto;
-    case SSITR:
-        return s->ssitr;
-    case SSSR:
-        return s->sssr | s->ssitr;
-    case SSDR:
-        if (!s->enable)
-            return 0xffffffff;
-        if (s->rx_level < 1) {
-            printf("%s: SSP Rx Underrun\n", __FUNCTION__);
-            return 0xffffffff;
-        }
-        s->rx_level --;
-        retval = s->rx_fifo[s->rx_start ++];
-        s->rx_start &= 0xf;
-        pxa2xx_ssp_fifo_update(s);
-        return retval;
-    case SSTSA:
-        return s->sstsa;
-    case SSRSA:
-        return s->ssrsa;
-    case SSTSS:
-        return 0;
-    case SSACD:
-        return s->ssacd;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_ssp_write(void *opaque, hwaddr addr,
-                             uint64_t value64, unsigned size)
-{
-    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
-    uint32_t value = value64;
-
-    switch (addr) {
-    case SSCR0:
-        s->sscr[0] = value & 0xc7ffffff;
-        s->enable = value & SSCR0_SSE;
-        if (value & SSCR0_MOD)
-            printf("%s: Attempt to use network mode\n", __FUNCTION__);
-        if (s->enable && SSCR0_DSS(value) < 4)
-            printf("%s: Wrong data size: %i bits\n", __FUNCTION__,
-                            SSCR0_DSS(value));
-        if (!(value & SSCR0_SSE)) {
-            s->sssr = 0;
-            s->ssitr = 0;
-            s->rx_level = 0;
-        }
-        pxa2xx_ssp_fifo_update(s);
-        break;
-
-    case SSCR1:
-        s->sscr[1] = value;
-        if (value & (SSCR1_LBM | SSCR1_EFWR))
-            printf("%s: Attempt to use SSP test mode\n", __FUNCTION__);
-        pxa2xx_ssp_fifo_update(s);
-        break;
-
-    case SSPSP:
-        s->sspsp = value;
-        break;
-
-    case SSTO:
-        s->ssto = value;
-        break;
-
-    case SSITR:
-        s->ssitr = value & SSITR_INT;
-        pxa2xx_ssp_int_update(s);
-        break;
-
-    case SSSR:
-        s->sssr &= ~(value & SSSR_RW);
-        pxa2xx_ssp_int_update(s);
-        break;
-
-    case SSDR:
-        if (SSCR0_UWIRE(s->sscr[0])) {
-            if (s->sscr[1] & SSCR1_MWDS)
-                value &= 0xffff;
-            else
-                value &= 0xff;
-        } else
-            /* Note how 32bits overflow does no harm here */
-            value &= (1 << SSCR0_DSS(s->sscr[0])) - 1;
-
-        /* Data goes from here to the Tx FIFO and is shifted out from
-         * there directly to the slave, no need to buffer it.
-         */
-        if (s->enable) {
-            uint32_t readval;
-            readval = ssi_transfer(s->bus, value);
-            if (s->rx_level < 0x10) {
-                s->rx_fifo[(s->rx_start + s->rx_level ++) & 0xf] = readval;
-            } else {
-                s->sssr |= SSSR_ROR;
-            }
-        }
-        pxa2xx_ssp_fifo_update(s);
-        break;
-
-    case SSTSA:
-        s->sstsa = value;
-        break;
-
-    case SSRSA:
-        s->ssrsa = value;
-        break;
-
-    case SSACD:
-        s->ssacd = value;
-        break;
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static const MemoryRegionOps pxa2xx_ssp_ops = {
-    .read = pxa2xx_ssp_read,
-    .write = pxa2xx_ssp_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void pxa2xx_ssp_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
-    int i;
-
-    qemu_put_be32(f, s->enable);
-
-    qemu_put_be32s(f, &s->sscr[0]);
-    qemu_put_be32s(f, &s->sscr[1]);
-    qemu_put_be32s(f, &s->sspsp);
-    qemu_put_be32s(f, &s->ssto);
-    qemu_put_be32s(f, &s->ssitr);
-    qemu_put_be32s(f, &s->sssr);
-    qemu_put_8s(f, &s->sstsa);
-    qemu_put_8s(f, &s->ssrsa);
-    qemu_put_8s(f, &s->ssacd);
-
-    qemu_put_byte(f, s->rx_level);
-    for (i = 0; i < s->rx_level; i ++)
-        qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 0xf]);
-}
-
-static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
-    int i;
-
-    s->enable = qemu_get_be32(f);
-
-    qemu_get_be32s(f, &s->sscr[0]);
-    qemu_get_be32s(f, &s->sscr[1]);
-    qemu_get_be32s(f, &s->sspsp);
-    qemu_get_be32s(f, &s->ssto);
-    qemu_get_be32s(f, &s->ssitr);
-    qemu_get_be32s(f, &s->sssr);
-    qemu_get_8s(f, &s->sstsa);
-    qemu_get_8s(f, &s->ssrsa);
-    qemu_get_8s(f, &s->ssacd);
-
-    s->rx_level = qemu_get_byte(f);
-    s->rx_start = 0;
-    for (i = 0; i < s->rx_level; i ++)
-        s->rx_fifo[i] = qemu_get_byte(f);
-
-    return 0;
-}
-
-static int pxa2xx_ssp_init(SysBusDevice *dev)
-{
-    PXA2xxSSPState *s = FROM_SYSBUS(PXA2xxSSPState, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-
-    memory_region_init_io(&s->iomem, &pxa2xx_ssp_ops, s, "pxa2xx-ssp", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
-                    pxa2xx_ssp_save, pxa2xx_ssp_load, s);
-
-    s->bus = ssi_create_bus(&dev->qdev, "ssi");
-    return 0;
-}
-
-/* Real-Time Clock */
-#define RCNR           0x00    /* RTC Counter register */
-#define RTAR           0x04    /* RTC Alarm register */
-#define RTSR           0x08    /* RTC Status register */
-#define RTTR           0x0c    /* RTC Timer Trim register */
-#define RDCR           0x10    /* RTC Day Counter register */
-#define RYCR           0x14    /* RTC Year Counter register */
-#define RDAR1          0x18    /* RTC Wristwatch Day Alarm register 1 */
-#define RYAR1          0x1c    /* RTC Wristwatch Year Alarm register 1 */
-#define RDAR2          0x20    /* RTC Wristwatch Day Alarm register 2 */
-#define RYAR2          0x24    /* RTC Wristwatch Year Alarm register 2 */
-#define SWCR           0x28    /* RTC Stopwatch Counter register */
-#define SWAR1          0x2c    /* RTC Stopwatch Alarm register 1 */
-#define SWAR2          0x30    /* RTC Stopwatch Alarm register 2 */
-#define RTCPICR                0x34    /* RTC Periodic Interrupt Counter register */
-#define PIAR           0x38    /* RTC Periodic Interrupt Alarm register */
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t rttr;
-    uint32_t rtsr;
-    uint32_t rtar;
-    uint32_t rdar1;
-    uint32_t rdar2;
-    uint32_t ryar1;
-    uint32_t ryar2;
-    uint32_t swar1;
-    uint32_t swar2;
-    uint32_t piar;
-    uint32_t last_rcnr;
-    uint32_t last_rdcr;
-    uint32_t last_rycr;
-    uint32_t last_swcr;
-    uint32_t last_rtcpicr;
-    int64_t last_hz;
-    int64_t last_sw;
-    int64_t last_pi;
-    QEMUTimer *rtc_hz;
-    QEMUTimer *rtc_rdal1;
-    QEMUTimer *rtc_rdal2;
-    QEMUTimer *rtc_swal1;
-    QEMUTimer *rtc_swal2;
-    QEMUTimer *rtc_pi;
-    qemu_irq rtc_irq;
-} PXA2xxRTCState;
-
-static inline void pxa2xx_rtc_int_update(PXA2xxRTCState *s)
-{
-    qemu_set_irq(s->rtc_irq, !!(s->rtsr & 0x2553));
-}
-
-static void pxa2xx_rtc_hzupdate(PXA2xxRTCState *s)
-{
-    int64_t rt = qemu_get_clock_ms(rtc_clock);
-    s->last_rcnr += ((rt - s->last_hz) << 15) /
-            (1000 * ((s->rttr & 0xffff) + 1));
-    s->last_rdcr += ((rt - s->last_hz) << 15) /
-            (1000 * ((s->rttr & 0xffff) + 1));
-    s->last_hz = rt;
-}
-
-static void pxa2xx_rtc_swupdate(PXA2xxRTCState *s)
-{
-    int64_t rt = qemu_get_clock_ms(rtc_clock);
-    if (s->rtsr & (1 << 12))
-        s->last_swcr += (rt - s->last_sw) / 10;
-    s->last_sw = rt;
-}
-
-static void pxa2xx_rtc_piupdate(PXA2xxRTCState *s)
-{
-    int64_t rt = qemu_get_clock_ms(rtc_clock);
-    if (s->rtsr & (1 << 15))
-        s->last_swcr += rt - s->last_pi;
-    s->last_pi = rt;
-}
-
-static inline void pxa2xx_rtc_alarm_update(PXA2xxRTCState *s,
-                uint32_t rtsr)
-{
-    if ((rtsr & (1 << 2)) && !(rtsr & (1 << 0)))
-        qemu_mod_timer(s->rtc_hz, s->last_hz +
-                (((s->rtar - s->last_rcnr) * 1000 *
-                  ((s->rttr & 0xffff) + 1)) >> 15));
-    else
-        qemu_del_timer(s->rtc_hz);
-
-    if ((rtsr & (1 << 5)) && !(rtsr & (1 << 4)))
-        qemu_mod_timer(s->rtc_rdal1, s->last_hz +
-                (((s->rdar1 - s->last_rdcr) * 1000 *
-                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_rdal1);
-
-    if ((rtsr & (1 << 7)) && !(rtsr & (1 << 6)))
-        qemu_mod_timer(s->rtc_rdal2, s->last_hz +
-                (((s->rdar2 - s->last_rdcr) * 1000 *
-                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_rdal2);
-
-    if ((rtsr & 0x1200) == 0x1200 && !(rtsr & (1 << 8)))
-        qemu_mod_timer(s->rtc_swal1, s->last_sw +
-                        (s->swar1 - s->last_swcr) * 10); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_swal1);
-
-    if ((rtsr & 0x1800) == 0x1800 && !(rtsr & (1 << 10)))
-        qemu_mod_timer(s->rtc_swal2, s->last_sw +
-                        (s->swar2 - s->last_swcr) * 10); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_swal2);
-
-    if ((rtsr & 0xc000) == 0xc000 && !(rtsr & (1 << 13)))
-        qemu_mod_timer(s->rtc_pi, s->last_pi +
-                        (s->piar & 0xffff) - s->last_rtcpicr);
-    else
-        qemu_del_timer(s->rtc_pi);
-}
-
-static inline void pxa2xx_rtc_hz_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 0);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_rdal1_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 4);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_rdal2_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 6);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_swal1_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 8);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_swal2_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 10);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_pi_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 13);
-    pxa2xx_rtc_piupdate(s);
-    s->last_rtcpicr = 0;
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static uint64_t pxa2xx_rtc_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-
-    switch (addr) {
-    case RTTR:
-        return s->rttr;
-    case RTSR:
-        return s->rtsr;
-    case RTAR:
-        return s->rtar;
-    case RDAR1:
-        return s->rdar1;
-    case RDAR2:
-        return s->rdar2;
-    case RYAR1:
-        return s->ryar1;
-    case RYAR2:
-        return s->ryar2;
-    case SWAR1:
-        return s->swar1;
-    case SWAR2:
-        return s->swar2;
-    case PIAR:
-        return s->piar;
-    case RCNR:
-        return s->last_rcnr + ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
-                (1000 * ((s->rttr & 0xffff) + 1));
-    case RDCR:
-        return s->last_rdcr + ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
-                (1000 * ((s->rttr & 0xffff) + 1));
-    case RYCR:
-        return s->last_rycr;
-    case SWCR:
-        if (s->rtsr & (1 << 12))
-            return s->last_swcr + (qemu_get_clock_ms(rtc_clock) - s->last_sw) / 10;
-        else
-            return s->last_swcr;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_rtc_write(void *opaque, hwaddr addr,
-                             uint64_t value64, unsigned size)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    uint32_t value = value64;
-
-    switch (addr) {
-    case RTTR:
-        if (!(s->rttr & (1 << 31))) {
-            pxa2xx_rtc_hzupdate(s);
-            s->rttr = value;
-            pxa2xx_rtc_alarm_update(s, s->rtsr);
-        }
-        break;
-
-    case RTSR:
-        if ((s->rtsr ^ value) & (1 << 15))
-            pxa2xx_rtc_piupdate(s);
-
-        if ((s->rtsr ^ value) & (1 << 12))
-            pxa2xx_rtc_swupdate(s);
-
-        if (((s->rtsr ^ value) & 0x4aac) | (value & ~0xdaac))
-            pxa2xx_rtc_alarm_update(s, value);
-
-        s->rtsr = (value & 0xdaac) | (s->rtsr & ~(value & ~0xdaac));
-        pxa2xx_rtc_int_update(s);
-        break;
-
-    case RTAR:
-        s->rtar = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RDAR1:
-        s->rdar1 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RDAR2:
-        s->rdar2 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RYAR1:
-        s->ryar1 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RYAR2:
-        s->ryar2 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case SWAR1:
-        pxa2xx_rtc_swupdate(s);
-        s->swar1 = value;
-        s->last_swcr = 0;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case SWAR2:
-        s->swar2 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case PIAR:
-        s->piar = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RCNR:
-        pxa2xx_rtc_hzupdate(s);
-        s->last_rcnr = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RDCR:
-        pxa2xx_rtc_hzupdate(s);
-        s->last_rdcr = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RYCR:
-        s->last_rycr = value;
-        break;
-
-    case SWCR:
-        pxa2xx_rtc_swupdate(s);
-        s->last_swcr = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RTCPICR:
-        pxa2xx_rtc_piupdate(s);
-        s->last_rtcpicr = value & 0xffff;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-    }
-}
-
-static const MemoryRegionOps pxa2xx_rtc_ops = {
-    .read = pxa2xx_rtc_read,
-    .write = pxa2xx_rtc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int pxa2xx_rtc_init(SysBusDevice *dev)
-{
-    PXA2xxRTCState *s = FROM_SYSBUS(PXA2xxRTCState, dev);
-    struct tm tm;
-    int wom;
-
-    s->rttr = 0x7fff;
-    s->rtsr = 0;
-
-    qemu_get_timedate(&tm, 0);
-    wom = ((tm.tm_mday - 1) / 7) + 1;
-
-    s->last_rcnr = (uint32_t) mktimegm(&tm);
-    s->last_rdcr = (wom << 20) | ((tm.tm_wday + 1) << 17) |
-            (tm.tm_hour << 12) | (tm.tm_min << 6) | tm.tm_sec;
-    s->last_rycr = ((tm.tm_year + 1900) << 9) |
-            ((tm.tm_mon + 1) << 5) | tm.tm_mday;
-    s->last_swcr = (tm.tm_hour << 19) |
-            (tm.tm_min << 13) | (tm.tm_sec << 7);
-    s->last_rtcpicr = 0;
-    s->last_hz = s->last_sw = s->last_pi = qemu_get_clock_ms(rtc_clock);
-
-    s->rtc_hz    = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_hz_tick,    s);
-    s->rtc_rdal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal1_tick, s);
-    s->rtc_rdal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal2_tick, s);
-    s->rtc_swal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal1_tick, s);
-    s->rtc_swal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal2_tick, s);
-    s->rtc_pi    = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_pi_tick,    s);
-
-    sysbus_init_irq(dev, &s->rtc_irq);
-
-    memory_region_init_io(&s->iomem, &pxa2xx_rtc_ops, s, "pxa2xx-rtc", 0x10000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    return 0;
-}
-
-static void pxa2xx_rtc_pre_save(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-
-    pxa2xx_rtc_hzupdate(s);
-    pxa2xx_rtc_piupdate(s);
-    pxa2xx_rtc_swupdate(s);
-}
-
-static int pxa2xx_rtc_post_load(void *opaque, int version_id)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_pxa2xx_rtc_regs = {
-    .name = "pxa2xx_rtc",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .pre_save = pxa2xx_rtc_pre_save,
-    .post_load = pxa2xx_rtc_post_load,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(rttr, PXA2xxRTCState),
-        VMSTATE_UINT32(rtsr, PXA2xxRTCState),
-        VMSTATE_UINT32(rtar, PXA2xxRTCState),
-        VMSTATE_UINT32(rdar1, PXA2xxRTCState),
-        VMSTATE_UINT32(rdar2, PXA2xxRTCState),
-        VMSTATE_UINT32(ryar1, PXA2xxRTCState),
-        VMSTATE_UINT32(ryar2, PXA2xxRTCState),
-        VMSTATE_UINT32(swar1, PXA2xxRTCState),
-        VMSTATE_UINT32(swar2, PXA2xxRTCState),
-        VMSTATE_UINT32(piar, PXA2xxRTCState),
-        VMSTATE_UINT32(last_rcnr, PXA2xxRTCState),
-        VMSTATE_UINT32(last_rdcr, PXA2xxRTCState),
-        VMSTATE_UINT32(last_rycr, PXA2xxRTCState),
-        VMSTATE_UINT32(last_swcr, PXA2xxRTCState),
-        VMSTATE_UINT32(last_rtcpicr, PXA2xxRTCState),
-        VMSTATE_INT64(last_hz, PXA2xxRTCState),
-        VMSTATE_INT64(last_sw, PXA2xxRTCState),
-        VMSTATE_INT64(last_pi, PXA2xxRTCState),
-        VMSTATE_END_OF_LIST(),
-    },
-};
-
-static void pxa2xx_rtc_sysbus_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = pxa2xx_rtc_init;
-    dc->desc = "PXA2xx RTC Controller";
-    dc->vmsd = &vmstate_pxa2xx_rtc_regs;
-}
-
-static const TypeInfo pxa2xx_rtc_sysbus_info = {
-    .name          = "pxa2xx_rtc",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PXA2xxRTCState),
-    .class_init    = pxa2xx_rtc_sysbus_class_init,
-};
-
-/* I2C Interface */
-typedef struct {
-    I2CSlave i2c;
-    PXA2xxI2CState *host;
-} PXA2xxI2CSlaveState;
-
-struct PXA2xxI2CState {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    PXA2xxI2CSlaveState *slave;
-    i2c_bus *bus;
-    qemu_irq irq;
-    uint32_t offset;
-    uint32_t region_size;
-
-    uint16_t control;
-    uint16_t status;
-    uint8_t ibmr;
-    uint8_t data;
-};
-
-#define IBMR   0x80    /* I2C Bus Monitor register */
-#define IDBR   0x88    /* I2C Data Buffer register */
-#define ICR    0x90    /* I2C Control register */
-#define ISR    0x98    /* I2C Status register */
-#define ISAR   0xa0    /* I2C Slave Address register */
-
-static void pxa2xx_i2c_update(PXA2xxI2CState *s)
-{
-    uint16_t level = 0;
-    level |= s->status & s->control & (1 << 10);               /* BED */
-    level |= (s->status & (1 << 7)) && (s->control & (1 << 9));        /* IRF */
-    level |= (s->status & (1 << 6)) && (s->control & (1 << 8));        /* ITE */
-    level |= s->status & (1 << 9);                             /* SAD */
-    qemu_set_irq(s->irq, !!level);
-}
-
-/* These are only stubs now.  */
-static void pxa2xx_i2c_event(I2CSlave *i2c, enum i2c_event event)
-{
-    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
-    PXA2xxI2CState *s = slave->host;
-
-    switch (event) {
-    case I2C_START_SEND:
-        s->status |= (1 << 9);                         /* set SAD */
-        s->status &= ~(1 << 0);                                /* clear RWM */
-        break;
-    case I2C_START_RECV:
-        s->status |= (1 << 9);                         /* set SAD */
-        s->status |= 1 << 0;                           /* set RWM */
-        break;
-    case I2C_FINISH:
-        s->status |= (1 << 4);                         /* set SSD */
-        break;
-    case I2C_NACK:
-        s->status |= 1 << 1;                           /* set ACKNAK */
-        break;
-    }
-    pxa2xx_i2c_update(s);
-}
-
-static int pxa2xx_i2c_rx(I2CSlave *i2c)
-{
-    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
-    PXA2xxI2CState *s = slave->host;
-    if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
-        return 0;
-
-    if (s->status & (1 << 0)) {                        /* RWM */
-        s->status |= 1 << 6;                   /* set ITE */
-    }
-    pxa2xx_i2c_update(s);
-
-    return s->data;
-}
-
-static int pxa2xx_i2c_tx(I2CSlave *i2c, uint8_t data)
-{
-    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
-    PXA2xxI2CState *s = slave->host;
-    if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
-        return 1;
-
-    if (!(s->status & (1 << 0))) {             /* RWM */
-        s->status |= 1 << 7;                   /* set IRF */
-        s->data = data;
-    }
-    pxa2xx_i2c_update(s);
-
-    return 1;
-}
-
-static uint64_t pxa2xx_i2c_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    PXA2xxI2CState *s = (PXA2xxI2CState *) opaque;
-
-    addr -= s->offset;
-    switch (addr) {
-    case ICR:
-        return s->control;
-    case ISR:
-        return s->status | (i2c_bus_busy(s->bus) << 2);
-    case ISAR:
-        return s->slave->i2c.address;
-    case IDBR:
-        return s->data;
-    case IBMR:
-        if (s->status & (1 << 2))
-            s->ibmr ^= 3;      /* Fake SCL and SDA pin changes */
-        else
-            s->ibmr = 0;
-        return s->ibmr;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_i2c_write(void *opaque, hwaddr addr,
-                             uint64_t value64, unsigned size)
-{
-    PXA2xxI2CState *s = (PXA2xxI2CState *) opaque;
-    uint32_t value = value64;
-    int ack;
-
-    addr -= s->offset;
-    switch (addr) {
-    case ICR:
-        s->control = value & 0xfff7;
-        if ((value & (1 << 3)) && (value & (1 << 6))) {        /* TB and IUE */
-            /* TODO: slave mode */
-            if (value & (1 << 0)) {                    /* START condition */
-                if (s->data & 1)
-                    s->status |= 1 << 0;               /* set RWM */
-                else
-                    s->status &= ~(1 << 0);            /* clear RWM */
-                ack = !i2c_start_transfer(s->bus, s->data >> 1, s->data & 1);
-            } else {
-                if (s->status & (1 << 0)) {            /* RWM */
-                    s->data = i2c_recv(s->bus);
-                    if (value & (1 << 2))              /* ACKNAK */
-                        i2c_nack(s->bus);
-                    ack = 1;
-                } else
-                    ack = !i2c_send(s->bus, s->data);
-            }
-
-            if (value & (1 << 1))                      /* STOP condition */
-                i2c_end_transfer(s->bus);
-
-            if (ack) {
-                if (value & (1 << 0))                  /* START condition */
-                    s->status |= 1 << 6;               /* set ITE */
-                else
-                    if (s->status & (1 << 0))          /* RWM */
-                        s->status |= 1 << 7;           /* set IRF */
-                    else
-                        s->status |= 1 << 6;           /* set ITE */
-                s->status &= ~(1 << 1);                        /* clear ACKNAK */
-            } else {
-                s->status |= 1 << 6;                   /* set ITE */
-                s->status |= 1 << 10;                  /* set BED */
-                s->status |= 1 << 1;                   /* set ACKNAK */
-            }
-        }
-        if (!(value & (1 << 3)) && (value & (1 << 6))) /* !TB and IUE */
-            if (value & (1 << 4))                      /* MA */
-                i2c_end_transfer(s->bus);
-        pxa2xx_i2c_update(s);
-        break;
-
-    case ISR:
-        s->status &= ~(value & 0x07f0);
-        pxa2xx_i2c_update(s);
-        break;
-
-    case ISAR:
-        i2c_set_slave_address(&s->slave->i2c, value & 0x7f);
-        break;
-
-    case IDBR:
-        s->data = value & 0xff;
-        break;
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-    }
-}
-
-static const MemoryRegionOps pxa2xx_i2c_ops = {
-    .read = pxa2xx_i2c_read,
-    .write = pxa2xx_i2c_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_pxa2xx_i2c_slave = {
-    .name = "pxa2xx_i2c_slave",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_I2C_SLAVE(i2c, PXA2xxI2CSlaveState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_pxa2xx_i2c = {
-    .name = "pxa2xx_i2c",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_UINT16(control, PXA2xxI2CState),
-        VMSTATE_UINT16(status, PXA2xxI2CState),
-        VMSTATE_UINT8(ibmr, PXA2xxI2CState),
-        VMSTATE_UINT8(data, PXA2xxI2CState),
-        VMSTATE_STRUCT_POINTER(slave, PXA2xxI2CState,
-                               vmstate_pxa2xx_i2c_slave, PXA2xxI2CSlaveState *),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int pxa2xx_i2c_slave_init(I2CSlave *i2c)
-{
-    /* Nothing to do.  */
-    return 0;
-}
-
-static void pxa2xx_i2c_slave_class_init(ObjectClass *klass, void *data)
-{
-    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
-
-    k->init = pxa2xx_i2c_slave_init;
-    k->event = pxa2xx_i2c_event;
-    k->recv = pxa2xx_i2c_rx;
-    k->send = pxa2xx_i2c_tx;
-}
-
-static const TypeInfo pxa2xx_i2c_slave_info = {
-    .name          = "pxa2xx-i2c-slave",
-    .parent        = TYPE_I2C_SLAVE,
-    .instance_size = sizeof(PXA2xxI2CSlaveState),
-    .class_init    = pxa2xx_i2c_slave_class_init,
-};
-
-PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
-                qemu_irq irq, uint32_t region_size)
-{
-    DeviceState *dev;
-    SysBusDevice *i2c_dev;
-    PXA2xxI2CState *s;
-
-    i2c_dev = SYS_BUS_DEVICE(qdev_create(NULL, "pxa2xx_i2c"));
-    qdev_prop_set_uint32(&i2c_dev->qdev, "size", region_size + 1);
-    qdev_prop_set_uint32(&i2c_dev->qdev, "offset", base & region_size);
-
-    qdev_init_nofail(&i2c_dev->qdev);
-
-    sysbus_mmio_map(i2c_dev, 0, base & ~region_size);
-    sysbus_connect_irq(i2c_dev, 0, irq);
-
-    s = FROM_SYSBUS(PXA2xxI2CState, i2c_dev);
-    /* FIXME: Should the slave device really be on a separate bus?  */
-    dev = i2c_create_slave(i2c_init_bus(NULL, "dummy"), "pxa2xx-i2c-slave", 0);
-    s->slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, I2C_SLAVE(dev));
-    s->slave->host = s;
-
-    return s;
-}
-
-static int pxa2xx_i2c_initfn(SysBusDevice *dev)
-{
-    PXA2xxI2CState *s = FROM_SYSBUS(PXA2xxI2CState, dev);
-
-    s->bus = i2c_init_bus(&dev->qdev, "i2c");
-
-    memory_region_init_io(&s->iomem, &pxa2xx_i2c_ops, s,
-                          "pxa2xx-i2x", s->region_size);
-    sysbus_init_mmio(dev, &s->iomem);
-    sysbus_init_irq(dev, &s->irq);
-
-    return 0;
-}
-
-i2c_bus *pxa2xx_i2c_bus(PXA2xxI2CState *s)
-{
-    return s->bus;
-}
-
-static Property pxa2xx_i2c_properties[] = {
-    DEFINE_PROP_UINT32("size", PXA2xxI2CState, region_size, 0x10000),
-    DEFINE_PROP_UINT32("offset", PXA2xxI2CState, offset, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = pxa2xx_i2c_initfn;
-    dc->desc = "PXA2xx I2C Bus Controller";
-    dc->vmsd = &vmstate_pxa2xx_i2c;
-    dc->props = pxa2xx_i2c_properties;
-}
-
-static const TypeInfo pxa2xx_i2c_info = {
-    .name          = "pxa2xx_i2c",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PXA2xxI2CState),
-    .class_init    = pxa2xx_i2c_class_init,
-};
-
-/* PXA Inter-IC Sound Controller */
-static void pxa2xx_i2s_reset(PXA2xxI2SState *i2s)
-{
-    i2s->rx_len = 0;
-    i2s->tx_len = 0;
-    i2s->fifo_len = 0;
-    i2s->clk = 0x1a;
-    i2s->control[0] = 0x00;
-    i2s->control[1] = 0x00;
-    i2s->status = 0x00;
-    i2s->mask = 0x00;
-}
-
-#define SACR_TFTH(val) ((val >> 8) & 0xf)
-#define SACR_RFTH(val) ((val >> 12) & 0xf)
-#define SACR_DREC(val) (val & (1 << 3))
-#define SACR_DPRL(val) (val & (1 << 4))
-
-static inline void pxa2xx_i2s_update(PXA2xxI2SState *i2s)
-{
-    int rfs, tfs;
-    rfs = SACR_RFTH(i2s->control[0]) < i2s->rx_len &&
-            !SACR_DREC(i2s->control[1]);
-    tfs = (i2s->tx_len || i2s->fifo_len < SACR_TFTH(i2s->control[0])) &&
-            i2s->enable && !SACR_DPRL(i2s->control[1]);
-
-    qemu_set_irq(i2s->rx_dma, rfs);
-    qemu_set_irq(i2s->tx_dma, tfs);
-
-    i2s->status &= 0xe0;
-    if (i2s->fifo_len < 16 || !i2s->enable)
-        i2s->status |= 1 << 0;                 /* TNF */
-    if (i2s->rx_len)
-        i2s->status |= 1 << 1;                 /* RNE */
-    if (i2s->enable)
-        i2s->status |= 1 << 2;                 /* BSY */
-    if (tfs)
-        i2s->status |= 1 << 3;                 /* TFS */
-    if (rfs)
-        i2s->status |= 1 << 4;                 /* RFS */
-    if (!(i2s->tx_len && i2s->enable))
-        i2s->status |= i2s->fifo_len << 8;     /* TFL */
-    i2s->status |= MAX(i2s->rx_len, 0xf) << 12;        /* RFL */
-
-    qemu_set_irq(i2s->irq, i2s->status & i2s->mask);
-}
-
-#define SACR0  0x00    /* Serial Audio Global Control register */
-#define SACR1  0x04    /* Serial Audio I2S/MSB-Justified Control register */
-#define SASR0  0x0c    /* Serial Audio Interface and FIFO Status register */
-#define SAIMR  0x14    /* Serial Audio Interrupt Mask register */
-#define SAICR  0x18    /* Serial Audio Interrupt Clear register */
-#define SADIV  0x60    /* Serial Audio Clock Divider register */
-#define SADR   0x80    /* Serial Audio Data register */
-
-static uint64_t pxa2xx_i2s_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-
-    switch (addr) {
-    case SACR0:
-        return s->control[0];
-    case SACR1:
-        return s->control[1];
-    case SASR0:
-        return s->status;
-    case SAIMR:
-        return s->mask;
-    case SAICR:
-        return 0;
-    case SADIV:
-        return s->clk;
-    case SADR:
-        if (s->rx_len > 0) {
-            s->rx_len --;
-            pxa2xx_i2s_update(s);
-            return s->codec_in(s->opaque);
-        }
-        return 0;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_i2s_write(void *opaque, hwaddr addr,
-                             uint64_t value, unsigned size)
-{
-    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-    uint32_t *sample;
-
-    switch (addr) {
-    case SACR0:
-        if (value & (1 << 3))                          /* RST */
-            pxa2xx_i2s_reset(s);
-        s->control[0] = value & 0xff3d;
-        if (!s->enable && (value & 1) && s->tx_len) {  /* ENB */
-            for (sample = s->fifo; s->fifo_len > 0; s->fifo_len --, sample ++)
-                s->codec_out(s->opaque, *sample);
-            s->status &= ~(1 << 7);                    /* I2SOFF */
-        }
-        if (value & (1 << 4))                          /* EFWR */
-            printf("%s: Attempt to use special function\n", __FUNCTION__);
-        s->enable = (value & 9) == 1;                  /* ENB && !RST*/
-        pxa2xx_i2s_update(s);
-        break;
-    case SACR1:
-        s->control[1] = value & 0x0039;
-        if (value & (1 << 5))                          /* ENLBF */
-            printf("%s: Attempt to use loopback function\n", __FUNCTION__);
-        if (value & (1 << 4))                          /* DPRL */
-            s->fifo_len = 0;
-        pxa2xx_i2s_update(s);
-        break;
-    case SAIMR:
-        s->mask = value & 0x0078;
-        pxa2xx_i2s_update(s);
-        break;
-    case SAICR:
-        s->status &= ~(value & (3 << 5));
-        pxa2xx_i2s_update(s);
-        break;
-    case SADIV:
-        s->clk = value & 0x007f;
-        break;
-    case SADR:
-        if (s->tx_len && s->enable) {
-            s->tx_len --;
-            pxa2xx_i2s_update(s);
-            s->codec_out(s->opaque, value);
-        } else if (s->fifo_len < 16) {
-            s->fifo[s->fifo_len ++] = value;
-            pxa2xx_i2s_update(s);
-        }
-        break;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-    }
-}
-
-static const MemoryRegionOps pxa2xx_i2s_ops = {
-    .read = pxa2xx_i2s_read,
-    .write = pxa2xx_i2s_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_pxa2xx_i2s = {
-    .name = "pxa2xx_i2s",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(control, PXA2xxI2SState, 2),
-        VMSTATE_UINT32(status, PXA2xxI2SState),
-        VMSTATE_UINT32(mask, PXA2xxI2SState),
-        VMSTATE_UINT32(clk, PXA2xxI2SState),
-        VMSTATE_INT32(enable, PXA2xxI2SState),
-        VMSTATE_INT32(rx_len, PXA2xxI2SState),
-        VMSTATE_INT32(tx_len, PXA2xxI2SState),
-        VMSTATE_INT32(fifo_len, PXA2xxI2SState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx)
-{
-    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-    uint32_t *sample;
-
-    /* Signal FIFO errors */
-    if (s->enable && s->tx_len)
-        s->status |= 1 << 5;           /* TUR */
-    if (s->enable && s->rx_len)
-        s->status |= 1 << 6;           /* ROR */
-
-    /* Should be tx - MIN(tx, s->fifo_len) but we don't really need to
-     * handle the cases where it makes a difference.  */
-    s->tx_len = tx - s->fifo_len;
-    s->rx_len = rx;
-    /* Note that is s->codec_out wasn't set, we wouldn't get called.  */
-    if (s->enable)
-        for (sample = s->fifo; s->fifo_len; s->fifo_len --, sample ++)
-            s->codec_out(s->opaque, *sample);
-    pxa2xx_i2s_update(s);
-}
-
-static PXA2xxI2SState *pxa2xx_i2s_init(MemoryRegion *sysmem,
-                hwaddr base,
-                qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma)
-{
-    PXA2xxI2SState *s = (PXA2xxI2SState *)
-            g_malloc0(sizeof(PXA2xxI2SState));
-
-    s->irq = irq;
-    s->rx_dma = rx_dma;
-    s->tx_dma = tx_dma;
-    s->data_req = pxa2xx_i2s_data_req;
-
-    pxa2xx_i2s_reset(s);
-
-    memory_region_init_io(&s->iomem, &pxa2xx_i2s_ops, s,
-                          "pxa2xx-i2s", 0x100000);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-
-    vmstate_register(NULL, base, &vmstate_pxa2xx_i2s, s);
-
-    return s;
-}
-
-/* PXA Fast Infra-red Communications Port */
-struct PXA2xxFIrState {
-    MemoryRegion iomem;
-    qemu_irq irq;
-    qemu_irq rx_dma;
-    qemu_irq tx_dma;
-    int enable;
-    CharDriverState *chr;
-
-    uint8_t control[3];
-    uint8_t status[2];
-
-    int rx_len;
-    int rx_start;
-    uint8_t rx_fifo[64];
-};
-
-static void pxa2xx_fir_reset(PXA2xxFIrState *s)
-{
-    s->control[0] = 0x00;
-    s->control[1] = 0x00;
-    s->control[2] = 0x00;
-    s->status[0] = 0x00;
-    s->status[1] = 0x00;
-    s->enable = 0;
-}
-
-static inline void pxa2xx_fir_update(PXA2xxFIrState *s)
-{
-    static const int tresh[4] = { 8, 16, 32, 0 };
-    int intr = 0;
-    if ((s->control[0] & (1 << 4)) &&                  /* RXE */
-                    s->rx_len >= tresh[s->control[2] & 3])     /* TRIG */
-        s->status[0] |= 1 << 4;                                /* RFS */
-    else
-        s->status[0] &= ~(1 << 4);                     /* RFS */
-    if (s->control[0] & (1 << 3))                      /* TXE */
-        s->status[0] |= 1 << 3;                                /* TFS */
-    else
-        s->status[0] &= ~(1 << 3);                     /* TFS */
-    if (s->rx_len)
-        s->status[1] |= 1 << 2;                                /* RNE */
-    else
-        s->status[1] &= ~(1 << 2);                     /* RNE */
-    if (s->control[0] & (1 << 4))                      /* RXE */
-        s->status[1] |= 1 << 0;                                /* RSY */
-    else
-        s->status[1] &= ~(1 << 0);                     /* RSY */
-
-    intr |= (s->control[0] & (1 << 5)) &&              /* RIE */
-            (s->status[0] & (1 << 4));                 /* RFS */
-    intr |= (s->control[0] & (1 << 6)) &&              /* TIE */
-            (s->status[0] & (1 << 3));                 /* TFS */
-    intr |= (s->control[2] & (1 << 4)) &&              /* TRAIL */
-            (s->status[0] & (1 << 6));                 /* EOC */
-    intr |= (s->control[0] & (1 << 2)) &&              /* TUS */
-            (s->status[0] & (1 << 1));                 /* TUR */
-    intr |= s->status[0] & 0x25;                       /* FRE, RAB, EIF */
-
-    qemu_set_irq(s->rx_dma, (s->status[0] >> 4) & 1);
-    qemu_set_irq(s->tx_dma, (s->status[0] >> 3) & 1);
-
-    qemu_set_irq(s->irq, intr && s->enable);
-}
-
-#define ICCR0  0x00    /* FICP Control register 0 */
-#define ICCR1  0x04    /* FICP Control register 1 */
-#define ICCR2  0x08    /* FICP Control register 2 */
-#define ICDR   0x0c    /* FICP Data register */
-#define ICSR0  0x14    /* FICP Status register 0 */
-#define ICSR1  0x18    /* FICP Status register 1 */
-#define ICFOR  0x1c    /* FICP FIFO Occupancy Status register */
-
-static uint64_t pxa2xx_fir_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    uint8_t ret;
-
-    switch (addr) {
-    case ICCR0:
-        return s->control[0];
-    case ICCR1:
-        return s->control[1];
-    case ICCR2:
-        return s->control[2];
-    case ICDR:
-        s->status[0] &= ~0x01;
-        s->status[1] &= ~0x72;
-        if (s->rx_len) {
-            s->rx_len --;
-            ret = s->rx_fifo[s->rx_start ++];
-            s->rx_start &= 63;
-            pxa2xx_fir_update(s);
-            return ret;
-        }
-        printf("%s: Rx FIFO underrun.\n", __FUNCTION__);
-        break;
-    case ICSR0:
-        return s->status[0];
-    case ICSR1:
-        return s->status[1] | (1 << 3);                        /* TNF */
-    case ICFOR:
-        return s->rx_len;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_fir_write(void *opaque, hwaddr addr,
-                             uint64_t value64, unsigned size)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    uint32_t value = value64;
-    uint8_t ch;
-
-    switch (addr) {
-    case ICCR0:
-        s->control[0] = value;
-        if (!(value & (1 << 4)))                       /* RXE */
-            s->rx_len = s->rx_start = 0;
-        if (!(value & (1 << 3))) {                      /* TXE */
-            /* Nop */
-        }
-        s->enable = value & 1;                         /* ITR */
-        if (!s->enable)
-            s->status[0] = 0;
-        pxa2xx_fir_update(s);
-        break;
-    case ICCR1:
-        s->control[1] = value;
-        break;
-    case ICCR2:
-        s->control[2] = value & 0x3f;
-        pxa2xx_fir_update(s);
-        break;
-    case ICDR:
-        if (s->control[2] & (1 << 2))                  /* TXP */
-            ch = value;
-        else
-            ch = ~value;
-        if (s->chr && s->enable && (s->control[0] & (1 << 3))) /* TXE */
-            qemu_chr_fe_write(s->chr, &ch, 1);
-        break;
-    case ICSR0:
-        s->status[0] &= ~(value & 0x66);
-        pxa2xx_fir_update(s);
-        break;
-    case ICFOR:
-        break;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-    }
-}
-
-static const MemoryRegionOps pxa2xx_fir_ops = {
-    .read = pxa2xx_fir_read,
-    .write = pxa2xx_fir_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int pxa2xx_fir_is_empty(void *opaque)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    return (s->rx_len < 64);
-}
-
-static void pxa2xx_fir_rx(void *opaque, const uint8_t *buf, int size)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    if (!(s->control[0] & (1 << 4)))                   /* RXE */
-        return;
-
-    while (size --) {
-        s->status[1] |= 1 << 4;                                /* EOF */
-        if (s->rx_len >= 64) {
-            s->status[1] |= 1 << 6;                    /* ROR */
-            break;
-        }
-
-        if (s->control[2] & (1 << 3))                  /* RXP */
-            s->rx_fifo[(s->rx_start + s->rx_len ++) & 63] = *(buf ++);
-        else
-            s->rx_fifo[(s->rx_start + s->rx_len ++) & 63] = ~*(buf ++);
-    }
-
-    pxa2xx_fir_update(s);
-}
-
-static void pxa2xx_fir_event(void *opaque, int event)
-{
-}
-
-static void pxa2xx_fir_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    int i;
-
-    qemu_put_be32(f, s->enable);
-
-    qemu_put_8s(f, &s->control[0]);
-    qemu_put_8s(f, &s->control[1]);
-    qemu_put_8s(f, &s->control[2]);
-    qemu_put_8s(f, &s->status[0]);
-    qemu_put_8s(f, &s->status[1]);
-
-    qemu_put_byte(f, s->rx_len);
-    for (i = 0; i < s->rx_len; i ++)
-        qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 63]);
-}
-
-static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    int i;
-
-    s->enable = qemu_get_be32(f);
-
-    qemu_get_8s(f, &s->control[0]);
-    qemu_get_8s(f, &s->control[1]);
-    qemu_get_8s(f, &s->control[2]);
-    qemu_get_8s(f, &s->status[0]);
-    qemu_get_8s(f, &s->status[1]);
-
-    s->rx_len = qemu_get_byte(f);
-    s->rx_start = 0;
-    for (i = 0; i < s->rx_len; i ++)
-        s->rx_fifo[i] = qemu_get_byte(f);
-
-    return 0;
-}
-
-static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
-                hwaddr base,
-                qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
-                CharDriverState *chr)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *)
-            g_malloc0(sizeof(PXA2xxFIrState));
-
-    s->irq = irq;
-    s->rx_dma = rx_dma;
-    s->tx_dma = tx_dma;
-    s->chr = chr;
-
-    pxa2xx_fir_reset(s);
-
-    memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-
-    if (chr)
-        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
-                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
-
-    register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
-                    pxa2xx_fir_load, s);
-
-    return s;
-}
-
-static void pxa2xx_reset(void *opaque, int line, int level)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    if (level && (s->pm_regs[PCFR >> 2] & 0x10)) {     /* GPR_EN */
-        cpu_reset(CPU(s->cpu));
-        /* TODO: reset peripherals */
-    }
-}
-
-/* Initialise a PXA270 integrated chip (ARM based core).  */
-PXA2xxState *pxa270_init(MemoryRegion *address_space,
-                         unsigned int sdram_size, const char *revision)
-{
-    PXA2xxState *s;
-    int i;
-    DriveInfo *dinfo;
-    s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
-
-    if (revision && strncmp(revision, "pxa27", 5)) {
-        fprintf(stderr, "Machine requires a PXA27x processor.\n");
-        exit(1);
-    }
-    if (!revision)
-        revision = "pxa270";
-    
-    s->cpu = cpu_arm_init(revision);
-    if (s->cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
-
-    /* SDRAM & Internal Memory Storage */
-    memory_region_init_ram(&s->sdram, "pxa270.sdram", sdram_size);
-    vmstate_register_ram_global(&s->sdram);
-    memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
-    memory_region_init_ram(&s->internal, "pxa270.internal", 0x40000);
-    vmstate_register_ram_global(&s->internal);
-    memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
-                                &s->internal);
-
-    s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
-
-    s->dma = pxa27x_dma_init(0x40000000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
-
-    sysbus_create_varargs("pxa27x-timer", 0x40a00000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 0),
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 1),
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 2),
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3),
-                    qdev_get_gpio_in(s->pic, PXA27X_PIC_OST_4_11),
-                    NULL);
-
-    s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 121);
-
-    dinfo = drive_get(IF_SD, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "qemu: missing SecureDigital device\n");
-        exit(1);
-    }
-    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
-                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
-                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
-
-    for (i = 0; pxa270_serial[i].io_base; i++) {
-        if (serial_hds[i]) {
-            serial_mm_init(address_space, pxa270_serial[i].io_base, 2,
-                           qdev_get_gpio_in(s->pic, pxa270_serial[i].irqn),
-                           14857000 / 16, serial_hds[i],
-                           DEVICE_NATIVE_ENDIAN);
-        } else {
-            break;
-        }
-    }
-    if (serial_hds[i])
-        s->fir = pxa2xx_fir_init(address_space, 0x40800000,
-                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
-                        qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_ICP),
-                        qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
-                        serial_hds[i]);
-
-    s->lcd = pxa2xx_lcdc_init(address_space, 0x44000000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
-
-    s->cm_base = 0x41300000;
-    s->cm_regs[CCCR >> 2] = 0x02000210;        /* 416.0 MHz */
-    s->clkcfg = 0x00000009;            /* Turbo mode active */
-    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
-    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
-
-    pxa2xx_setup_cp14(s);
-
-    s->mm_base = 0x48000000;
-    s->mm_regs[MDMRS >> 2] = 0x00020002;
-    s->mm_regs[MDREFR >> 2] = 0x03ca4000;
-    s->mm_regs[MECR >> 2] = 0x00000001;        /* Two PC Card sockets */
-    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
-    memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
-
-    s->pm_base = 0x40f00000;
-    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
-    memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
-
-    for (i = 0; pxa27x_ssp[i].io_base; i ++);
-    s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
-    for (i = 0; pxa27x_ssp[i].io_base; i ++) {
-        DeviceState *dev;
-        dev = sysbus_create_simple("pxa2xx-ssp", pxa27x_ssp[i].io_base,
-                        qdev_get_gpio_in(s->pic, pxa27x_ssp[i].irqn));
-        s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
-    }
-
-    if (usb_enabled(false)) {
-        sysbus_create_simple("sysbus-ohci", 0x4c000000,
-                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
-    }
-
-    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
-    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
-
-    sysbus_create_simple("pxa2xx_rtc", 0x40900000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
-
-    s->i2c[0] = pxa2xx_i2c_init(0x40301600,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2C), 0xffff);
-    s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
-
-    s->i2s = pxa2xx_i2s_init(address_space, 0x40400000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S),
-                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_I2S),
-                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_I2S));
-
-    s->kp = pxa27x_keypad_init(address_space, 0x41500000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_KEYPAD));
-
-    /* GPIO1 resets the processor */
-    /* The handler can be overridden by board-specific code */
-    qdev_connect_gpio_out(s->gpio, 1, s->reset);
-    return s;
-}
-
-/* Initialise a PXA255 integrated chip (ARM based core).  */
-PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
-{
-    PXA2xxState *s;
-    int i;
-    DriveInfo *dinfo;
-
-    s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
-
-    s->cpu = cpu_arm_init("pxa255");
-    if (s->cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
-
-    /* SDRAM & Internal Memory Storage */
-    memory_region_init_ram(&s->sdram, "pxa255.sdram", sdram_size);
-    vmstate_register_ram_global(&s->sdram);
-    memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
-    memory_region_init_ram(&s->internal, "pxa255.internal",
-                           PXA2XX_INTERNAL_SIZE);
-    vmstate_register_ram_global(&s->internal);
-    memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
-                                &s->internal);
-
-    s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
-
-    s->dma = pxa255_dma_init(0x40000000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
-
-    sysbus_create_varargs("pxa25x-timer", 0x40a00000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 0),
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 1),
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 2),
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3),
-                    NULL);
-
-    s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 85);
-
-    dinfo = drive_get(IF_SD, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "qemu: missing SecureDigital device\n");
-        exit(1);
-    }
-    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
-                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
-                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
-
-    for (i = 0; pxa255_serial[i].io_base; i++) {
-        if (serial_hds[i]) {
-            serial_mm_init(address_space, pxa255_serial[i].io_base, 2,
-                           qdev_get_gpio_in(s->pic, pxa255_serial[i].irqn),
-                           14745600 / 16, serial_hds[i],
-                           DEVICE_NATIVE_ENDIAN);
-        } else {
-            break;
-        }
-    }
-    if (serial_hds[i])
-        s->fir = pxa2xx_fir_init(address_space, 0x40800000,
-                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
-                        qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_ICP),
-                        qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
-                        serial_hds[i]);
-
-    s->lcd = pxa2xx_lcdc_init(address_space, 0x44000000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
-
-    s->cm_base = 0x41300000;
-    s->cm_regs[CCCR >> 2] = 0x02000210;        /* 416.0 MHz */
-    s->clkcfg = 0x00000009;            /* Turbo mode active */
-    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
-    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
-
-    pxa2xx_setup_cp14(s);
-
-    s->mm_base = 0x48000000;
-    s->mm_regs[MDMRS >> 2] = 0x00020002;
-    s->mm_regs[MDREFR >> 2] = 0x03ca4000;
-    s->mm_regs[MECR >> 2] = 0x00000001;        /* Two PC Card sockets */
-    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
-    memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
-
-    s->pm_base = 0x40f00000;
-    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
-    memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
-
-    for (i = 0; pxa255_ssp[i].io_base; i ++);
-    s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
-    for (i = 0; pxa255_ssp[i].io_base; i ++) {
-        DeviceState *dev;
-        dev = sysbus_create_simple("pxa2xx-ssp", pxa255_ssp[i].io_base,
-                        qdev_get_gpio_in(s->pic, pxa255_ssp[i].irqn));
-        s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
-    }
-
-    if (usb_enabled(false)) {
-        sysbus_create_simple("sysbus-ohci", 0x4c000000,
-                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
-    }
-
-    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
-    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
-
-    sysbus_create_simple("pxa2xx_rtc", 0x40900000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
-
-    s->i2c[0] = pxa2xx_i2c_init(0x40301600,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2C), 0xffff);
-    s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
-
-    s->i2s = pxa2xx_i2s_init(address_space, 0x40400000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S),
-                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_I2S),
-                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_I2S));
-
-    /* GPIO1 resets the processor */
-    /* The handler can be overridden by board-specific code */
-    qdev_connect_gpio_out(s->gpio, 1, s->reset);
-    return s;
-}
-
-static void pxa2xx_ssp_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = pxa2xx_ssp_init;
-}
-
-static const TypeInfo pxa2xx_ssp_info = {
-    .name          = "pxa2xx-ssp",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PXA2xxSSPState),
-    .class_init    = pxa2xx_ssp_class_init,
-};
-
-static void pxa2xx_register_types(void)
-{
-    type_register_static(&pxa2xx_i2c_slave_info);
-    type_register_static(&pxa2xx_ssp_info);
-    type_register_static(&pxa2xx_i2c_info);
-    type_register_static(&pxa2xx_rtc_sysbus_info);
-}
-
-type_init(pxa2xx_register_types)
index c0dba45752c198126659b4ec0d4883bf3de8c69d..1db21c99ab3f45af76ee4d90cf70aca8cb800fb5 100644 (file)
@@ -8,9 +8,9 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw.h"
-#include "pxa.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/sysbus.h"
 
 #define PXA255_DMA_NUM_CHANNELS 16
 #define PXA27X_DMA_NUM_CHANNELS 32
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
deleted file mode 100644 (file)
index 05d2ad2..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Intel XScale PXA255/270 GPIO controller emulation.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog@zabor.org>
- *
- * This code is licensed under the GPL.
- */
-
-#include "hw.h"
-#include "sysbus.h"
-#include "pxa.h"
-
-#define PXA2XX_GPIO_BANKS      4
-
-typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
-struct PXA2xxGPIOInfo {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    qemu_irq irq0, irq1, irqX;
-    int lines;
-    int ncpu;
-    ARMCPU *cpu;
-
-    /* XXX: GNU C vectors are more suitable */
-    uint32_t ilevel[PXA2XX_GPIO_BANKS];
-    uint32_t olevel[PXA2XX_GPIO_BANKS];
-    uint32_t dir[PXA2XX_GPIO_BANKS];
-    uint32_t rising[PXA2XX_GPIO_BANKS];
-    uint32_t falling[PXA2XX_GPIO_BANKS];
-    uint32_t status[PXA2XX_GPIO_BANKS];
-    uint32_t gpsr[PXA2XX_GPIO_BANKS];
-    uint32_t gafr[PXA2XX_GPIO_BANKS * 2];
-
-    uint32_t prev_level[PXA2XX_GPIO_BANKS];
-    qemu_irq handler[PXA2XX_GPIO_BANKS * 32];
-    qemu_irq read_notify;
-};
-
-static struct {
-    enum {
-        GPIO_NONE,
-        GPLR,
-        GPSR,
-        GPCR,
-        GPDR,
-        GRER,
-        GFER,
-        GEDR,
-        GAFR_L,
-        GAFR_U,
-    } reg;
-    int bank;
-} pxa2xx_gpio_regs[0x200] = {
-    [0 ... 0x1ff] = { GPIO_NONE, 0 },
-#define PXA2XX_REG(reg, a0, a1, a2, a3)        \
-    [a0] = { reg, 0 }, [a1] = { reg, 1 }, [a2] = { reg, 2 }, [a3] = { reg, 3 },
-
-    PXA2XX_REG(GPLR, 0x000, 0x004, 0x008, 0x100)
-    PXA2XX_REG(GPSR, 0x018, 0x01c, 0x020, 0x118)
-    PXA2XX_REG(GPCR, 0x024, 0x028, 0x02c, 0x124)
-    PXA2XX_REG(GPDR, 0x00c, 0x010, 0x014, 0x10c)
-    PXA2XX_REG(GRER, 0x030, 0x034, 0x038, 0x130)
-    PXA2XX_REG(GFER, 0x03c, 0x040, 0x044, 0x13c)
-    PXA2XX_REG(GEDR, 0x048, 0x04c, 0x050, 0x148)
-    PXA2XX_REG(GAFR_L, 0x054, 0x05c, 0x064, 0x06c)
-    PXA2XX_REG(GAFR_U, 0x058, 0x060, 0x068, 0x070)
-};
-
-static void pxa2xx_gpio_irq_update(PXA2xxGPIOInfo *s)
-{
-    if (s->status[0] & (1 << 0))
-        qemu_irq_raise(s->irq0);
-    else
-        qemu_irq_lower(s->irq0);
-
-    if (s->status[0] & (1 << 1))
-        qemu_irq_raise(s->irq1);
-    else
-        qemu_irq_lower(s->irq1);
-
-    if ((s->status[0] & ~3) | s->status[1] | s->status[2] | s->status[3])
-        qemu_irq_raise(s->irqX);
-    else
-        qemu_irq_lower(s->irqX);
-}
-
-/* Bitmap of pins used as standby and sleep wake-up sources.  */
-static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
-    0x8003fe1b, 0x002001fc, 0xec080000, 0x0012007f,
-};
-
-static void pxa2xx_gpio_set(void *opaque, int line, int level)
-{
-    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
-    int bank;
-    uint32_t mask;
-
-    if (line >= s->lines) {
-        printf("%s: No GPIO pin %i\n", __FUNCTION__, line);
-        return;
-    }
-
-    bank = line >> 5;
-    mask = 1 << (line & 31);
-
-    if (level) {
-        s->status[bank] |= s->rising[bank] & mask &
-                ~s->ilevel[bank] & ~s->dir[bank];
-        s->ilevel[bank] |= mask;
-    } else {
-        s->status[bank] |= s->falling[bank] & mask &
-                s->ilevel[bank] & ~s->dir[bank];
-        s->ilevel[bank] &= ~mask;
-    }
-
-    if (s->status[bank] & mask)
-        pxa2xx_gpio_irq_update(s);
-
-    /* Wake-up GPIOs */
-    if (s->cpu->env.halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
-    }
-}
-
-static void pxa2xx_gpio_handler_update(PXA2xxGPIOInfo *s) {
-    uint32_t level, diff;
-    int i, bit, line;
-    for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
-        level = s->olevel[i] & s->dir[i];
-
-        for (diff = s->prev_level[i] ^ level; diff; diff ^= 1 << bit) {
-            bit = ffs(diff) - 1;
-            line = bit + 32 * i;
-            qemu_set_irq(s->handler[line], (level >> bit) & 1);
-        }
-
-        s->prev_level[i] = level;
-    }
-}
-
-static uint64_t pxa2xx_gpio_read(void *opaque, hwaddr offset,
-                                 unsigned size)
-{
-    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
-    uint32_t ret;
-    int bank;
-    if (offset >= 0x200)
-        return 0;
-
-    bank = pxa2xx_gpio_regs[offset].bank;
-    switch (pxa2xx_gpio_regs[offset].reg) {
-    case GPDR:         /* GPIO Pin-Direction registers */
-        return s->dir[bank];
-
-    case GPSR:         /* GPIO Pin-Output Set registers */
-        printf("%s: Read from a write-only register " REG_FMT "\n",
-                        __FUNCTION__, offset);
-        return s->gpsr[bank];  /* Return last written value.  */
-
-    case GPCR:         /* GPIO Pin-Output Clear registers */
-        printf("%s: Read from a write-only register " REG_FMT "\n",
-                        __FUNCTION__, offset);
-        return 31337;          /* Specified as unpredictable in the docs.  */
-
-    case GRER:         /* GPIO Rising-Edge Detect Enable registers */
-        return s->rising[bank];
-
-    case GFER:         /* GPIO Falling-Edge Detect Enable registers */
-        return s->falling[bank];
-
-    case GAFR_L:       /* GPIO Alternate Function registers */
-        return s->gafr[bank * 2];
-
-    case GAFR_U:       /* GPIO Alternate Function registers */
-        return s->gafr[bank * 2 + 1];
-
-    case GPLR:         /* GPIO Pin-Level registers */
-        ret = (s->olevel[bank] & s->dir[bank]) |
-                (s->ilevel[bank] & ~s->dir[bank]);
-        qemu_irq_raise(s->read_notify);
-        return ret;
-
-    case GEDR:         /* GPIO Edge Detect Status registers */
-        return s->status[bank];
-
-    default:
-        hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
-    }
-
-    return 0;
-}
-
-static void pxa2xx_gpio_write(void *opaque, hwaddr offset,
-                              uint64_t value, unsigned size)
-{
-    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
-    int bank;
-    if (offset >= 0x200)
-        return;
-
-    bank = pxa2xx_gpio_regs[offset].bank;
-    switch (pxa2xx_gpio_regs[offset].reg) {
-    case GPDR:         /* GPIO Pin-Direction registers */
-        s->dir[bank] = value;
-        pxa2xx_gpio_handler_update(s);
-        break;
-
-    case GPSR:         /* GPIO Pin-Output Set registers */
-        s->olevel[bank] |= value;
-        pxa2xx_gpio_handler_update(s);
-        s->gpsr[bank] = value;
-        break;
-
-    case GPCR:         /* GPIO Pin-Output Clear registers */
-        s->olevel[bank] &= ~value;
-        pxa2xx_gpio_handler_update(s);
-        break;
-
-    case GRER:         /* GPIO Rising-Edge Detect Enable registers */
-        s->rising[bank] = value;
-        break;
-
-    case GFER:         /* GPIO Falling-Edge Detect Enable registers */
-        s->falling[bank] = value;
-        break;
-
-    case GAFR_L:       /* GPIO Alternate Function registers */
-        s->gafr[bank * 2] = value;
-        break;
-
-    case GAFR_U:       /* GPIO Alternate Function registers */
-        s->gafr[bank * 2 + 1] = value;
-        break;
-
-    case GEDR:         /* GPIO Edge Detect Status registers */
-        s->status[bank] &= ~value;
-        pxa2xx_gpio_irq_update(s);
-        break;
-
-    default:
-        hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
-    }
-}
-
-static const MemoryRegionOps pxa_gpio_ops = {
-    .read = pxa2xx_gpio_read,
-    .write = pxa2xx_gpio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-DeviceState *pxa2xx_gpio_init(hwaddr base,
-                              ARMCPU *cpu, DeviceState *pic, int lines)
-{
-    CPUState *cs = CPU(cpu);
-    DeviceState *dev;
-
-    dev = qdev_create(NULL, "pxa2xx-gpio");
-    qdev_prop_set_int32(dev, "lines", lines);
-    qdev_prop_set_int32(dev, "ncpu", cs->cpu_index);
-    qdev_init_nofail(dev);
-
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
-                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_0));
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1,
-                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_1));
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2,
-                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_X));
-
-    return dev;
-}
-
-static int pxa2xx_gpio_initfn(SysBusDevice *dev)
-{
-    PXA2xxGPIOInfo *s;
-
-    s = FROM_SYSBUS(PXA2xxGPIOInfo, dev);
-
-    s->cpu = ARM_CPU(qemu_get_cpu(s->ncpu));
-
-    qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
-    qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
-
-    memory_region_init_io(&s->iomem, &pxa_gpio_ops, s, "pxa2xx-gpio", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    sysbus_init_irq(dev, &s->irq0);
-    sysbus_init_irq(dev, &s->irq1);
-    sysbus_init_irq(dev, &s->irqX);
-
-    return 0;
-}
-
-/*
- * Registers a callback to notify on GPLR reads.  This normally
- * shouldn't be needed but it is used for the hack on Spitz machines.
- */
-void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler)
-{
-    PXA2xxGPIOInfo *s = FROM_SYSBUS(PXA2xxGPIOInfo, SYS_BUS_DEVICE(dev));
-    s->read_notify = handler;
-}
-
-static const VMStateDescription vmstate_pxa2xx_gpio_regs = {
-    .name = "pxa2xx-gpio",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField []) {
-        VMSTATE_INT32(lines, PXA2xxGPIOInfo),
-        VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(olevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(dir, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(rising, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(falling, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(status, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(gafr, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS * 2),
-        VMSTATE_END_OF_LIST(),
-    },
-};
-
-static Property pxa2xx_gpio_properties[] = {
-    DEFINE_PROP_INT32("lines", PXA2xxGPIOInfo, lines, 0),
-    DEFINE_PROP_INT32("ncpu", PXA2xxGPIOInfo, ncpu, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = pxa2xx_gpio_initfn;
-    dc->desc = "PXA2xx GPIO controller";
-    dc->props = pxa2xx_gpio_properties;
-}
-
-static const TypeInfo pxa2xx_gpio_info = {
-    .name          = "pxa2xx-gpio",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PXA2xxGPIOInfo),
-    .class_init    = pxa2xx_gpio_class_init,
-};
-
-static void pxa2xx_gpio_register_types(void)
-{
-    type_register_static(&pxa2xx_gpio_info);
-}
-
-type_init(pxa2xx_gpio_register_types)
index 4ff04ad63b3452e707808a3ab9c0e6510ddd08ed..32ea7a5d34c7b7d73b756229a0b73f3af7c51282 100644 (file)
@@ -11,8 +11,8 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "pxa.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
 #include "ui/console.h"
 
 /*
index 512a27e702926043214e5de6fd4ccadbb1931468..6484d27de188ed3edaab243a7bbb13cabf113733 100644 (file)
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "pxa.h"
+#include "hw/pxa.h"
 #include "ui/pixel_ops.h"
 /* FIXME: For graphic_rotate. Should probably be done in common code.  */
 #include "sysemu/sysemu.h"
-#include "framebuffer.h"
+#include "hw/framebuffer.h"
 
 struct DMAChannel {
     uint32_t branch;
@@ -976,15 +976,15 @@ static const VMStateDescription vmstate_pxa2xx_lcdc = {
 };
 
 #define BITS 8
-#include "pxa2xx_template.h"
+#include "hw/pxa2xx_template.h"
 #define BITS 15
-#include "pxa2xx_template.h"
+#include "hw/pxa2xx_template.h"
 #define BITS 16
-#include "pxa2xx_template.h"
+#include "hw/pxa2xx_template.h"
 #define BITS 24
-#include "pxa2xx_template.h"
+#include "hw/pxa2xx_template.h"
 #define BITS 32
-#include "pxa2xx_template.h"
+#include "hw/pxa2xx_template.h"
 
 PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
                                  hwaddr base, qemu_irq irq)
index 3589968712570270f970d56aab169aaa33c9cbfb..0df83cc1df8ad3f4e5a0f358f66be168526dec38 100644 (file)
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "pxa.h"
-#include "sd.h"
-#include "qdev.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/sd.h"
+#include "hw/qdev.h"
 
 struct PXA2xxMMCIState {
     MemoryRegion iomem;
index 3a79c728ab2446e76374b9c4da63eb324032b175..66fefba58cea252444a1d67cdf78eb814fac5e01 100644 (file)
@@ -10,9 +10,9 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "pcmcia.h"
-#include "pxa.h"
+#include "hw/hw.h"
+#include "hw/pcmcia.h"
+#include "hw/pxa.h"
 
 
 struct PXA2xxPCMCIAState {
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
deleted file mode 100644 (file)
index 90b8fef..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Intel XScale PXA Programmable Interrupt Controller.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Copyright (c) 2006 Thorsten Zitterell
- * Written by Andrzej Zaborowski <balrog@zabor.org>
- *
- * This code is licensed under the GPL.
- */
-
-#include "hw.h"
-#include "pxa.h"
-#include "sysbus.h"
-
-#define ICIP   0x00    /* Interrupt Controller IRQ Pending register */
-#define ICMR   0x04    /* Interrupt Controller Mask register */
-#define ICLR   0x08    /* Interrupt Controller Level register */
-#define ICFP   0x0c    /* Interrupt Controller FIQ Pending register */
-#define ICPR   0x10    /* Interrupt Controller Pending register */
-#define ICCR   0x14    /* Interrupt Controller Control register */
-#define ICHP   0x18    /* Interrupt Controller Highest Priority register */
-#define IPR0   0x1c    /* Interrupt Controller Priority register 0 */
-#define IPR31  0x98    /* Interrupt Controller Priority register 31 */
-#define ICIP2  0x9c    /* Interrupt Controller IRQ Pending register 2 */
-#define ICMR2  0xa0    /* Interrupt Controller Mask register 2 */
-#define ICLR2  0xa4    /* Interrupt Controller Level register 2 */
-#define ICFP2  0xa8    /* Interrupt Controller FIQ Pending register 2 */
-#define ICPR2  0xac    /* Interrupt Controller Pending register 2 */
-#define IPR32  0xb0    /* Interrupt Controller Priority register 32 */
-#define IPR39  0xcc    /* Interrupt Controller Priority register 39 */
-
-#define PXA2XX_PIC_SRCS        40
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    ARMCPU *cpu;
-    uint32_t int_enabled[2];
-    uint32_t int_pending[2];
-    uint32_t is_fiq[2];
-    uint32_t int_idle;
-    uint32_t priority[PXA2XX_PIC_SRCS];
-} PXA2xxPICState;
-
-static void pxa2xx_pic_update(void *opaque)
-{
-    uint32_t mask[2];
-    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-
-    if (s->cpu->env.halted) {
-        mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
-        mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
-        if (mask[0] || mask[1]) {
-            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
-        }
-    }
-
-    mask[0] = s->int_pending[0] & s->int_enabled[0];
-    mask[1] = s->int_pending[1] & s->int_enabled[1];
-
-    if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
-    } else {
-        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
-    }
-
-    if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
-    } else {
-        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
-    }
-}
-
-/* Note: Here level means state of the signal on a pin, not
- * IRQ/FIQ distinction as in PXA Developer Manual.  */
-static void pxa2xx_pic_set_irq(void *opaque, int irq, int level)
-{
-    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-    int int_set = (irq >= 32);
-    irq &= 31;
-
-    if (level)
-        s->int_pending[int_set] |= 1 << irq;
-    else
-        s->int_pending[int_set] &= ~(1 << irq);
-
-    pxa2xx_pic_update(opaque);
-}
-
-static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
-    int i, int_set, irq;
-    uint32_t bit, mask[2];
-    uint32_t ichp = 0x003f003f;        /* Both IDs invalid */
-
-    mask[0] = s->int_pending[0] & s->int_enabled[0];
-    mask[1] = s->int_pending[1] & s->int_enabled[1];
-
-    for (i = PXA2XX_PIC_SRCS - 1; i >= 0; i --) {
-        irq = s->priority[i] & 0x3f;
-        if ((s->priority[i] & (1 << 31)) && irq < PXA2XX_PIC_SRCS) {
-            /* Source peripheral ID is valid.  */
-            bit = 1 << (irq & 31);
-            int_set = (irq >= 32);
-
-            if (mask[int_set] & bit & s->is_fiq[int_set]) {
-                /* FIQ asserted */
-                ichp &= 0xffff0000;
-                ichp |= (1 << 15) | irq;
-            }
-
-            if (mask[int_set] & bit & ~s->is_fiq[int_set]) {
-                /* IRQ asserted */
-                ichp &= 0x0000ffff;
-                ichp |= (1 << 31) | (irq << 16);
-            }
-        }
-    }
-
-    return ichp;
-}
-
-static uint64_t pxa2xx_pic_mem_read(void *opaque, hwaddr offset,
-                                    unsigned size)
-{
-    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-
-    switch (offset) {
-    case ICIP: /* IRQ Pending register */
-        return s->int_pending[0] & ~s->is_fiq[0] & s->int_enabled[0];
-    case ICIP2:        /* IRQ Pending register 2 */
-        return s->int_pending[1] & ~s->is_fiq[1] & s->int_enabled[1];
-    case ICMR: /* Mask register */
-        return s->int_enabled[0];
-    case ICMR2:        /* Mask register 2 */
-        return s->int_enabled[1];
-    case ICLR: /* Level register */
-        return s->is_fiq[0];
-    case ICLR2:        /* Level register 2 */
-        return s->is_fiq[1];
-    case ICCR: /* Idle mask */
-        return (s->int_idle == 0);
-    case ICFP: /* FIQ Pending register */
-        return s->int_pending[0] & s->is_fiq[0] & s->int_enabled[0];
-    case ICFP2:        /* FIQ Pending register 2 */
-        return s->int_pending[1] & s->is_fiq[1] & s->int_enabled[1];
-    case ICPR: /* Pending register */
-        return s->int_pending[0];
-    case ICPR2:        /* Pending register 2 */
-        return s->int_pending[1];
-    case IPR0  ... IPR31:
-        return s->priority[0  + ((offset - IPR0 ) >> 2)];
-    case IPR32 ... IPR39:
-        return s->priority[32 + ((offset - IPR32) >> 2)];
-    case ICHP: /* Highest Priority register */
-        return pxa2xx_pic_highest(s);
-    default:
-        printf("%s: Bad register offset " REG_FMT "\n", __FUNCTION__, offset);
-        return 0;
-    }
-}
-
-static void pxa2xx_pic_mem_write(void *opaque, hwaddr offset,
-                                 uint64_t value, unsigned size)
-{
-    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-
-    switch (offset) {
-    case ICMR: /* Mask register */
-        s->int_enabled[0] = value;
-        break;
-    case ICMR2:        /* Mask register 2 */
-        s->int_enabled[1] = value;
-        break;
-    case ICLR: /* Level register */
-        s->is_fiq[0] = value;
-        break;
-    case ICLR2:        /* Level register 2 */
-        s->is_fiq[1] = value;
-        break;
-    case ICCR: /* Idle mask */
-        s->int_idle = (value & 1) ? 0 : ~0;
-        break;
-    case IPR0  ... IPR31:
-        s->priority[0  + ((offset - IPR0 ) >> 2)] = value & 0x8000003f;
-        break;
-    case IPR32 ... IPR39:
-        s->priority[32 + ((offset - IPR32) >> 2)] = value & 0x8000003f;
-        break;
-    default:
-        printf("%s: Bad register offset " REG_FMT "\n", __FUNCTION__, offset);
-        return;
-    }
-    pxa2xx_pic_update(opaque);
-}
-
-/* Interrupt Controller Coprocessor Space Register Mapping */
-static const int pxa2xx_cp_reg_map[0x10] = {
-    [0x0 ... 0xf] = -1,
-    [0x0] = ICIP,
-    [0x1] = ICMR,
-    [0x2] = ICLR,
-    [0x3] = ICFP,
-    [0x4] = ICPR,
-    [0x5] = ICHP,
-    [0x6] = ICIP2,
-    [0x7] = ICMR2,
-    [0x8] = ICLR2,
-    [0x9] = ICFP2,
-    [0xa] = ICPR2,
-};
-
-static int pxa2xx_pic_cp_read(CPUARMState *env, const ARMCPRegInfo *ri,
-                              uint64_t *value)
-{
-    int offset = pxa2xx_cp_reg_map[ri->crn];
-    *value = pxa2xx_pic_mem_read(ri->opaque, offset, 4);
-    return 0;
-}
-
-static int pxa2xx_pic_cp_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                               uint64_t value)
-{
-    int offset = pxa2xx_cp_reg_map[ri->crn];
-    pxa2xx_pic_mem_write(ri->opaque, offset, value, 4);
-    return 0;
-}
-
-#define REGINFO_FOR_PIC_CP(NAME, CRN) \
-    { .name = NAME, .cp = 6, .crn = CRN, .crm = 0, .opc1 = 0, .opc2 = 0, \
-      .access = PL1_RW, \
-      .readfn = pxa2xx_pic_cp_read, .writefn = pxa2xx_pic_cp_write }
-
-static const ARMCPRegInfo pxa_pic_cp_reginfo[] = {
-    REGINFO_FOR_PIC_CP("ICIP", 0),
-    REGINFO_FOR_PIC_CP("ICMR", 1),
-    REGINFO_FOR_PIC_CP("ICLR", 2),
-    REGINFO_FOR_PIC_CP("ICFP", 3),
-    REGINFO_FOR_PIC_CP("ICPR", 4),
-    REGINFO_FOR_PIC_CP("ICHP", 5),
-    REGINFO_FOR_PIC_CP("ICIP2", 6),
-    REGINFO_FOR_PIC_CP("ICMR2", 7),
-    REGINFO_FOR_PIC_CP("ICLR2", 8),
-    REGINFO_FOR_PIC_CP("ICFP2", 9),
-    REGINFO_FOR_PIC_CP("ICPR2", 0xa),
-    REGINFO_SENTINEL
-};
-
-static const MemoryRegionOps pxa2xx_pic_ops = {
-    .read = pxa2xx_pic_mem_read,
-    .write = pxa2xx_pic_mem_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int pxa2xx_pic_post_load(void *opaque, int version_id)
-{
-    pxa2xx_pic_update(opaque);
-    return 0;
-}
-
-DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu)
-{
-    CPUARMState *env = &cpu->env;
-    DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
-    PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, SYS_BUS_DEVICE(dev));
-
-    s->cpu = cpu;
-
-    s->int_pending[0] = 0;
-    s->int_pending[1] = 0;
-    s->int_enabled[0] = 0;
-    s->int_enabled[1] = 0;
-    s->is_fiq[0] = 0;
-    s->is_fiq[1] = 0;
-
-    qdev_init_nofail(dev);
-
-    qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS);
-
-    /* Enable IC memory-mapped registers access.  */
-    memory_region_init_io(&s->iomem, &pxa2xx_pic_ops, s,
-                          "pxa2xx-pic", 0x00100000);
-    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
-
-    /* Enable IC coprocessor access.  */
-    define_arm_cp_regs_with_opaque(arm_env_get_cpu(env), pxa_pic_cp_reginfo, s);
-
-    return dev;
-}
-
-static VMStateDescription vmstate_pxa2xx_pic_regs = {
-    .name = "pxa2xx_pic",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .post_load = pxa2xx_pic_post_load,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(int_enabled, PXA2xxPICState, 2),
-        VMSTATE_UINT32_ARRAY(int_pending, PXA2xxPICState, 2),
-        VMSTATE_UINT32_ARRAY(is_fiq, PXA2xxPICState, 2),
-        VMSTATE_UINT32(int_idle, PXA2xxPICState),
-        VMSTATE_UINT32_ARRAY(priority, PXA2xxPICState, PXA2XX_PIC_SRCS),
-        VMSTATE_END_OF_LIST(),
-    },
-};
-
-static int pxa2xx_pic_initfn(SysBusDevice *dev)
-{
-    return 0;
-}
-
-static void pxa2xx_pic_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = pxa2xx_pic_initfn;
-    dc->desc = "PXA2xx PIC";
-    dc->vmsd = &vmstate_pxa2xx_pic_regs;
-}
-
-static const TypeInfo pxa2xx_pic_info = {
-    .name          = "pxa2xx_pic",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PXA2xxPICState),
-    .class_init    = pxa2xx_pic_class_init,
-};
-
-static void pxa2xx_pic_register_types(void)
-{
-    type_register_static(&pxa2xx_pic_info);
-}
-
-type_init(pxa2xx_pic_register_types)
index 5c9d2e8bc6b77e9aa2ab78ab78928e11620dc6f0..c173fe4c1158b7cf7afe65cb5a3799e6e1d56fa0 100644 (file)
@@ -7,11 +7,11 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
-#include "pxa.h"
-#include "sysbus.h"
+#include "hw/pxa.h"
+#include "hw/sysbus.h"
 
 #define OSMR0  0x00
 #define OSMR1  0x04
index efebc2786ac736642be00a7c296b90cf60487f37..0a25b8bf1fef5fc6fd062c39e1d3d5357d4593d9 100644 (file)
--- a/hw/q35.c
+++ b/hw/q35.c
@@ -27,8 +27,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "q35.h"
+#include "hw/hw.h"
+#include "hw/q35.h"
 
 /****************************************************************************
  * Q35 host
index 246c12cb0440ae7f556ab8aabcf9215149193ae4..d766bb7b023498c7354fd142415f41a54f1f6f77 100644 (file)
--- a/hw/q35.h
+++ b/hw/q35.h
 #ifndef HW_Q35_H
 #define HW_Q35_H
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/range.h"
-#include "isa.h"
-#include "sysbus.h"
-#include "pc.h"
-#include "apm.h"
-#include "apic.h"
-#include "pci/pci.h"
-#include "pci/pcie_host.h"
-#include "acpi.h"
-#include "acpi_ich9.h"
-#include "pam.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
+#include "hw/pc.h"
+#include "hw/apm.h"
+#include "hw/apic.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/acpi.h"
+#include "hw/acpi_ich9.h"
+#include "hw/pam.h"
 
 #define TYPE_Q35_HOST_DEVICE "q35-pcihost"
 #define Q35_HOST_DEVICE(obj) \
index b4388f6a663046db59871e6789cd4891bc6b73d0..2398b4a37fce7bf5a768a4fb8298da1dee310a64 100644 (file)
@@ -1,6 +1,7 @@
-#include "qdev.h"
-#include "qdev-addr.h"
+#include "hw/qdev.h"
+#include "hw/qdev-addr.h"
 #include "exec/hwaddr.h"
+#include "qapi/qmp/qerror.h"
 #include "qapi/visitor.h"
 
 /* --- target physical address --- */
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
deleted file mode 100644 (file)
index 4f9a6eb..0000000
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- *  Dynamic device configuration and creation.
- *
- *  Copyright (c) 2009 CodeSourcery
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qdev.h"
-#include "monitor/monitor.h"
-#include "qmp-commands.h"
-#include "sysemu/arch_init.h"
-#include "qemu/config-file.h"
-
-/*
- * Aliases were a bad idea from the start.  Let's keep them
- * from spreading further.
- */
-typedef struct QDevAlias
-{
-    const char *typename;
-    const char *alias;
-    uint32_t arch_mask;
-} QDevAlias;
-
-static const QDevAlias qdev_alias_table[] = {
-    { "virtio-blk-pci", "virtio-blk", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
-    { "virtio-net-pci", "virtio-net", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
-    { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
-    { "virtio-balloon-pci", "virtio-balloon",
-            QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
-    { "virtio-blk-s390", "virtio-blk", QEMU_ARCH_S390X },
-    { "virtio-net-s390", "virtio-net", QEMU_ARCH_S390X },
-    { "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X },
-    { "lsi53c895a", "lsi" },
-    { "ich9-ahci", "ahci" },
-    { "kvm-pci-assign", "pci-assign" },
-    { }
-};
-
-static const char *qdev_class_get_alias(DeviceClass *dc)
-{
-    const char *typename = object_class_get_name(OBJECT_CLASS(dc));
-    int i;
-
-    for (i = 0; qdev_alias_table[i].typename; i++) {
-        if (qdev_alias_table[i].arch_mask &&
-            !(qdev_alias_table[i].arch_mask & arch_type)) {
-            continue;
-        }
-
-        if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
-            return qdev_alias_table[i].alias;
-        }
-    }
-
-    return NULL;
-}
-
-static bool qdev_class_has_alias(DeviceClass *dc)
-{
-    return (qdev_class_get_alias(dc) != NULL);
-}
-
-static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
-{
-    DeviceClass *dc;
-    bool *show_no_user = opaque;
-
-    dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
-
-    if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
-        return;
-    }
-
-    error_printf("name \"%s\"", object_class_get_name(klass));
-    if (dc->bus_type) {
-        error_printf(", bus %s", dc->bus_type);
-    }
-    if (qdev_class_has_alias(dc)) {
-        error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
-    }
-    if (dc->desc) {
-        error_printf(", desc \"%s\"", dc->desc);
-    }
-    if (dc->no_user) {
-        error_printf(", no-user");
-    }
-    error_printf("\n");
-}
-
-static int set_property(const char *name, const char *value, void *opaque)
-{
-    DeviceState *dev = opaque;
-
-    if (strcmp(name, "driver") == 0)
-        return 0;
-    if (strcmp(name, "bus") == 0)
-        return 0;
-
-    if (qdev_prop_parse(dev, name, value) == -1) {
-        return -1;
-    }
-    return 0;
-}
-
-static const char *find_typename_by_alias(const char *alias)
-{
-    int i;
-
-    for (i = 0; qdev_alias_table[i].alias; i++) {
-        if (qdev_alias_table[i].arch_mask &&
-            !(qdev_alias_table[i].arch_mask & arch_type)) {
-            continue;
-        }
-
-        if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
-            return qdev_alias_table[i].typename;
-        }
-    }
-
-    return NULL;
-}
-
-int qdev_device_help(QemuOpts *opts)
-{
-    const char *driver;
-    Property *prop;
-    ObjectClass *klass;
-
-    driver = qemu_opt_get(opts, "driver");
-    if (driver && is_help_option(driver)) {
-        bool show_no_user = false;
-        object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
-        return 1;
-    }
-
-    if (!driver || !qemu_opt_has_help_opt(opts)) {
-        return 0;
-    }
-
-    klass = object_class_by_name(driver);
-    if (!klass) {
-        const char *typename = find_typename_by_alias(driver);
-
-        if (typename) {
-            driver = typename;
-            klass = object_class_by_name(driver);
-        }
-    }
-
-    if (!klass) {
-        return 0;
-    }
-    do {
-        for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
-            /*
-             * TODO Properties without a parser are just for dirty hacks.
-             * qdev_prop_ptr is the only such PropertyInfo.  It's marked
-             * for removal.  This conditional should be removed along with
-             * it.
-             */
-            if (!prop->info->set) {
-                continue;           /* no way to set it, don't show */
-            }
-            error_printf("%s.%s=%s\n", driver, prop->name,
-                         prop->info->legacy_name ?: prop->info->name);
-        }
-        klass = object_class_get_parent(klass);
-    } while (klass != object_class_by_name(TYPE_DEVICE));
-    return 1;
-}
-
-static Object *qdev_get_peripheral(void)
-{
-    static Object *dev;
-
-    if (dev == NULL) {
-        dev = container_get(qdev_get_machine(), "/peripheral");
-    }
-
-    return dev;
-}
-
-static Object *qdev_get_peripheral_anon(void)
-{
-    static Object *dev;
-
-    if (dev == NULL) {
-        dev = container_get(qdev_get_machine(), "/peripheral-anon");
-    }
-
-    return dev;
-}
-
-static void qbus_list_bus(DeviceState *dev)
-{
-    BusState *child;
-    const char *sep = " ";
-
-    error_printf("child busses at \"%s\":",
-                 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
-    QLIST_FOREACH(child, &dev->child_bus, sibling) {
-        error_printf("%s\"%s\"", sep, child->name);
-        sep = ", ";
-    }
-    error_printf("\n");
-}
-
-static void qbus_list_dev(BusState *bus)
-{
-    BusChild *kid;
-    const char *sep = " ";
-
-    error_printf("devices at \"%s\":", bus->name);
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
-        if (dev->id)
-            error_printf("/\"%s\"", dev->id);
-        sep = ", ";
-    }
-    error_printf("\n");
-}
-
-static BusState *qbus_find_bus(DeviceState *dev, char *elem)
-{
-    BusState *child;
-
-    QLIST_FOREACH(child, &dev->child_bus, sibling) {
-        if (strcmp(child->name, elem) == 0) {
-            return child;
-        }
-    }
-    return NULL;
-}
-
-static DeviceState *qbus_find_dev(BusState *bus, char *elem)
-{
-    BusChild *kid;
-
-    /*
-     * try to match in order:
-     *   (1) instance id, if present
-     *   (2) driver name
-     *   (3) driver alias, if present
-     */
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
-            return dev;
-        }
-    }
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
-            return dev;
-        }
-    }
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        DeviceClass *dc = DEVICE_GET_CLASS(dev);
-
-        if (qdev_class_has_alias(dc) &&
-            strcmp(qdev_class_get_alias(dc), elem) == 0) {
-            return dev;
-        }
-    }
-    return NULL;
-}
-
-static BusState *qbus_find_recursive(BusState *bus, const char *name,
-                                     const char *bus_typename)
-{
-    BusClass *bus_class = BUS_GET_CLASS(bus);
-    BusChild *kid;
-    BusState *child, *ret;
-    int match = 1;
-
-    if (name && (strcmp(bus->name, name) != 0)) {
-        match = 0;
-    }
-    if (bus_typename && !object_dynamic_cast(OBJECT(bus), bus_typename)) {
-        match = 0;
-    }
-    if ((bus_class->max_dev != 0) && (bus_class->max_dev <= bus->max_index)) {
-        if (name != NULL) {
-            /* bus was explicitly specified: return an error. */
-            qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full",
-                          bus->name);
-            return NULL;
-        } else {
-            /* bus was not specified: try to find another one. */
-            match = 0;
-        }
-    }
-    if (match) {
-        return bus;
-    }
-
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        QLIST_FOREACH(child, &dev->child_bus, sibling) {
-            ret = qbus_find_recursive(child, name, bus_typename);
-            if (ret) {
-                return ret;
-            }
-        }
-    }
-    return NULL;
-}
-
-static BusState *qbus_find(const char *path)
-{
-    DeviceState *dev;
-    BusState *bus;
-    char elem[128];
-    int pos, len;
-
-    /* find start element */
-    if (path[0] == '/') {
-        bus = sysbus_get_default();
-        pos = 0;
-    } else {
-        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
-            assert(!path[0]);
-            elem[0] = len = 0;
-        }
-        bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
-        if (!bus) {
-            qerror_report(QERR_BUS_NOT_FOUND, elem);
-            return NULL;
-        }
-        pos = len;
-    }
-
-    for (;;) {
-        assert(path[pos] == '/' || !path[pos]);
-        while (path[pos] == '/') {
-            pos++;
-        }
-        if (path[pos] == '\0') {
-            return bus;
-        }
-
-        /* find device */
-        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
-            assert(0);
-            elem[0] = len = 0;
-        }
-        pos += len;
-        dev = qbus_find_dev(bus, elem);
-        if (!dev) {
-            qerror_report(QERR_DEVICE_NOT_FOUND, elem);
-            if (!monitor_cur_is_qmp()) {
-                qbus_list_dev(bus);
-            }
-            return NULL;
-        }
-
-        assert(path[pos] == '/' || !path[pos]);
-        while (path[pos] == '/') {
-            pos++;
-        }
-        if (path[pos] == '\0') {
-            /* last specified element is a device.  If it has exactly
-             * one child bus accept it nevertheless */
-            switch (dev->num_child_bus) {
-            case 0:
-                qerror_report(QERR_DEVICE_NO_BUS, elem);
-                return NULL;
-            case 1:
-                return QLIST_FIRST(&dev->child_bus);
-            default:
-                qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
-                if (!monitor_cur_is_qmp()) {
-                    qbus_list_bus(dev);
-                }
-                return NULL;
-            }
-        }
-
-        /* find bus */
-        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
-            assert(0);
-            elem[0] = len = 0;
-        }
-        pos += len;
-        bus = qbus_find_bus(dev, elem);
-        if (!bus) {
-            qerror_report(QERR_BUS_NOT_FOUND, elem);
-            if (!monitor_cur_is_qmp()) {
-                qbus_list_bus(dev);
-            }
-            return NULL;
-        }
-    }
-}
-
-DeviceState *qdev_device_add(QemuOpts *opts)
-{
-    ObjectClass *obj;
-    DeviceClass *k;
-    const char *driver, *path, *id;
-    DeviceState *qdev;
-    BusState *bus;
-
-    driver = qemu_opt_get(opts, "driver");
-    if (!driver) {
-        qerror_report(QERR_MISSING_PARAMETER, "driver");
-        return NULL;
-    }
-
-    /* find driver */
-    obj = object_class_by_name(driver);
-    if (!obj) {
-        const char *typename = find_typename_by_alias(driver);
-
-        if (typename) {
-            driver = typename;
-            obj = object_class_by_name(driver);
-        }
-    }
-
-    if (!obj) {
-        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
-        return NULL;
-    }
-
-    k = DEVICE_CLASS(obj);
-
-    /* find bus */
-    path = qemu_opt_get(opts, "bus");
-    if (path != NULL) {
-        bus = qbus_find(path);
-        if (!bus) {
-            return NULL;
-        }
-        if (!object_dynamic_cast(OBJECT(bus), k->bus_type)) {
-            qerror_report(QERR_BAD_BUS_FOR_DEVICE,
-                          driver, object_get_typename(OBJECT(bus)));
-            return NULL;
-        }
-    } else {
-        bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type);
-        if (!bus) {
-            qerror_report(QERR_NO_BUS_FOR_DEVICE,
-                          k->bus_type, driver);
-            return NULL;
-        }
-    }
-    if (qdev_hotplug && !bus->allow_hotplug) {
-        qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
-        return NULL;
-    }
-
-    if (!bus) {
-        bus = sysbus_get_default();
-    }
-
-    /* create device, set properties */
-    qdev = DEVICE(object_new(driver));
-    qdev_set_parent_bus(qdev, bus);
-
-    id = qemu_opts_id(opts);
-    if (id) {
-        qdev->id = id;
-    }
-    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
-        qdev_free(qdev);
-        return NULL;
-    }
-    if (qdev->id) {
-        object_property_add_child(qdev_get_peripheral(), qdev->id,
-                                  OBJECT(qdev), NULL);
-    } else {
-        static int anon_count;
-        gchar *name = g_strdup_printf("device[%d]", anon_count++);
-        object_property_add_child(qdev_get_peripheral_anon(), name,
-                                  OBJECT(qdev), NULL);
-        g_free(name);
-    }        
-    if (qdev_init(qdev) < 0) {
-        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
-        return NULL;
-    }
-    qdev->opts = opts;
-    return qdev;
-}
-
-
-#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
-static void qbus_print(Monitor *mon, BusState *bus, int indent);
-
-static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
-                             int indent)
-{
-    if (!props)
-        return;
-    for (; props->name; props++) {
-        Error *err = NULL;
-        char *value;
-        char *legacy_name = g_strdup_printf("legacy-%s", props->name);
-        if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
-            value = object_property_get_str(OBJECT(dev), legacy_name, &err);
-        } else {
-            value = object_property_print(OBJECT(dev), props->name, &err);
-        }
-        g_free(legacy_name);
-
-        if (err) {
-            error_free(err);
-            continue;
-        }
-        qdev_printf("%s = %s\n", props->name,
-                    value && *value ? value : "<null>");
-        g_free(value);
-    }
-}
-
-static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int indent)
-{
-    BusClass *bc = BUS_GET_CLASS(bus);
-
-    if (bc->print_dev) {
-        bc->print_dev(mon, dev, indent);
-    }
-}
-
-static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
-{
-    ObjectClass *class;
-    BusState *child;
-    qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
-                dev->id ? dev->id : "");
-    indent += 2;
-    if (dev->num_gpio_in) {
-        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
-    }
-    if (dev->num_gpio_out) {
-        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
-    }
-    class = object_get_class(OBJECT(dev));
-    do {
-        qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
-        class = object_class_get_parent(class);
-    } while (class != object_class_by_name(TYPE_DEVICE));
-    bus_print_dev(dev->parent_bus, mon, dev, indent);
-    QLIST_FOREACH(child, &dev->child_bus, sibling) {
-        qbus_print(mon, child, indent);
-    }
-}
-
-static void qbus_print(Monitor *mon, BusState *bus, int indent)
-{
-    BusChild *kid;
-
-    qdev_printf("bus: %s\n", bus->name);
-    indent += 2;
-    qdev_printf("type %s\n", object_get_typename(OBJECT(bus)));
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        qdev_print(mon, dev, indent);
-    }
-}
-#undef qdev_printf
-
-void do_info_qtree(Monitor *mon, const QDict *qdict)
-{
-    if (sysbus_get_default())
-        qbus_print(mon, sysbus_get_default(), 0);
-}
-
-void do_info_qdm(Monitor *mon, const QDict *qdict)
-{
-    object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
-}
-
-int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    Error *local_err = NULL;
-    QemuOpts *opts;
-    DeviceState *dev;
-
-    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
-    if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-        return -1;
-    }
-    if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
-        qemu_opts_del(opts);
-        return 0;
-    }
-    dev = qdev_device_add(opts);
-    if (!dev) {
-        qemu_opts_del(opts);
-        return -1;
-    }
-    object_unref(OBJECT(dev));
-    return 0;
-}
-
-void qmp_device_del(const char *id, Error **errp)
-{
-    DeviceState *dev;
-
-    dev = qdev_find_recursive(sysbus_get_default(), id);
-    if (NULL == dev) {
-        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
-        return;
-    }
-
-    qdev_unplug(dev, errp);
-}
-
-void qdev_machine_init(void)
-{
-    qdev_get_peripheral_anon();
-    qdev_get_peripheral();
-}
-
-QemuOptsList qemu_device_opts = {
-    .name = "device",
-    .implied_opt_name = "driver",
-    .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
-    .desc = {
-        /*
-         * no elements => accept any
-         * sanity checking will happen later
-         * when setting device properties
-         */
-        { /* end of list */ }
-    },
-};
-
-QemuOptsList qemu_global_opts = {
-    .name = "global",
-    .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
-    .desc = {
-        {
-            .name = "driver",
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "property",
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "value",
-            .type = QEMU_OPT_STRING,
-        },
-        { /* end of list */ }
-    },
-};
-
-int qemu_global_option(const char *str)
-{
-    char driver[64], property[64];
-    QemuOpts *opts;
-    int rc, offset;
-
-    rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
-    if (rc < 2 || str[offset] != '=') {
-        error_report("can't parse: \"%s\"", str);
-        return -1;
-    }
-
-    opts = qemu_opts_create_nofail(&qemu_global_opts);
-    qemu_opt_set(opts, "driver", driver);
-    qemu_opt_set(opts, "property", property);
-    qemu_opt_set(opts, "value", str+offset+1);
-    return 0;
-}
diff --git a/hw/qdev-monitor.h b/hw/qdev-monitor.h
deleted file mode 100644 (file)
index 9ec4850..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef QEMU_QDEV_MONITOR_H
-#define QEMU_QDEV_MONITOR_H
-
-#include "qdev-core.h"
-#include "monitor/monitor.h"
-
-/*** monitor commands ***/
-
-void do_info_qtree(Monitor *mon, const QDict *qdict);
-void do_info_qdm(Monitor *mon, const QDict *qdict);
-int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int qdev_device_help(QemuOpts *opts);
-DeviceState *qdev_device_add(QemuOpts *opts);
-
-#endif
index ce3af2219366810140bfe9d81cee1f5a99f18714..87951444a1c53c50bb6cb3acb34572c45c4b4f54 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #include "net/net.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "qapi/qmp/qerror.h"
 #include "sysemu/blockdev.h"
 #include "hw/block-common.h"
index a8a31f56e429b4fb9368a3b96fa6a7c65c3a25a5..0307a7830b029a85b8da323dcb3b0051e471a9a5 100644 (file)
@@ -1,5 +1,5 @@
 #include "net/net.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "qapi/qmp/qerror.h"
 #include "sysemu/blockdev.h"
 #include "hw/block-common.h"
index 20c67f344353d345f591815161b22ec0576fca94..0b0465c9b34e56243f9ad8e9db81e63e56a63b63 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef QEMU_QDEV_PROPERTIES_H
 #define QEMU_QDEV_PROPERTIES_H
 
-#include "qdev-core.h"
+#include "hw/qdev-core.h"
 
 /*** qdev-properties.c ***/
 
index 689cd543e9d4477fb6c219cc5b4cde9d7281e51d..0b20280133ce28ea60edc5407f5b7d4acda12095 100644 (file)
--- a/hw/qdev.c
+++ b/hw/qdev.c
    inherit from a particular bus (e.g. PCI or I2C) rather than
    this API directly.  */
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "sysemu/sysemu.h"
 #include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
 #include "qapi/visitor.h"
 
 int qdev_hotplug = 0;
index 365b8d6ca2a443f435a36ec4999fbfcecfd301da..5cb8b080a623202d9fdddc02a0f9443c5aeb5b19 100644 (file)
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -2,8 +2,7 @@
 #define QDEV_H
 
 #include "hw/hw.h"
-#include "qdev-core.h"
-#include "qdev-properties.h"
-#include "qdev-monitor.h"
+#include "hw/qdev-core.h"
+#include "hw/qdev-properties.h"
 
 #endif
index 3cd85d9b9786fcfa0d6a1e1763848c4b353a890e..84f9aa1eda63773bd3b3952d9428c9b401b0d083 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #include "qemu/timer.h"
-#include "qxl.h"
+#include "hw/qxl.h"
 
 static const char *qxl_type[] = {
     [ QXL_CMD_NOP ]     = "nop",
index 455fb91269b0d95151320523e095e413d2c6045d..d77df42b7ee9e5de61b011eee92ad6a248706559 100644 (file)
@@ -19,7 +19,7 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "qxl.h"
+#include "hw/qxl.h"
 
 static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
 {
index 2e1c5e225b6f75018799ae03c38bee5156098ec5..ef693486c296be831c3fe59eb89dcedab3bc3b46 100644 (file)
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -27,7 +27,7 @@
 #include "sysemu/sysemu.h"
 #include "trace.h"
 
-#include "qxl.h"
+#include "hw/qxl.h"
 
 /*
  * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as
index f867a1d0ac699e3ff179111fbf6dfac90ffb6a78..36f1a2502bf115618f34fc0ce00f973ec67e256c 100644 (file)
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -4,9 +4,9 @@
 #include "qemu-common.h"
 
 #include "ui/console.h"
-#include "hw.h"
-#include "pci/pci.h"
-#include "vga_int.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/vga_int.h"
 #include "qemu/thread.h"
 
 #include "ui/qemu-spice.h"
diff --git a/hw/r2d.c b/hw/r2d.c
deleted file mode 100644 (file)
index 2d0dd1f..0000000
--- a/hw/r2d.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Renesas SH7751R R2D-PLUS emulation
- *
- * Copyright (c) 2007 Magnus Damm
- * Copyright (c) 2008 Paul Mundt
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "hw.h"
-#include "sh.h"
-#include "devices.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "pci/pci.h"
-#include "net/net.h"
-#include "sh7750_regs.h"
-#include "ide.h"
-#include "loader.h"
-#include "usb.h"
-#include "flash.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define FLASH_BASE 0x00000000
-#define FLASH_SIZE 0x02000000
-
-#define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
-#define SDRAM_SIZE 0x04000000
-
-#define SM501_VRAM_SIZE 0x800000
-
-#define BOOT_PARAMS_OFFSET 0x0010000
-/* CONFIG_BOOT_LINK_OFFSET of Linux kernel */
-#define LINUX_LOAD_OFFSET  0x0800000
-#define INITRD_LOAD_OFFSET 0x1800000
-
-#define PA_IRLMSK      0x00
-#define PA_POWOFF      0x30
-#define PA_VERREG      0x32
-#define PA_OUTPORT     0x36
-
-typedef struct {
-    uint16_t bcr;
-    uint16_t irlmsk;
-    uint16_t irlmon;
-    uint16_t cfctl;
-    uint16_t cfpow;
-    uint16_t dispctl;
-    uint16_t sdmpow;
-    uint16_t rtcce;
-    uint16_t pcicd;
-    uint16_t voyagerrts;
-    uint16_t cfrst;
-    uint16_t admrts;
-    uint16_t extrst;
-    uint16_t cfcdintclr;
-    uint16_t keyctlclr;
-    uint16_t pad0;
-    uint16_t pad1;
-    uint16_t verreg;
-    uint16_t inport;
-    uint16_t outport;
-    uint16_t bverreg;
-
-/* output pin */
-    qemu_irq irl;
-    MemoryRegion iomem;
-} r2d_fpga_t;
-
-enum r2d_fpga_irq {
-    PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T,
-    SDCARD, PCI_INTA, PCI_INTB, EXT, TP,
-    NR_IRQS
-};
-
-static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = {
-    [CF_IDE]   = {  1, 1<<9 },
-    [CF_CD]    = {  2, 1<<8 },
-    [PCI_INTA] = {  9, 1<<14 },
-    [PCI_INTB] = { 10, 1<<13 },
-    [PCI_INTC] = {  3, 1<<12 },
-    [PCI_INTD] = {  0, 1<<11 },
-    [SM501]    = {  4, 1<<10 },
-    [KEY]      = {  5, 1<<6 },
-    [RTC_A]    = {  6, 1<<5 },
-    [RTC_T]    = {  7, 1<<4 },
-    [SDCARD]   = {  8, 1<<7 },
-    [EXT]      = { 11, 1<<0 },
-    [TP]       = { 12, 1<<15 },
-};
-
-static void update_irl(r2d_fpga_t *fpga)
-{
-    int i, irl = 15;
-    for (i = 0; i < NR_IRQS; i++)
-        if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk)
-            if (irqtab[i].irl < irl)
-                irl = irqtab[i].irl;
-    qemu_set_irq(fpga->irl, irl ^ 15);
-}
-
-static void r2d_fpga_irq_set(void *opaque, int n, int level)
-{
-    r2d_fpga_t *fpga = opaque;
-    if (level)
-        fpga->irlmon |= irqtab[n].msk;
-    else
-        fpga->irlmon &= ~irqtab[n].msk;
-    update_irl(fpga);
-}
-
-static uint32_t r2d_fpga_read(void *opaque, hwaddr addr)
-{
-    r2d_fpga_t *s = opaque;
-
-    switch (addr) {
-    case PA_IRLMSK:
-        return s->irlmsk;
-    case PA_OUTPORT:
-       return s->outport;
-    case PA_POWOFF:
-       return 0x00;
-    case PA_VERREG:
-       return 0x10;
-    }
-
-    return 0;
-}
-
-static void
-r2d_fpga_write(void *opaque, hwaddr addr, uint32_t value)
-{
-    r2d_fpga_t *s = opaque;
-
-    switch (addr) {
-    case PA_IRLMSK:
-        s->irlmsk = value;
-        update_irl(s);
-       break;
-    case PA_OUTPORT:
-       s->outport = value;
-       break;
-    case PA_POWOFF:
-        if (value & 1) {
-            qemu_system_shutdown_request();
-        }
-        break;
-    case PA_VERREG:
-       /* Discard writes */
-       break;
-    }
-}
-
-static const MemoryRegionOps r2d_fpga_ops = {
-    .old_mmio = {
-        .read = { r2d_fpga_read, r2d_fpga_read, NULL, },
-        .write = { r2d_fpga_write, r2d_fpga_write, NULL, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static qemu_irq *r2d_fpga_init(MemoryRegion *sysmem,
-                               hwaddr base, qemu_irq irl)
-{
-    r2d_fpga_t *s;
-
-    s = g_malloc0(sizeof(r2d_fpga_t));
-
-    s->irl = irl;
-
-    memory_region_init_io(&s->iomem, &r2d_fpga_ops, s, "r2d-fpga", 0x40);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-    return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
-}
-
-typedef struct ResetData {
-    SuperHCPU *cpu;
-    uint32_t vector;
-} ResetData;
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetData *s = (ResetData *)opaque;
-    CPUSH4State *env = &s->cpu->env;
-
-    cpu_reset(CPU(s->cpu));
-    env->pc = s->vector;
-}
-
-static struct QEMU_PACKED
-{
-    int mount_root_rdonly;
-    int ramdisk_flags;
-    int orig_root_dev;
-    int loader_type;
-    int initrd_start;
-    int initrd_size;
-
-    char pad[232];
-
-    char kernel_cmdline[256];
-} boot_params;
-
-static void r2d_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    SuperHCPU *cpu;
-    CPUSH4State *env;
-    ResetData *reset_info;
-    struct SH7750State *s;
-    MemoryRegion *sdram = g_new(MemoryRegion, 1);
-    qemu_irq *irq;
-    DriveInfo *dinfo;
-    int i;
-    DeviceState *dev;
-    SysBusDevice *busdev;
-    MemoryRegion *address_space_mem = get_system_memory();
-
-    if (cpu_model == NULL) {
-        cpu_model = "SH7751R";
-    }
-
-    cpu = cpu_sh4_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->cpu = cpu;
-    reset_info->vector = env->pc;
-    qemu_register_reset(main_cpu_reset, reset_info);
-
-    /* Allocate memory space */
-    memory_region_init_ram(sdram, "r2d.sdram", SDRAM_SIZE);
-    vmstate_register_ram_global(sdram);
-    memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);
-    /* Register peripherals */
-    s = sh7750_init(env, address_space_mem);
-    irq = r2d_fpga_init(address_space_mem, 0x04000000, sh7750_irl(s));
-
-    dev = qdev_create(NULL, "sh_pci");
-    busdev = SYS_BUS_DEVICE(dev);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(busdev, 0, P4ADDR(0x1e200000));
-    sysbus_mmio_map(busdev, 1, A7ADDR(0x1e200000));
-    sysbus_connect_irq(busdev, 0, irq[PCI_INTA]);
-    sysbus_connect_irq(busdev, 1, irq[PCI_INTB]);
-    sysbus_connect_irq(busdev, 2, irq[PCI_INTC]);
-    sysbus_connect_irq(busdev, 3, irq[PCI_INTD]);
-
-    sm501_init(address_space_mem, 0x10000000, SM501_VRAM_SIZE,
-               irq[SM501], serial_hds[2]);
-
-    /* onboard CF (True IDE mode, Master only). */
-    dinfo = drive_get(IF_IDE, 0, 0);
-    dev = qdev_create(NULL, "mmio-ide");
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(busdev, 0, irq[CF_IDE]);
-    qdev_prop_set_uint32(dev, "shift", 1);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(busdev, 0, 0x14001000);
-    sysbus_mmio_map(busdev, 1, 0x1400080c);
-    mmio_ide_init_drives(dev, dinfo, NULL);
-
-    /* onboard flash memory */
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, (16 * 1024),
-                          FLASH_SIZE >> 16,
-                          1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
-                          0x555, 0x2aa, 0);
-
-    /* NIC: rtl8139 on-board, and 2 slots. */
-    for (i = 0; i < nb_nics; i++)
-        pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL);
-
-    /* USB keyboard */
-    usbdevice_create("keyboard");
-
-    /* Todo: register on board registers */
-    memset(&boot_params, 0, sizeof(boot_params));
-
-    if (kernel_filename) {
-        int kernel_size;
-
-        kernel_size = load_image_targphys(kernel_filename,
-                                          SDRAM_BASE + LINUX_LOAD_OFFSET,
-                                          INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET);
-        if (kernel_size < 0) {
-          fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
-          exit(1);
-        }
-
-        /* initialization which should be done by firmware */
-        stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
-        stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
-        reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
-    }
-
-    if (initrd_filename) {
-        int initrd_size;
-
-        initrd_size = load_image_targphys(initrd_filename,
-                                          SDRAM_BASE + INITRD_LOAD_OFFSET,
-                                          SDRAM_SIZE - INITRD_LOAD_OFFSET);
-
-        if (initrd_size < 0) {
-          fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename);
-          exit(1);
-        }
-
-        /* initialization which should be done by firmware */
-        boot_params.loader_type = 1;
-        boot_params.initrd_start = INITRD_LOAD_OFFSET;
-        boot_params.initrd_size = initrd_size;
-    }
-
-    if (kernel_cmdline) {
-        /* I see no evidence that this .kernel_cmdline buffer requires
-           NUL-termination, so using strncpy should be ok. */
-        strncpy(boot_params.kernel_cmdline, kernel_cmdline,
-                sizeof(boot_params.kernel_cmdline));
-    }
-
-    rom_add_blob_fixed("boot_params", &boot_params, sizeof(boot_params),
-                       SDRAM_BASE + BOOT_PARAMS_OFFSET);
-}
-
-static QEMUMachine r2d_machine = {
-    .name = "r2d",
-    .desc = "r2d-plus board",
-    .init = r2d_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void r2d_machine_init(void)
-{
-    qemu_register_machine(&r2d_machine);
-}
-
-machine_init(r2d_machine_init);
index a0358a319c9936e854cd267287e01dcc62335876..b065515e672a1cf59d94e548511e47b59aa571d5 100644 (file)
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "mips.h"
+#include "hw/hw.h"
+#include "hw/mips.h"
 #include "qemu/timer.h"
 
 /********************************************************/
diff --git a/hw/realview.c b/hw/realview.c
deleted file mode 100644 (file)
index 78da767..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * ARM RealView Baseboard System emulation.
- *
- * Copyright (c) 2006-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "primecell.h"
-#include "devices.h"
-#include "pci/pci.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "i2c.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define SMP_BOOT_ADDR 0xe0000000
-#define SMP_BOOTREG_ADDR 0x10000030
-
-/* Board init.  */
-
-static struct arm_boot_info realview_binfo = {
-    .smp_loader_start = SMP_BOOT_ADDR,
-    .smp_bootreg_addr = SMP_BOOTREG_ADDR,
-};
-
-/* The following two lists must be consistent.  */
-enum realview_board_type {
-    BOARD_EB,
-    BOARD_EB_MPCORE,
-    BOARD_PB_A8,
-    BOARD_PBX_A9,
-};
-
-static const int realview_board_id[] = {
-    0x33b,
-    0x33b,
-    0x769,
-    0x76d
-};
-
-static void realview_init(QEMUMachineInitArgs *args,
-                          enum realview_board_type board_type)
-{
-    ARMCPU *cpu = NULL;
-    CPUARMState *env;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
-    MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
-    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
-    MemoryRegion *ram_hack = g_new(MemoryRegion, 1);
-    DeviceState *dev, *sysctl, *gpio2, *pl041;
-    SysBusDevice *busdev;
-    qemu_irq *irqp;
-    qemu_irq pic[64];
-    qemu_irq mmc_irq[2];
-    PCIBus *pci_bus;
-    NICInfo *nd;
-    i2c_bus *i2c;
-    int n;
-    int done_nic = 0;
-    qemu_irq cpu_irq[4];
-    int is_mpcore = 0;
-    int is_pb = 0;
-    uint32_t proc_id = 0;
-    uint32_t sys_id;
-    ram_addr_t low_ram_size;
-    ram_addr_t ram_size = args->ram_size;
-
-    switch (board_type) {
-    case BOARD_EB:
-        break;
-    case BOARD_EB_MPCORE:
-        is_mpcore = 1;
-        break;
-    case BOARD_PB_A8:
-        is_pb = 1;
-        break;
-    case BOARD_PBX_A9:
-        is_mpcore = 1;
-        is_pb = 1;
-        break;
-    }
-    for (n = 0; n < smp_cpus; n++) {
-        cpu = cpu_arm_init(args->cpu_model);
-        if (!cpu) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        irqp = arm_pic_init_cpu(cpu);
-        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
-    }
-    env = &cpu->env;
-    if (arm_feature(env, ARM_FEATURE_V7)) {
-        if (is_mpcore) {
-            proc_id = 0x0c000000;
-        } else {
-            proc_id = 0x0e000000;
-        }
-    } else if (arm_feature(env, ARM_FEATURE_V6K)) {
-        proc_id = 0x06000000;
-    } else if (arm_feature(env, ARM_FEATURE_V6)) {
-        proc_id = 0x04000000;
-    } else {
-        proc_id = 0x02000000;
-    }
-
-    if (is_pb && ram_size > 0x20000000) {
-        /* Core tile RAM.  */
-        low_ram_size = ram_size - 0x20000000;
-        ram_size = 0x20000000;
-        memory_region_init_ram(ram_lo, "realview.lowmem", low_ram_size);
-        vmstate_register_ram_global(ram_lo);
-        memory_region_add_subregion(sysmem, 0x20000000, ram_lo);
-    }
-
-    memory_region_init_ram(ram_hi, "realview.highmem", ram_size);
-    vmstate_register_ram_global(ram_hi);
-    low_ram_size = ram_size;
-    if (low_ram_size > 0x10000000)
-      low_ram_size = 0x10000000;
-    /* SDRAM at address zero.  */
-    memory_region_init_alias(ram_alias, "realview.alias",
-                             ram_hi, 0, low_ram_size);
-    memory_region_add_subregion(sysmem, 0, ram_alias);
-    if (is_pb) {
-        /* And again at a high address.  */
-        memory_region_add_subregion(sysmem, 0x70000000, ram_hi);
-    } else {
-        ram_size = low_ram_size;
-    }
-
-    sys_id = is_pb ? 0x01780500 : 0xc1400400;
-    sysctl = qdev_create(NULL, "realview_sysctl");
-    qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
-    qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
-    qdev_init_nofail(sysctl);
-    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
-
-    if (is_mpcore) {
-        hwaddr periphbase;
-        dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
-        qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
-        qdev_init_nofail(dev);
-        busdev = SYS_BUS_DEVICE(dev);
-        if (is_pb) {
-            periphbase = 0x1f000000;
-        } else {
-            periphbase = 0x10100000;
-        }
-        sysbus_mmio_map(busdev, 0, periphbase);
-        for (n = 0; n < smp_cpus; n++) {
-            sysbus_connect_irq(busdev, n, cpu_irq[n]);
-        }
-        sysbus_create_varargs("l2x0", periphbase + 0x2000, NULL);
-        /* Both A9 and 11MPCore put the GIC CPU i/f at base + 0x100 */
-        realview_binfo.gic_cpu_if_addr = periphbase + 0x100;
-    } else {
-        uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000;
-        /* For now just create the nIRQ GIC, and ignore the others.  */
-        dev = sysbus_create_simple("realview_gic", gic_addr, cpu_irq[0]);
-    }
-    for (n = 0; n < 64; n++) {
-        pic[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    pl041 = qdev_create(NULL, "pl041");
-    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
-    qdev_init_nofail(pl041);
-    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
-    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[19]);
-
-    sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]);
-    sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]);
-
-    sysbus_create_simple("pl011", 0x10009000, pic[12]);
-    sysbus_create_simple("pl011", 0x1000a000, pic[13]);
-    sysbus_create_simple("pl011", 0x1000b000, pic[14]);
-    sysbus_create_simple("pl011", 0x1000c000, pic[15]);
-
-    /* DMA controller is optional, apparently.  */
-    sysbus_create_simple("pl081", 0x10030000, pic[24]);
-
-    sysbus_create_simple("sp804", 0x10011000, pic[4]);
-    sysbus_create_simple("sp804", 0x10012000, pic[5]);
-
-    sysbus_create_simple("pl061", 0x10013000, pic[6]);
-    sysbus_create_simple("pl061", 0x10014000, pic[7]);
-    gpio2 = sysbus_create_simple("pl061", 0x10015000, pic[8]);
-
-    sysbus_create_simple("pl111", 0x10020000, pic[23]);
-
-    dev = sysbus_create_varargs("pl181", 0x10005000, pic[17], pic[18], NULL);
-    /* Wire up MMC card detect and read-only signals. These have
-     * to go to both the PL061 GPIO and the sysctl register.
-     * Note that the PL181 orders these lines (readonly,inserted)
-     * and the PL061 has them the other way about. Also the card
-     * detect line is inverted.
-     */
-    mmc_irq[0] = qemu_irq_split(
-        qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
-        qdev_get_gpio_in(gpio2, 1));
-    mmc_irq[1] = qemu_irq_split(
-        qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
-        qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
-    qdev_connect_gpio_out(dev, 0, mmc_irq[0]);
-    qdev_connect_gpio_out(dev, 1, mmc_irq[1]);
-
-    sysbus_create_simple("pl031", 0x10017000, pic[10]);
-
-    if (!is_pb) {
-        dev = qdev_create(NULL, "realview_pci");
-        busdev = SYS_BUS_DEVICE(dev);
-        qdev_init_nofail(dev);
-        sysbus_mmio_map(busdev, 0, 0x61000000); /* PCI self-config */
-        sysbus_mmio_map(busdev, 1, 0x62000000); /* PCI config */
-        sysbus_mmio_map(busdev, 2, 0x63000000); /* PCI I/O */
-        sysbus_connect_irq(busdev, 0, pic[48]);
-        sysbus_connect_irq(busdev, 1, pic[49]);
-        sysbus_connect_irq(busdev, 2, pic[50]);
-        sysbus_connect_irq(busdev, 3, pic[51]);
-        pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
-        if (usb_enabled(false)) {
-            pci_create_simple(pci_bus, -1, "pci-ohci");
-        }
-        n = drive_get_max_bus(IF_SCSI);
-        while (n >= 0) {
-            pci_create_simple(pci_bus, -1, "lsi53c895a");
-            n--;
-        }
-    }
-    for(n = 0; n < nb_nics; n++) {
-        nd = &nd_table[n];
-
-        if (!done_nic && (!nd->model ||
-                    strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0)) {
-            if (is_pb) {
-                lan9118_init(nd, 0x4e000000, pic[28]);
-            } else {
-                smc91c111_init(nd, 0x4e000000, pic[28]);
-            }
-            done_nic = 1;
-        } else {
-            pci_nic_init_nofail(nd, "rtl8139", NULL);
-        }
-    }
-
-    dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
-    i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
-    i2c_create_slave(i2c, "ds1338", 0x68);
-
-    /* Memory map for RealView Emulation Baseboard:  */
-    /* 0x10000000 System registers.  */
-    /*  0x10001000 System controller.  */
-    /* 0x10002000 Two-Wire Serial Bus.  */
-    /* 0x10003000 Reserved.  */
-    /*  0x10004000 AACI.  */
-    /*  0x10005000 MCI.  */
-    /* 0x10006000 KMI0.  */
-    /* 0x10007000 KMI1.  */
-    /*  0x10008000 Character LCD. (EB) */
-    /* 0x10009000 UART0.  */
-    /* 0x1000a000 UART1.  */
-    /* 0x1000b000 UART2.  */
-    /* 0x1000c000 UART3.  */
-    /*  0x1000d000 SSPI.  */
-    /*  0x1000e000 SCI.  */
-    /* 0x1000f000 Reserved.  */
-    /*  0x10010000 Watchdog.  */
-    /* 0x10011000 Timer 0+1.  */
-    /* 0x10012000 Timer 2+3.  */
-    /*  0x10013000 GPIO 0.  */
-    /*  0x10014000 GPIO 1.  */
-    /*  0x10015000 GPIO 2.  */
-    /*  0x10002000 Two-Wire Serial Bus - DVI. (PB) */
-    /* 0x10017000 RTC.  */
-    /*  0x10018000 DMC.  */
-    /*  0x10019000 PCI controller config.  */
-    /*  0x10020000 CLCD.  */
-    /* 0x10030000 DMA Controller.  */
-    /* 0x10040000 GIC1. (EB) */
-    /*  0x10050000 GIC2. (EB) */
-    /*  0x10060000 GIC3. (EB) */
-    /*  0x10070000 GIC4. (EB) */
-    /*  0x10080000 SMC.  */
-    /* 0x1e000000 GIC1. (PB) */
-    /*  0x1e001000 GIC2. (PB) */
-    /*  0x1e002000 GIC3. (PB) */
-    /*  0x1e003000 GIC4. (PB) */
-    /*  0x40000000 NOR flash.  */
-    /*  0x44000000 DoC flash.  */
-    /*  0x48000000 SRAM.  */
-    /*  0x4c000000 Configuration flash.  */
-    /* 0x4e000000 Ethernet.  */
-    /*  0x4f000000 USB.  */
-    /*  0x50000000 PISMO.  */
-    /*  0x54000000 PISMO.  */
-    /*  0x58000000 PISMO.  */
-    /*  0x5c000000 PISMO.  */
-    /* 0x60000000 PCI.  */
-    /* 0x61000000 PCI Self Config.  */
-    /* 0x62000000 PCI Config.  */
-    /* 0x63000000 PCI IO.  */
-    /* 0x64000000 PCI mem 0.  */
-    /* 0x68000000 PCI mem 1.  */
-    /* 0x6c000000 PCI mem 2.  */
-
-    /* ??? Hack to map an additional page of ram for the secondary CPU
-       startup code.  I guess this works on real hardware because the
-       BootROM happens to be in ROM/flash or in memory that isn't clobbered
-       until after Linux boots the secondary CPUs.  */
-    memory_region_init_ram(ram_hack, "realview.hack", 0x1000);
-    vmstate_register_ram_global(ram_hack);
-    memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
-
-    realview_binfo.ram_size = ram_size;
-    realview_binfo.kernel_filename = args->kernel_filename;
-    realview_binfo.kernel_cmdline = args->kernel_cmdline;
-    realview_binfo.initrd_filename = args->initrd_filename;
-    realview_binfo.nb_cpus = smp_cpus;
-    realview_binfo.board_id = realview_board_id[board_type];
-    realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo);
-}
-
-static void realview_eb_init(QEMUMachineInitArgs *args)
-{
-    if (!args->cpu_model) {
-        args->cpu_model = "arm926";
-    }
-    realview_init(args, BOARD_EB);
-}
-
-static void realview_eb_mpcore_init(QEMUMachineInitArgs *args)
-{
-    if (!args->cpu_model) {
-        args->cpu_model = "arm11mpcore";
-    }
-    realview_init(args, BOARD_EB_MPCORE);
-}
-
-static void realview_pb_a8_init(QEMUMachineInitArgs *args)
-{
-    if (!args->cpu_model) {
-        args->cpu_model = "cortex-a8";
-    }
-    realview_init(args, BOARD_PB_A8);
-}
-
-static void realview_pbx_a9_init(QEMUMachineInitArgs *args)
-{
-    if (!args->cpu_model) {
-        args->cpu_model = "cortex-a9";
-    }
-    realview_init(args, BOARD_PBX_A9);
-}
-
-static QEMUMachine realview_eb_machine = {
-    .name = "realview-eb",
-    .desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)",
-    .init = realview_eb_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine realview_eb_mpcore_machine = {
-    .name = "realview-eb-mpcore",
-    .desc = "ARM RealView Emulation Baseboard (ARM11MPCore)",
-    .init = realview_eb_mpcore_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine realview_pb_a8_machine = {
-    .name = "realview-pb-a8",
-    .desc = "ARM RealView Platform Baseboard for Cortex-A8",
-    .init = realview_pb_a8_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine realview_pbx_a9_machine = {
-    .name = "realview-pbx-a9",
-    .desc = "ARM RealView Platform Baseboard Explore for Cortex-A9",
-    .init = realview_pbx_a9_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void realview_machine_init(void)
-{
-    qemu_register_machine(&realview_eb_machine);
-    qemu_register_machine(&realview_eb_mpcore_machine);
-    qemu_register_machine(&realview_pb_a8_machine);
-    qemu_register_machine(&realview_pbx_a9_machine);
-}
-
-machine_init(realview_machine_init);
index 8f2a7e2f3451d0f96538ab22e10b898284fc0ac1..0ec30caa069d1d26e9e28d03f4d4edbf9ddec87c 100644 (file)
@@ -7,7 +7,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 typedef struct {
     SysBusDevice busdev;
index d7716beb9e689a7dc787c947e330cc061afdd144..786b875c5891939851a0d11c0e5ffc075dc7f0f2 100644 (file)
 /* For crc32 */
 #include <zlib.h>
 
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "sysemu/dma.h"
 #include "qemu/timer.h"
 #include "net/net.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "sysemu/sysemu.h"
 #include "qemu/iov.h"
 
index 6b5699518958142d213d945248e2dcdcc4cb0e14..0faade0766160fb49cee00efb9b3efeef6b35f96 100644 (file)
@@ -18,8 +18,8 @@
 #include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
 
-#include "sclp.h"
-#include "event-facility.h"
+#include "hw/s390x/sclp.h"
+#include "hw/s390x/event-facility.h"
 
 typedef struct EventTypesBus {
     BusState qbus;
index 65492118200ce91bf278e41cf03816a0c0899200..d4364143ea72c5f5ae2110060971353250f36863 100644 (file)
@@ -12,7 +12,7 @@
 #include "hw/boards.h"
 #include "exec/address-spaces.h"
 #include "s390-virtio.h"
-#include "sclp.h"
+#include "hw/s390x/sclp.h"
 #include "ioinst.h"
 #include "css.h"
 #include "virtio-ccw.h"
index a9d3a6a91d2f22764342a51b2b5b405a3bb8cbaf..86d6ae0023661ec3dc2f1249454b5da78635de6c 100644 (file)
@@ -16,7 +16,7 @@
 #include "sysemu/kvm.h"
 #include "exec/memory.h"
 
-#include "sclp.h"
+#include "hw/s390x/sclp.h"
 
 static inline S390SCLPDevice *get_event_facility(void)
 {
index effe51110f38e4b20f5ccbb53a51569ad93f2711..5c881e5f3f940e584e85fd9cd8680984d3eb87c5 100644 (file)
 
 #include <hw/qdev.h>
 #include "qemu/thread.h"
+#include "qemu/error-report.h"
 
-#include "sclp.h"
-#include "event-facility.h"
+#include "hw/s390x/sclp.h"
+#include "hw/s390x/event-facility.h"
 #include "char/char.h"
 
 typedef struct ASCIIConsoleData {
index 2538498959efb0b26918ffed5fd543e02dfcf349..5fadc86d42935376e32f337b6be99ba92fb87f60 100644 (file)
@@ -13,8 +13,8 @@
  */
 #include <hw/qdev.h>
 #include "sysemu/sysemu.h"
-#include "sclp.h"
-#include "event-facility.h"
+#include "hw/s390x/sclp.h"
+#include "hw/s390x/event-facility.h"
 
 typedef struct SignalQuiesce {
     EventBufferHeader ebh;
index 52dfedf5f1bc5de30861501fe88f7636da7f8cf2..bd51cebfd8a8e4dd3b4d3d4457e61d7647c02543 100644 (file)
--- a/hw/sb16.c
+++ b/hw/sb16.c
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "isa.h"
-#include "qdev.h"
+#include "hw/isa.h"
+#include "hw/qdev.h"
 #include "qemu/timer.h"
 #include "qemu/host-utils.h"
 
index d58184a6aaa77d60313358955ffb13c365e3c803..8795749de87c157d90e8567e3d86e82c8198bda9 100644 (file)
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 //#define DEBUG_IRQ
 
index a97f1cdc1c74d7d6ce55dad659be1495eacd64be..08787c2a9bfb0d3be7bac322147e4b0db5754e4a 100644 (file)
@@ -1,8 +1,8 @@
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/error-report.h"
-#include "scsi.h"
-#include "scsi-defs.h"
-#include "qdev.h"
+#include "hw/scsi.h"
+#include "hw/scsi-defs.h"
+#include "hw/qdev.h"
 #include "sysemu/blockdev.h"
 #include "trace.h"
 #include "sysemu/dma.h"
@@ -1508,6 +1508,10 @@ void scsi_req_unref(SCSIRequest *req)
    will start the next chunk or complete the command.  */
 void scsi_req_continue(SCSIRequest *req)
 {
+    if (req->io_canceled) {
+        trace_scsi_req_continue_canceled(req->dev->id, req->lun, req->tag);
+        return;
+    }
     trace_scsi_req_continue(req->dev->id, req->lun, req->tag);
     if (req->cmd.mode == SCSI_XFER_TO_DEV) {
         req->ops->write_data(req);
index d41158693e023fa7e483649c00d8d6f613879de8..c5c7bf3dfa6dd06e0a4300a2b6839fe16cea6fd0 100644 (file)
@@ -30,8 +30,8 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
 
 #include "qemu-common.h"
 #include "qemu/error-report.h"
-#include "scsi.h"
-#include "scsi-defs.h"
+#include "hw/scsi.h"
+#include "hw/scsi-defs.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/blockdev.h"
 #include "hw/block-common.h"
@@ -178,6 +178,9 @@ static void scsi_aio_complete(void *opaque, int ret)
     assert(r->req.aiocb != NULL);
     r->req.aiocb = NULL;
     bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+    if (r->req.io_canceled) {
+        goto done;
+    }
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
@@ -223,6 +226,10 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
 
+    if (r->req.io_canceled) {
+        goto done;
+    }
+
     if (scsi_is_cmd_fua(&r->req.cmd)) {
         bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
         r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
@@ -230,6 +237,8 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
     }
 
     scsi_req_complete(&r->req, GOOD);
+
+done:
     if (!r->req.io_canceled) {
         scsi_req_unref(&r->req);
     }
@@ -243,6 +252,9 @@ static void scsi_dma_complete(void *opaque, int ret)
     assert(r->req.aiocb != NULL);
     r->req.aiocb = NULL;
     bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+    if (r->req.io_canceled) {
+        goto done;
+    }
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
@@ -274,6 +286,9 @@ static void scsi_read_complete(void * opaque, int ret)
     assert(r->req.aiocb != NULL);
     r->req.aiocb = NULL;
     bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+    if (r->req.io_canceled) {
+        goto done;
+    }
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
@@ -305,6 +320,9 @@ static void scsi_do_read(void *opaque, int ret)
         r->req.aiocb = NULL;
         bdrv_acct_done(s->qdev.conf.bs, &r->acct);
     }
+    if (r->req.io_canceled) {
+        goto done;
+    }
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
@@ -312,10 +330,6 @@ static void scsi_do_read(void *opaque, int ret)
         }
     }
 
-    if (r->req.io_canceled) {
-        return;
-    }
-
     /* The request is used as the AIO opaque value, so add a ref.  */
     scsi_req_ref(&r->req);
 
@@ -423,6 +437,9 @@ static void scsi_write_complete(void * opaque, int ret)
         r->req.aiocb = NULL;
         bdrv_acct_done(s->qdev.conf.bs, &r->acct);
     }
+    if (r->req.io_canceled) {
+        goto done;
+    }
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
@@ -1478,13 +1495,17 @@ static void scsi_unmap_complete(void *opaque, int ret)
     uint32_t nb_sectors;
 
     r->req.aiocb = NULL;
+    if (r->req.io_canceled) {
+        goto done;
+    }
+
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
             goto done;
         }
     }
 
-    if (data->count > 0 && !r->req.io_canceled) {
+    if (data->count > 0) {
         sector_num = ldq_be_p(&data->inbuf[0]);
         nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL;
         if (!check_lba_range(s, sector_num, nb_sectors)) {
@@ -1501,10 +1522,9 @@ static void scsi_unmap_complete(void *opaque, int ret)
         return;
     }
 
+    scsi_req_complete(&r->req, GOOD);
+
 done:
-    if (data->count == 0) {
-        scsi_req_complete(&r->req, GOOD);
-    }
     if (!r->req.io_canceled) {
         scsi_req_unref(&r->req);
     }
index 8175474a67c52e1ab0d595255a605824bdad82a5..4d04caccce3004132aa88bf5ecb694c5ceeb6960 100644 (file)
@@ -13,7 +13,7 @@
 
 #include "qemu-common.h"
 #include "qemu/error-report.h"
-#include "scsi.h"
+#include "hw/scsi.h"
 #include "sysemu/blockdev.h"
 
 #ifdef __linux__
@@ -35,7 +35,7 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
 #include <sys/stat.h>
 #include <unistd.h>
 #include <scsi/sg.h>
-#include "scsi-defs.h"
+#include "hw/scsi-defs.h"
 
 #define SCSI_SENSE_BUF_SIZE 96
 
index a5b5b2ec0d4ae43e3c1122bf62980c7390d45513..33e2e0bdf119dcfa56dbd9054a6d79d733ebed3d 100644 (file)
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_HW_SCSI_H
 #define QEMU_HW_SCSI_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "block/block.h"
 #include "hw/block-common.h"
 #include "sysemu/sysemu.h"
diff --git a/hw/sd.c b/hw/sd.c
index 428bd78e327fb4958deb06b87108fd7f290938be..a895123867c2d300c1330ee803c9f56f65c690cd 100644 (file)
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -29,9 +29,9 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "block/block.h"
-#include "sd.h"
+#include "hw/sd.h"
 #include "qemu/bitmap.h"
 
 //#define DEBUG_SD 1
index e535df96719b038013ec042ca28d85d6bf17ecce..93feada049d559daa7158ad868a2a7dfc29b3934 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/dma.h"
 #include "qemu/timer.h"
 #include "block/block_int.h"
 #include "qemu/bitops.h"
 
-#include "sdhci.h"
+#include "hw/sdhci.h"
 
 /* host controller debug messages */
 #ifndef SDHC_DEBUG
index 931d7406f0d82136224282e755581f2a7c1f3716..a560c3c93fc67b831a9bf21054ed3bff5a65e1be 100644 (file)
@@ -26,8 +26,8 @@
 #define SDHCI_H
 
 #include "qemu-common.h"
-#include "sysbus.h"
-#include "sd.h"
+#include "hw/sysbus.h"
+#include "hw/sd.h"
 
 /* R/W SDMA System Address register 0x0 */
 #define SDHC_SYSAD                     0x00
index 5a6f51f856ddbf888255c9955c5e3870afdd5adc..a630a7d506a7e6e05b10e2f18c12f9eb046029c4 100644 (file)
@@ -23,8 +23,8 @@
  * THE SOFTWARE.
  */
 
-#include "serial.h"
-#include "isa.h"
+#include "hw/serial.h"
+#include "hw/isa.h"
 
 typedef struct ISASerialState {
     ISADevice dev;
index 1c31353f6df5e8d1bf730bed86322590dcc30457..954657ba326e1569a6ff1de268c2fcafcdc5f77c 100644 (file)
@@ -25,8 +25,8 @@
 
 /* see docs/specs/pci-serial.txt */
 
-#include "serial.h"
-#include "pci/pci.h"
+#include "hw/serial.h"
+#include "hw/pci/pci.h"
 
 #define PCI_SERIAL_MAX_PORTS 4
 
index eb38f2231dec42ef51719d94ab381b80a2788e9c..48a5eb62b9a8f498d8c8ec206a6f6ddb6f28da9d 100644 (file)
@@ -23,7 +23,7 @@
  * THE SOFTWARE.
  */
 
-#include "serial.h"
+#include "hw/serial.h"
 #include "char/char.h"
 #include "qemu/timer.h"
 #include "exec/address-spaces.h"
index e57375d03c89bca76aa24811d4a85dbc322b2dd3..e884499607315f436e4e966ba4aad592977bbf01 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef HW_SERIAL_H
 #define HW_SERIAL_H 1
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/sysemu.h"
 #include "exec/memory.h"
 
index 29bc3e0246d64ff285aeadaecf17bb109af5cbce..4b1d4e536997ffd50b0ddd1982f7c3e9b2f36d7c 100644 (file)
--- a/hw/sga.c
+++ b/hw/sga.c
@@ -24,9 +24,9 @@
  * sgabios code originally available at code.google.com/p/sgabios
  *
  */
-#include "pci/pci.h"
-#include "pc.h"
-#include "loader.h"
+#include "hw/pci/pci.h"
+#include "hw/pc.h"
+#include "hw/loader.h"
 #include "sysemu/sysemu.h"
 
 #define SGABIOS_FILENAME "sgabios.bin"
diff --git a/hw/sh.h b/hw/sh.h
index 77bf8aad2c0dc925eb0ca6201487b16d47c9c7e8..6230954eac924e64bfc5782b4d181f541dd3cee8 100644 (file)
--- a/hw/sh.h
+++ b/hw/sh.h
@@ -2,7 +2,7 @@
 #define QEMU_SH_H
 /* Definitions for SH board emulation.  */
 
-#include "sh_intc.h"
+#include "hw/sh_intc.h"
 
 #define A7ADDR(x) ((x) & 0x1fffffff)
 #define P4ADDR(x) ((x) | 0xe0000000)
index 68c592179070394e8c53aebd32f599f2df311724..72b6a1fcb43f0947e43327e20ea4b685aeec77a6 100644 (file)
@@ -1,5 +1,9 @@
-obj-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
+obj-y = tc58128.o
 obj-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
 obj-y += ide/mmio.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += shix.o r2d.o
+
+obj-y += sh7750.o sh7750_regnames.o
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
new file mode 100644 (file)
index 0000000..faa03d2
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * Renesas SH7751R R2D-PLUS emulation
+ *
+ * Copyright (c) 2007 Magnus Damm
+ * Copyright (c) 2008 Paul Mundt
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "hw/devices.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/pci/pci.h"
+#include "net/net.h"
+#include "hw/sh7750_regs.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
+#include "hw/usb.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define FLASH_BASE 0x00000000
+#define FLASH_SIZE 0x02000000
+
+#define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
+#define SDRAM_SIZE 0x04000000
+
+#define SM501_VRAM_SIZE 0x800000
+
+#define BOOT_PARAMS_OFFSET 0x0010000
+/* CONFIG_BOOT_LINK_OFFSET of Linux kernel */
+#define LINUX_LOAD_OFFSET  0x0800000
+#define INITRD_LOAD_OFFSET 0x1800000
+
+#define PA_IRLMSK      0x00
+#define PA_POWOFF      0x30
+#define PA_VERREG      0x32
+#define PA_OUTPORT     0x36
+
+typedef struct {
+    uint16_t bcr;
+    uint16_t irlmsk;
+    uint16_t irlmon;
+    uint16_t cfctl;
+    uint16_t cfpow;
+    uint16_t dispctl;
+    uint16_t sdmpow;
+    uint16_t rtcce;
+    uint16_t pcicd;
+    uint16_t voyagerrts;
+    uint16_t cfrst;
+    uint16_t admrts;
+    uint16_t extrst;
+    uint16_t cfcdintclr;
+    uint16_t keyctlclr;
+    uint16_t pad0;
+    uint16_t pad1;
+    uint16_t verreg;
+    uint16_t inport;
+    uint16_t outport;
+    uint16_t bverreg;
+
+/* output pin */
+    qemu_irq irl;
+    MemoryRegion iomem;
+} r2d_fpga_t;
+
+enum r2d_fpga_irq {
+    PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T,
+    SDCARD, PCI_INTA, PCI_INTB, EXT, TP,
+    NR_IRQS
+};
+
+static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = {
+    [CF_IDE]   = {  1, 1<<9 },
+    [CF_CD]    = {  2, 1<<8 },
+    [PCI_INTA] = {  9, 1<<14 },
+    [PCI_INTB] = { 10, 1<<13 },
+    [PCI_INTC] = {  3, 1<<12 },
+    [PCI_INTD] = {  0, 1<<11 },
+    [SM501]    = {  4, 1<<10 },
+    [KEY]      = {  5, 1<<6 },
+    [RTC_A]    = {  6, 1<<5 },
+    [RTC_T]    = {  7, 1<<4 },
+    [SDCARD]   = {  8, 1<<7 },
+    [EXT]      = { 11, 1<<0 },
+    [TP]       = { 12, 1<<15 },
+};
+
+static void update_irl(r2d_fpga_t *fpga)
+{
+    int i, irl = 15;
+    for (i = 0; i < NR_IRQS; i++)
+        if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk)
+            if (irqtab[i].irl < irl)
+                irl = irqtab[i].irl;
+    qemu_set_irq(fpga->irl, irl ^ 15);
+}
+
+static void r2d_fpga_irq_set(void *opaque, int n, int level)
+{
+    r2d_fpga_t *fpga = opaque;
+    if (level)
+        fpga->irlmon |= irqtab[n].msk;
+    else
+        fpga->irlmon &= ~irqtab[n].msk;
+    update_irl(fpga);
+}
+
+static uint32_t r2d_fpga_read(void *opaque, hwaddr addr)
+{
+    r2d_fpga_t *s = opaque;
+
+    switch (addr) {
+    case PA_IRLMSK:
+        return s->irlmsk;
+    case PA_OUTPORT:
+       return s->outport;
+    case PA_POWOFF:
+       return 0x00;
+    case PA_VERREG:
+       return 0x10;
+    }
+
+    return 0;
+}
+
+static void
+r2d_fpga_write(void *opaque, hwaddr addr, uint32_t value)
+{
+    r2d_fpga_t *s = opaque;
+
+    switch (addr) {
+    case PA_IRLMSK:
+        s->irlmsk = value;
+        update_irl(s);
+       break;
+    case PA_OUTPORT:
+       s->outport = value;
+       break;
+    case PA_POWOFF:
+        if (value & 1) {
+            qemu_system_shutdown_request();
+        }
+        break;
+    case PA_VERREG:
+       /* Discard writes */
+       break;
+    }
+}
+
+static const MemoryRegionOps r2d_fpga_ops = {
+    .old_mmio = {
+        .read = { r2d_fpga_read, r2d_fpga_read, NULL, },
+        .write = { r2d_fpga_write, r2d_fpga_write, NULL, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static qemu_irq *r2d_fpga_init(MemoryRegion *sysmem,
+                               hwaddr base, qemu_irq irl)
+{
+    r2d_fpga_t *s;
+
+    s = g_malloc0(sizeof(r2d_fpga_t));
+
+    s->irl = irl;
+
+    memory_region_init_io(&s->iomem, &r2d_fpga_ops, s, "r2d-fpga", 0x40);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
+    return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
+}
+
+typedef struct ResetData {
+    SuperHCPU *cpu;
+    uint32_t vector;
+} ResetData;
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetData *s = (ResetData *)opaque;
+    CPUSH4State *env = &s->cpu->env;
+
+    cpu_reset(CPU(s->cpu));
+    env->pc = s->vector;
+}
+
+static struct QEMU_PACKED
+{
+    int mount_root_rdonly;
+    int ramdisk_flags;
+    int orig_root_dev;
+    int loader_type;
+    int initrd_start;
+    int initrd_size;
+
+    char pad[232];
+
+    char kernel_cmdline[256];
+} boot_params;
+
+static void r2d_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    SuperHCPU *cpu;
+    CPUSH4State *env;
+    ResetData *reset_info;
+    struct SH7750State *s;
+    MemoryRegion *sdram = g_new(MemoryRegion, 1);
+    qemu_irq *irq;
+    DriveInfo *dinfo;
+    int i;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    MemoryRegion *address_space_mem = get_system_memory();
+
+    if (cpu_model == NULL) {
+        cpu_model = "SH7751R";
+    }
+
+    cpu = cpu_sh4_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    reset_info = g_malloc0(sizeof(ResetData));
+    reset_info->cpu = cpu;
+    reset_info->vector = env->pc;
+    qemu_register_reset(main_cpu_reset, reset_info);
+
+    /* Allocate memory space */
+    memory_region_init_ram(sdram, "r2d.sdram", SDRAM_SIZE);
+    vmstate_register_ram_global(sdram);
+    memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);
+    /* Register peripherals */
+    s = sh7750_init(env, address_space_mem);
+    irq = r2d_fpga_init(address_space_mem, 0x04000000, sh7750_irl(s));
+
+    dev = qdev_create(NULL, "sh_pci");
+    busdev = SYS_BUS_DEVICE(dev);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(busdev, 0, P4ADDR(0x1e200000));
+    sysbus_mmio_map(busdev, 1, A7ADDR(0x1e200000));
+    sysbus_connect_irq(busdev, 0, irq[PCI_INTA]);
+    sysbus_connect_irq(busdev, 1, irq[PCI_INTB]);
+    sysbus_connect_irq(busdev, 2, irq[PCI_INTC]);
+    sysbus_connect_irq(busdev, 3, irq[PCI_INTD]);
+
+    sm501_init(address_space_mem, 0x10000000, SM501_VRAM_SIZE,
+               irq[SM501], serial_hds[2]);
+
+    /* onboard CF (True IDE mode, Master only). */
+    dinfo = drive_get(IF_IDE, 0, 0);
+    dev = qdev_create(NULL, "mmio-ide");
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(busdev, 0, irq[CF_IDE]);
+    qdev_prop_set_uint32(dev, "shift", 1);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(busdev, 0, 0x14001000);
+    sysbus_mmio_map(busdev, 1, 0x1400080c);
+    mmio_ide_init_drives(dev, dinfo, NULL);
+
+    /* onboard flash memory */
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, (16 * 1024),
+                          FLASH_SIZE >> 16,
+                          1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
+                          0x555, 0x2aa, 0);
+
+    /* NIC: rtl8139 on-board, and 2 slots. */
+    for (i = 0; i < nb_nics; i++)
+        pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL);
+
+    /* USB keyboard */
+    usbdevice_create("keyboard");
+
+    /* Todo: register on board registers */
+    memset(&boot_params, 0, sizeof(boot_params));
+
+    if (kernel_filename) {
+        int kernel_size;
+
+        kernel_size = load_image_targphys(kernel_filename,
+                                          SDRAM_BASE + LINUX_LOAD_OFFSET,
+                                          INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET);
+        if (kernel_size < 0) {
+          fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
+          exit(1);
+        }
+
+        /* initialization which should be done by firmware */
+        stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
+        stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
+        reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
+    }
+
+    if (initrd_filename) {
+        int initrd_size;
+
+        initrd_size = load_image_targphys(initrd_filename,
+                                          SDRAM_BASE + INITRD_LOAD_OFFSET,
+                                          SDRAM_SIZE - INITRD_LOAD_OFFSET);
+
+        if (initrd_size < 0) {
+          fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename);
+          exit(1);
+        }
+
+        /* initialization which should be done by firmware */
+        boot_params.loader_type = 1;
+        boot_params.initrd_start = INITRD_LOAD_OFFSET;
+        boot_params.initrd_size = initrd_size;
+    }
+
+    if (kernel_cmdline) {
+        /* I see no evidence that this .kernel_cmdline buffer requires
+           NUL-termination, so using strncpy should be ok. */
+        strncpy(boot_params.kernel_cmdline, kernel_cmdline,
+                sizeof(boot_params.kernel_cmdline));
+    }
+
+    rom_add_blob_fixed("boot_params", &boot_params, sizeof(boot_params),
+                       SDRAM_BASE + BOOT_PARAMS_OFFSET);
+}
+
+static QEMUMachine r2d_machine = {
+    .name = "r2d",
+    .desc = "r2d-plus board",
+    .init = r2d_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void r2d_machine_init(void)
+{
+    qemu_register_machine(&r2d_machine);
+}
+
+machine_init(r2d_machine_init);
diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c
new file mode 100644 (file)
index 0000000..6778c94
--- /dev/null
@@ -0,0 +1,838 @@
+/*
+ * SH7750 device
+ *
+ * Copyright (c) 2007 Magnus Damm
+ * Copyright (c) 2005 Samuel Tardieu
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <stdio.h>
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "sysemu/sysemu.h"
+#include "hw/sh7750_regs.h"
+#include "hw/sh7750_regnames.h"
+#include "hw/sh_intc.h"
+#include "cpu.h"
+#include "exec/address-spaces.h"
+
+#define NB_DEVICES 4
+
+typedef struct SH7750State {
+    MemoryRegion iomem;
+    MemoryRegion iomem_1f0;
+    MemoryRegion iomem_ff0;
+    MemoryRegion iomem_1f8;
+    MemoryRegion iomem_ff8;
+    MemoryRegion iomem_1fc;
+    MemoryRegion iomem_ffc;
+    MemoryRegion mmct_iomem;
+    /* CPU */
+    CPUSH4State *cpu;
+    /* Peripheral frequency in Hz */
+    uint32_t periph_freq;
+    /* SDRAM controller */
+    uint32_t bcr1;
+    uint16_t bcr2;
+    uint16_t bcr3;
+    uint32_t bcr4;
+    uint16_t rfcr;
+    /* PCMCIA controller */
+    uint16_t pcr;
+    /* IO ports */
+    uint16_t gpioic;
+    uint32_t pctra;
+    uint32_t pctrb;
+    uint16_t portdira;         /* Cached */
+    uint16_t portpullupa;      /* Cached */
+    uint16_t portdirb;         /* Cached */
+    uint16_t portpullupb;      /* Cached */
+    uint16_t pdtra;
+    uint16_t pdtrb;
+    uint16_t periph_pdtra;     /* Imposed by the peripherals */
+    uint16_t periph_portdira;  /* Direction seen from the peripherals */
+    uint16_t periph_pdtrb;     /* Imposed by the peripherals */
+    uint16_t periph_portdirb;  /* Direction seen from the peripherals */
+    sh7750_io_device *devices[NB_DEVICES];     /* External peripherals */
+
+    /* Cache */
+    uint32_t ccr;
+
+    struct intc_desc intc;
+} SH7750State;
+
+static inline int has_bcr3_and_bcr4(SH7750State * s)
+{
+       return (s->cpu->features & SH_FEATURE_BCR3_AND_BCR4);
+}
+/**********************************************************************
+ I/O ports
+**********************************************************************/
+
+int sh7750_register_io_device(SH7750State * s, sh7750_io_device * device)
+{
+    int i;
+
+    for (i = 0; i < NB_DEVICES; i++) {
+       if (s->devices[i] == NULL) {
+           s->devices[i] = device;
+           return 0;
+       }
+    }
+    return -1;
+}
+
+static uint16_t portdir(uint32_t v)
+{
+#define EVENPORTMASK(n) ((v & (1<<((n)<<1))) >> (n))
+    return
+       EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
+       EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
+       EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
+       EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
+       EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
+       EVENPORTMASK(0);
+}
+
+static uint16_t portpullup(uint32_t v)
+{
+#define ODDPORTMASK(n) ((v & (1<<(((n)<<1)+1))) >> (n))
+    return
+       ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
+       ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
+       ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
+       ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
+       ODDPORTMASK(1) | ODDPORTMASK(0);
+}
+
+static uint16_t porta_lines(SH7750State * s)
+{
+    return (s->portdira & s->pdtra) |  /* CPU */
+       (s->periph_portdira & s->periph_pdtra) |        /* Peripherals */
+       (~(s->portdira | s->periph_portdira) & s->portpullupa); /* Pullups */
+}
+
+static uint16_t portb_lines(SH7750State * s)
+{
+    return (s->portdirb & s->pdtrb) |  /* CPU */
+       (s->periph_portdirb & s->periph_pdtrb) |        /* Peripherals */
+       (~(s->portdirb | s->periph_portdirb) & s->portpullupb); /* Pullups */
+}
+
+static void gen_port_interrupts(SH7750State * s)
+{
+    /* XXXXX interrupts not generated */
+}
+
+static void porta_changed(SH7750State * s, uint16_t prev)
+{
+    uint16_t currenta, changes;
+    int i, r = 0;
+
+#if 0
+    fprintf(stderr, "porta changed from 0x%04x to 0x%04x\n",
+           prev, porta_lines(s));
+    fprintf(stderr, "pdtra=0x%04x, pctra=0x%08x\n", s->pdtra, s->pctra);
+#endif
+    currenta = porta_lines(s);
+    if (currenta == prev)
+       return;
+    changes = currenta ^ prev;
+
+    for (i = 0; i < NB_DEVICES; i++) {
+       if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
+           r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
+                                              &s->periph_pdtra,
+                                              &s->periph_portdira,
+                                              &s->periph_pdtrb,
+                                              &s->periph_portdirb);
+       }
+    }
+
+    if (r)
+       gen_port_interrupts(s);
+}
+
+static void portb_changed(SH7750State * s, uint16_t prev)
+{
+    uint16_t currentb, changes;
+    int i, r = 0;
+
+    currentb = portb_lines(s);
+    if (currentb == prev)
+       return;
+    changes = currentb ^ prev;
+
+    for (i = 0; i < NB_DEVICES; i++) {
+       if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
+           r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
+                                              &s->periph_pdtra,
+                                              &s->periph_portdira,
+                                              &s->periph_pdtrb,
+                                              &s->periph_portdirb);
+       }
+    }
+
+    if (r)
+       gen_port_interrupts(s);
+}
+
+/**********************************************************************
+ Memory
+**********************************************************************/
+
+static void error_access(const char *kind, hwaddr addr)
+{
+    fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") not supported\n",
+           kind, regname(addr), addr);
+}
+
+static void ignore_access(const char *kind, hwaddr addr)
+{
+    fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") ignored\n",
+           kind, regname(addr), addr);
+}
+
+static uint32_t sh7750_mem_readb(void *opaque, hwaddr addr)
+{
+    switch (addr) {
+    default:
+       error_access("byte read", addr);
+        abort();
+    }
+}
+
+static uint32_t sh7750_mem_readw(void *opaque, hwaddr addr)
+{
+    SH7750State *s = opaque;
+
+    switch (addr) {
+    case SH7750_BCR2_A7:
+       return s->bcr2;
+    case SH7750_BCR3_A7:
+       if(!has_bcr3_and_bcr4(s))
+           error_access("word read", addr);
+       return s->bcr3;
+    case SH7750_FRQCR_A7:
+       return 0;
+    case SH7750_PCR_A7:
+       return s->pcr;
+    case SH7750_RFCR_A7:
+       fprintf(stderr,
+               "Read access to refresh count register, incrementing\n");
+       return s->rfcr++;
+    case SH7750_PDTRA_A7:
+       return porta_lines(s);
+    case SH7750_PDTRB_A7:
+       return portb_lines(s);
+    case SH7750_RTCOR_A7:
+    case SH7750_RTCNT_A7:
+    case SH7750_RTCSR_A7:
+       ignore_access("word read", addr);
+       return 0;
+    default:
+       error_access("word read", addr);
+        abort();
+    }
+}
+
+static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
+{
+    SH7750State *s = opaque;
+
+    switch (addr) {
+    case SH7750_BCR1_A7:
+       return s->bcr1;
+    case SH7750_BCR4_A7:
+       if(!has_bcr3_and_bcr4(s))
+           error_access("long read", addr);
+       return s->bcr4;
+    case SH7750_WCR1_A7:
+    case SH7750_WCR2_A7:
+    case SH7750_WCR3_A7:
+    case SH7750_MCR_A7:
+        ignore_access("long read", addr);
+        return 0;
+    case SH7750_MMUCR_A7:
+       return s->cpu->mmucr;
+    case SH7750_PTEH_A7:
+       return s->cpu->pteh;
+    case SH7750_PTEL_A7:
+       return s->cpu->ptel;
+    case SH7750_TTB_A7:
+       return s->cpu->ttb;
+    case SH7750_TEA_A7:
+       return s->cpu->tea;
+    case SH7750_TRA_A7:
+       return s->cpu->tra;
+    case SH7750_EXPEVT_A7:
+       return s->cpu->expevt;
+    case SH7750_INTEVT_A7:
+       return s->cpu->intevt;
+    case SH7750_CCR_A7:
+       return s->ccr;
+    case 0x1f000030:           /* Processor version */
+       return s->cpu->pvr;
+    case 0x1f000040:           /* Cache version */
+       return s->cpu->cvr;
+    case 0x1f000044:           /* Processor revision */
+       return s->cpu->prr;
+    default:
+       error_access("long read", addr);
+        abort();
+    }
+}
+
+#define is_in_sdrmx(a, x) (a >= SH7750_SDMR ## x ## _A7 \
+                       && a <= (SH7750_SDMR ## x ## _A7 + SH7750_SDMR ## x ## _REGNB))
+static void sh7750_mem_writeb(void *opaque, hwaddr addr,
+                             uint32_t mem_value)
+{
+
+    if (is_in_sdrmx(addr, 2) || is_in_sdrmx(addr, 3)) {
+       ignore_access("byte write", addr);
+       return;
+    }
+
+    error_access("byte write", addr);
+    abort();
+}
+
+static void sh7750_mem_writew(void *opaque, hwaddr addr,
+                             uint32_t mem_value)
+{
+    SH7750State *s = opaque;
+    uint16_t temp;
+
+    switch (addr) {
+       /* SDRAM controller */
+    case SH7750_BCR2_A7:
+        s->bcr2 = mem_value;
+        return;
+    case SH7750_BCR3_A7:
+       if(!has_bcr3_and_bcr4(s))
+           error_access("word write", addr);
+       s->bcr3 = mem_value;
+       return;
+    case SH7750_PCR_A7:
+       s->pcr = mem_value;
+       return;
+    case SH7750_RTCNT_A7:
+    case SH7750_RTCOR_A7:
+    case SH7750_RTCSR_A7:
+       ignore_access("word write", addr);
+       return;
+       /* IO ports */
+    case SH7750_PDTRA_A7:
+       temp = porta_lines(s);
+       s->pdtra = mem_value;
+       porta_changed(s, temp);
+       return;
+    case SH7750_PDTRB_A7:
+       temp = portb_lines(s);
+       s->pdtrb = mem_value;
+       portb_changed(s, temp);
+       return;
+    case SH7750_RFCR_A7:
+       fprintf(stderr, "Write access to refresh count register\n");
+       s->rfcr = mem_value;
+       return;
+    case SH7750_GPIOIC_A7:
+       s->gpioic = mem_value;
+       if (mem_value != 0) {
+           fprintf(stderr, "I/O interrupts not implemented\n");
+            abort();
+       }
+       return;
+    default:
+       error_access("word write", addr);
+        abort();
+    }
+}
+
+static void sh7750_mem_writel(void *opaque, hwaddr addr,
+                             uint32_t mem_value)
+{
+    SH7750State *s = opaque;
+    uint16_t temp;
+
+    switch (addr) {
+       /* SDRAM controller */
+    case SH7750_BCR1_A7:
+        s->bcr1 = mem_value;
+        return;
+    case SH7750_BCR4_A7:
+       if(!has_bcr3_and_bcr4(s))
+           error_access("long write", addr);
+       s->bcr4 = mem_value;
+       return;
+    case SH7750_WCR1_A7:
+    case SH7750_WCR2_A7:
+    case SH7750_WCR3_A7:
+    case SH7750_MCR_A7:
+       ignore_access("long write", addr);
+       return;
+       /* IO ports */
+    case SH7750_PCTRA_A7:
+       temp = porta_lines(s);
+       s->pctra = mem_value;
+       s->portdira = portdir(mem_value);
+       s->portpullupa = portpullup(mem_value);
+       porta_changed(s, temp);
+       return;
+    case SH7750_PCTRB_A7:
+       temp = portb_lines(s);
+       s->pctrb = mem_value;
+       s->portdirb = portdir(mem_value);
+       s->portpullupb = portpullup(mem_value);
+       portb_changed(s, temp);
+       return;
+    case SH7750_MMUCR_A7:
+        if (mem_value & MMUCR_TI) {
+            cpu_sh4_invalidate_tlb(s->cpu);
+        }
+        s->cpu->mmucr = mem_value & ~MMUCR_TI;
+        return;
+    case SH7750_PTEH_A7:
+        /* If asid changes, clear all registered tlb entries. */
+       if ((s->cpu->pteh & 0xff) != (mem_value & 0xff))
+           tlb_flush(s->cpu, 1);
+       s->cpu->pteh = mem_value;
+       return;
+    case SH7750_PTEL_A7:
+       s->cpu->ptel = mem_value;
+       return;
+    case SH7750_PTEA_A7:
+       s->cpu->ptea = mem_value & 0x0000000f;
+       return;
+    case SH7750_TTB_A7:
+       s->cpu->ttb = mem_value;
+       return;
+    case SH7750_TEA_A7:
+       s->cpu->tea = mem_value;
+       return;
+    case SH7750_TRA_A7:
+       s->cpu->tra = mem_value & 0x000007ff;
+       return;
+    case SH7750_EXPEVT_A7:
+       s->cpu->expevt = mem_value & 0x000007ff;
+       return;
+    case SH7750_INTEVT_A7:
+       s->cpu->intevt = mem_value & 0x000007ff;
+       return;
+    case SH7750_CCR_A7:
+       s->ccr = mem_value;
+       return;
+    default:
+       error_access("long write", addr);
+        abort();
+    }
+}
+
+static const MemoryRegionOps sh7750_mem_ops = {
+    .old_mmio = {
+        .read = {sh7750_mem_readb,
+                 sh7750_mem_readw,
+                 sh7750_mem_readl },
+        .write = {sh7750_mem_writeb,
+                  sh7750_mem_writew,
+                  sh7750_mem_writel },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+/* sh775x interrupt controller tables for sh_intc.c
+ * stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+ */
+
+enum {
+       UNUSED = 0,
+
+       /* interrupt sources */
+       IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
+       IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
+       IRL0, IRL1, IRL2, IRL3,
+       HUDI, GPIOI,
+       DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
+       DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
+       DMAC_DMAE,
+       PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+       PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
+       TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
+       RTC_ATI, RTC_PRI, RTC_CUI,
+       SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
+       SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
+       WDT,
+       REF_RCMI, REF_ROVI,
+
+       /* interrupt groups */
+       DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
+       /* irl bundle */
+       IRL,
+
+       NR_SOURCES,
+};
+
+static struct intc_vect vectors[] = {
+       INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
+       INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+       INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
+       INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
+       INTC_VECT(RTC_CUI, 0x4c0),
+       INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
+       INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
+       INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
+       INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
+       INTC_VECT(WDT, 0x560),
+       INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
+};
+
+static struct intc_group groups[] = {
+       INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
+       INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
+       INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
+       INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
+       INTC_GROUP(REF, REF_RCMI, REF_ROVI),
+};
+
+static struct intc_prio_reg prio_registers[] = {
+       { 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
+       { 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
+       { 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
+       { 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
+       { 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0,
+                                                TMU4, TMU3,
+                                                PCIC1, PCIC0_PCISERR } },
+};
+
+/* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
+
+static struct intc_vect vectors_dma4[] = {
+       INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+       INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+       INTC_VECT(DMAC_DMAE, 0x6c0),
+};
+
+static struct intc_group groups_dma4[] = {
+       INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+                  DMAC_DMTE3, DMAC_DMAE),
+};
+
+/* SH7750R and SH7751R both have 8-channel DMA controllers */
+
+static struct intc_vect vectors_dma8[] = {
+       INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+       INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+       INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
+       INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
+       INTC_VECT(DMAC_DMAE, 0x6c0),
+};
+
+static struct intc_group groups_dma8[] = {
+       INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+                  DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
+                  DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
+};
+
+/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
+
+static struct intc_vect vectors_tmu34[] = {
+       INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
+};
+
+static struct intc_mask_reg mask_registers[] = {
+       { 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
+         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+           0, 0, 0, 0, 0, 0, TMU4, TMU3,
+           PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+           PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
+           PCIC1_PCIDMA3, PCIC0_PCISERR } },
+};
+
+/* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
+
+static struct intc_vect vectors_irlm[] = {
+       INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
+       INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
+};
+
+/* SH7751 and SH7751R both have PCI */
+
+static struct intc_vect vectors_pci[] = {
+       INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
+       INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
+       INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
+       INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
+};
+
+static struct intc_group groups_pci[] = {
+       INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+                  PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
+};
+
+static struct intc_vect vectors_irl[] = {
+       INTC_VECT(IRL_0, 0x200),
+       INTC_VECT(IRL_1, 0x220),
+       INTC_VECT(IRL_2, 0x240),
+       INTC_VECT(IRL_3, 0x260),
+       INTC_VECT(IRL_4, 0x280),
+       INTC_VECT(IRL_5, 0x2a0),
+       INTC_VECT(IRL_6, 0x2c0),
+       INTC_VECT(IRL_7, 0x2e0),
+       INTC_VECT(IRL_8, 0x300),
+       INTC_VECT(IRL_9, 0x320),
+       INTC_VECT(IRL_A, 0x340),
+       INTC_VECT(IRL_B, 0x360),
+       INTC_VECT(IRL_C, 0x380),
+       INTC_VECT(IRL_D, 0x3a0),
+       INTC_VECT(IRL_E, 0x3c0),
+};
+
+static struct intc_group groups_irl[] = {
+       INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
+               IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
+};
+
+/**********************************************************************
+ Memory mapped cache and TLB
+**********************************************************************/
+
+#define MM_REGION_MASK   0x07000000
+#define MM_ICACHE_ADDR   (0)
+#define MM_ICACHE_DATA   (1)
+#define MM_ITLB_ADDR     (2)
+#define MM_ITLB_DATA     (3)
+#define MM_OCACHE_ADDR   (4)
+#define MM_OCACHE_DATA   (5)
+#define MM_UTLB_ADDR     (6)
+#define MM_UTLB_DATA     (7)
+#define MM_REGION_TYPE(addr)  ((addr & MM_REGION_MASK) >> 24)
+
+static uint64_t invalid_read(void *opaque, hwaddr addr)
+{
+    abort();
+
+    return 0;
+}
+
+static uint64_t sh7750_mmct_read(void *opaque, hwaddr addr,
+                                 unsigned size)
+{
+    SH7750State *s = opaque;
+    uint32_t ret = 0;
+
+    if (size != 4) {
+        return invalid_read(opaque, addr);
+    }
+
+    switch (MM_REGION_TYPE(addr)) {
+    case MM_ICACHE_ADDR:
+    case MM_ICACHE_DATA:
+        /* do nothing */
+       break;
+    case MM_ITLB_ADDR:
+        ret = cpu_sh4_read_mmaped_itlb_addr(s->cpu, addr);
+        break;
+    case MM_ITLB_DATA:
+        ret = cpu_sh4_read_mmaped_itlb_data(s->cpu, addr);
+        break;
+    case MM_OCACHE_ADDR:
+    case MM_OCACHE_DATA:
+        /* do nothing */
+       break;
+    case MM_UTLB_ADDR:
+        ret = cpu_sh4_read_mmaped_utlb_addr(s->cpu, addr);
+        break;
+    case MM_UTLB_DATA:
+        ret = cpu_sh4_read_mmaped_utlb_data(s->cpu, addr);
+        break;
+    default:
+        abort();
+    }
+
+    return ret;
+}
+
+static void invalid_write(void *opaque, hwaddr addr,
+                          uint64_t mem_value)
+{
+    abort();
+}
+
+static void sh7750_mmct_write(void *opaque, hwaddr addr,
+                              uint64_t mem_value, unsigned size)
+{
+    SH7750State *s = opaque;
+
+    if (size != 4) {
+        invalid_write(opaque, addr, mem_value);
+    }
+
+    switch (MM_REGION_TYPE(addr)) {
+    case MM_ICACHE_ADDR:
+    case MM_ICACHE_DATA:
+        /* do nothing */
+       break;
+    case MM_ITLB_ADDR:
+        cpu_sh4_write_mmaped_itlb_addr(s->cpu, addr, mem_value);
+        break;
+    case MM_ITLB_DATA:
+        cpu_sh4_write_mmaped_itlb_data(s->cpu, addr, mem_value);
+        abort();
+       break;
+    case MM_OCACHE_ADDR:
+    case MM_OCACHE_DATA:
+        /* do nothing */
+       break;
+    case MM_UTLB_ADDR:
+        cpu_sh4_write_mmaped_utlb_addr(s->cpu, addr, mem_value);
+       break;
+    case MM_UTLB_DATA:
+        cpu_sh4_write_mmaped_utlb_data(s->cpu, addr, mem_value);
+       break;
+    default:
+        abort();
+       break;
+    }
+}
+
+static const MemoryRegionOps sh7750_mmct_ops = {
+    .read = sh7750_mmct_read,
+    .write = sh7750_mmct_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
+{
+    SH7750State *s;
+
+    s = g_malloc0(sizeof(SH7750State));
+    s->cpu = cpu;
+    s->periph_freq = 60000000; /* 60MHz */
+    memory_region_init_io(&s->iomem, &sh7750_mem_ops, s,
+                          "memory", 0x1fc01000);
+
+    memory_region_init_alias(&s->iomem_1f0, "memory-1f0",
+                             &s->iomem, 0x1f000000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0);
+
+    memory_region_init_alias(&s->iomem_ff0, "memory-ff0",
+                             &s->iomem, 0x1f000000, 0x1000);
+    memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0);
+
+    memory_region_init_alias(&s->iomem_1f8, "memory-1f8",
+                             &s->iomem, 0x1f800000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8);
+
+    memory_region_init_alias(&s->iomem_ff8, "memory-ff8",
+                             &s->iomem, 0x1f800000, 0x1000);
+    memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8);
+
+    memory_region_init_alias(&s->iomem_1fc, "memory-1fc",
+                             &s->iomem, 0x1fc00000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc);
+
+    memory_region_init_alias(&s->iomem_ffc, "memory-ffc",
+                             &s->iomem, 0x1fc00000, 0x1000);
+    memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc);
+
+    memory_region_init_io(&s->mmct_iomem, &sh7750_mmct_ops, s,
+                          "cache-and-tlb", 0x08000000);
+    memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
+
+    sh_intc_init(sysmem, &s->intc, NR_SOURCES,
+                _INTC_ARRAY(mask_registers),
+                _INTC_ARRAY(prio_registers));
+
+    sh_intc_register_sources(&s->intc,
+                            _INTC_ARRAY(vectors),
+                            _INTC_ARRAY(groups));
+
+    cpu->intc_handle = &s->intc;
+
+    sh_serial_init(sysmem, 0x1fe00000,
+                   0, s->periph_freq, serial_hds[0],
+                   s->intc.irqs[SCI1_ERI],
+                   s->intc.irqs[SCI1_RXI],
+                   s->intc.irqs[SCI1_TXI],
+                   s->intc.irqs[SCI1_TEI],
+                   NULL);
+    sh_serial_init(sysmem, 0x1fe80000,
+                   SH_SERIAL_FEAT_SCIF,
+                   s->periph_freq, serial_hds[1],
+                   s->intc.irqs[SCIF_ERI],
+                   s->intc.irqs[SCIF_RXI],
+                   s->intc.irqs[SCIF_TXI],
+                   NULL,
+                   s->intc.irqs[SCIF_BRI]);
+
+    tmu012_init(sysmem, 0x1fd80000,
+               TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
+               s->periph_freq,
+               s->intc.irqs[TMU0],
+               s->intc.irqs[TMU1],
+               s->intc.irqs[TMU2_TUNI],
+               s->intc.irqs[TMU2_TICPI]);
+
+    if (cpu->id & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
+        sh_intc_register_sources(&s->intc,
+                                _INTC_ARRAY(vectors_dma4),
+                                _INTC_ARRAY(groups_dma4));
+    }
+
+    if (cpu->id & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
+        sh_intc_register_sources(&s->intc,
+                                _INTC_ARRAY(vectors_dma8),
+                                _INTC_ARRAY(groups_dma8));
+    }
+
+    if (cpu->id & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
+        sh_intc_register_sources(&s->intc,
+                                _INTC_ARRAY(vectors_tmu34),
+                                NULL, 0);
+        tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq,
+                   s->intc.irqs[TMU3],
+                   s->intc.irqs[TMU4],
+                   NULL, NULL);
+    }
+
+    if (cpu->id & (SH_CPU_SH7751_ALL)) {
+        sh_intc_register_sources(&s->intc,
+                                _INTC_ARRAY(vectors_pci),
+                                _INTC_ARRAY(groups_pci));
+    }
+
+    if (cpu->id & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
+        sh_intc_register_sources(&s->intc,
+                                _INTC_ARRAY(vectors_irlm),
+                                NULL, 0);
+    }
+
+    sh_intc_register_sources(&s->intc,
+                               _INTC_ARRAY(vectors_irl),
+                               _INTC_ARRAY(groups_irl));
+    return s;
+}
+
+qemu_irq sh7750_irl(SH7750State *s)
+{
+    sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
+    return qemu_allocate_irqs(sh_intc_set_irl, sh_intc_source(&s->intc, IRL),
+                               1)[0];
+}
diff --git a/hw/sh4/sh7750_regnames.c b/hw/sh4/sh7750_regnames.c
new file mode 100644 (file)
index 0000000..389698d
--- /dev/null
@@ -0,0 +1,97 @@
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "hw/sh7750_regs.h"
+#include "hw/sh7750_regnames.h"
+
+#define REGNAME(r) {r, #r},
+
+typedef struct {
+    uint32_t regaddr;
+    const char *regname;
+} regname_t;
+
+static regname_t regnames[] = {
+    REGNAME(SH7750_PTEH_A7)
+       REGNAME(SH7750_PTEL_A7)
+       REGNAME(SH7750_PTEA_A7)
+       REGNAME(SH7750_TTB_A7)
+       REGNAME(SH7750_TEA_A7)
+       REGNAME(SH7750_MMUCR_A7)
+       REGNAME(SH7750_CCR_A7)
+       REGNAME(SH7750_QACR0_A7)
+       REGNAME(SH7750_QACR1_A7)
+       REGNAME(SH7750_TRA_A7)
+       REGNAME(SH7750_EXPEVT_A7)
+       REGNAME(SH7750_INTEVT_A7)
+       REGNAME(SH7750_STBCR_A7)
+       REGNAME(SH7750_STBCR2_A7)
+       REGNAME(SH7750_FRQCR_A7)
+       REGNAME(SH7750_WTCNT_A7)
+       REGNAME(SH7750_WTCSR_A7)
+       REGNAME(SH7750_R64CNT_A7)
+       REGNAME(SH7750_RSECCNT_A7)
+       REGNAME(SH7750_RMINCNT_A7)
+       REGNAME(SH7750_RHRCNT_A7)
+       REGNAME(SH7750_RWKCNT_A7)
+       REGNAME(SH7750_RDAYCNT_A7)
+       REGNAME(SH7750_RMONCNT_A7)
+       REGNAME(SH7750_RYRCNT_A7)
+       REGNAME(SH7750_RSECAR_A7)
+       REGNAME(SH7750_RMINAR_A7)
+       REGNAME(SH7750_RHRAR_A7)
+       REGNAME(SH7750_RWKAR_A7)
+       REGNAME(SH7750_RDAYAR_A7)
+       REGNAME(SH7750_RMONAR_A7)
+       REGNAME(SH7750_RCR1_A7)
+       REGNAME(SH7750_RCR2_A7)
+       REGNAME(SH7750_BCR1_A7)
+       REGNAME(SH7750_BCR2_A7)
+       REGNAME(SH7750_WCR1_A7)
+       REGNAME(SH7750_WCR2_A7)
+       REGNAME(SH7750_WCR3_A7)
+       REGNAME(SH7750_MCR_A7)
+       REGNAME(SH7750_PCR_A7)
+       REGNAME(SH7750_RTCSR_A7)
+       REGNAME(SH7750_RTCNT_A7)
+       REGNAME(SH7750_RTCOR_A7)
+       REGNAME(SH7750_RFCR_A7)
+       REGNAME(SH7750_SAR0_A7)
+       REGNAME(SH7750_SAR1_A7)
+       REGNAME(SH7750_SAR2_A7)
+       REGNAME(SH7750_SAR3_A7)
+       REGNAME(SH7750_DAR0_A7)
+       REGNAME(SH7750_DAR1_A7)
+       REGNAME(SH7750_DAR2_A7)
+       REGNAME(SH7750_DAR3_A7)
+       REGNAME(SH7750_DMATCR0_A7)
+       REGNAME(SH7750_DMATCR1_A7)
+       REGNAME(SH7750_DMATCR2_A7)
+       REGNAME(SH7750_DMATCR3_A7)
+       REGNAME(SH7750_CHCR0_A7)
+       REGNAME(SH7750_CHCR1_A7)
+       REGNAME(SH7750_CHCR2_A7)
+       REGNAME(SH7750_CHCR3_A7)
+       REGNAME(SH7750_DMAOR_A7)
+       REGNAME(SH7750_PCTRA_A7)
+       REGNAME(SH7750_PDTRA_A7)
+       REGNAME(SH7750_PCTRB_A7)
+       REGNAME(SH7750_PDTRB_A7)
+       REGNAME(SH7750_GPIOIC_A7)
+       REGNAME(SH7750_ICR_A7)
+       REGNAME(SH7750_BCR3_A7)
+       REGNAME(SH7750_BCR4_A7)
+       REGNAME(SH7750_SDMR2_A7)
+       REGNAME(SH7750_SDMR3_A7) {(uint32_t) - 1, NULL}
+};
+
+const char *regname(uint32_t addr)
+{
+    unsigned int i;
+
+    for (i = 0; regnames[i].regaddr != (uint32_t) - 1; i++) {
+       if (regnames[i].regaddr == addr)
+           return regnames[i].regname;
+    }
+
+    return "<unknown reg>";
+}
diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c
new file mode 100644 (file)
index 0000000..192579d
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * SHIX 2.0 board description
+ *
+ * Copyright (c) 2005 Samuel Tardieu
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+/*
+   Shix 2.0 board by Alexis Polti, described at
+   http://perso.enst.fr/~polti/realisations/shix20/
+
+   More information in target-sh4/README.sh4
+*/
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "exec/address-spaces.h"
+
+#define BIOS_FILENAME "shix_bios.bin"
+#define BIOS_ADDRESS 0xA0000000
+
+static void shix_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    int ret;
+    CPUSH4State *env;
+    struct SH7750State *s;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    MemoryRegion *sdram = g_new(MemoryRegion, 2);
+    
+    if (!cpu_model)
+        cpu_model = "any";
+
+    printf("Initializing CPU\n");
+    env = cpu_init(cpu_model);
+
+    /* Allocate memory space */
+    printf("Allocating ROM\n");
+    memory_region_init_ram(rom, "shix.rom", 0x4000);
+    vmstate_register_ram_global(rom);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(sysmem, 0x00000000, rom);
+    printf("Allocating SDRAM 1\n");
+    memory_region_init_ram(&sdram[0], "shix.sdram1", 0x01000000);
+    vmstate_register_ram_global(&sdram[0]);
+    memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]);
+    printf("Allocating SDRAM 2\n");
+    memory_region_init_ram(&sdram[1], "shix.sdram2", 0x01000000);
+    vmstate_register_ram_global(&sdram[1]);
+    memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
+
+    /* Load BIOS in 0 (and access it through P2, 0xA0000000) */
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    printf("%s: load BIOS '%s'\n", __func__, bios_name);
+    ret = load_image_targphys(bios_name, 0, 0x4000);
+    if (ret < 0) {             /* Check bios size */
+       fprintf(stderr, "ret=%d\n", ret);
+       fprintf(stderr, "qemu: could not load SHIX bios '%s'\n",
+               bios_name);
+       exit(1);
+    }
+
+    /* Register peripherals */
+    s = sh7750_init(env, sysmem);
+    /* XXXXX Check success */
+    tc58128_init(s, "shix_linux_nand.bin", NULL);
+    fprintf(stderr, "initialization terminated\n");
+}
+
+static QEMUMachine shix_machine = {
+    .name = "shix",
+    .desc = "shix card",
+    .init = shix_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void shix_machine_init(void)
+{
+    qemu_register_machine(&shix_machine);
+}
+
+machine_init(shix_machine_init);
diff --git a/hw/sh7750.c b/hw/sh7750.c
deleted file mode 100644 (file)
index 666f865..0000000
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
- * SH7750 device
- *
- * Copyright (c) 2007 Magnus Damm
- * Copyright (c) 2005 Samuel Tardieu
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include <stdio.h>
-#include "hw.h"
-#include "sh.h"
-#include "sysemu/sysemu.h"
-#include "sh7750_regs.h"
-#include "sh7750_regnames.h"
-#include "sh_intc.h"
-#include "cpu.h"
-#include "exec/address-spaces.h"
-
-#define NB_DEVICES 4
-
-typedef struct SH7750State {
-    MemoryRegion iomem;
-    MemoryRegion iomem_1f0;
-    MemoryRegion iomem_ff0;
-    MemoryRegion iomem_1f8;
-    MemoryRegion iomem_ff8;
-    MemoryRegion iomem_1fc;
-    MemoryRegion iomem_ffc;
-    MemoryRegion mmct_iomem;
-    /* CPU */
-    CPUSH4State *cpu;
-    /* Peripheral frequency in Hz */
-    uint32_t periph_freq;
-    /* SDRAM controller */
-    uint32_t bcr1;
-    uint16_t bcr2;
-    uint16_t bcr3;
-    uint32_t bcr4;
-    uint16_t rfcr;
-    /* PCMCIA controller */
-    uint16_t pcr;
-    /* IO ports */
-    uint16_t gpioic;
-    uint32_t pctra;
-    uint32_t pctrb;
-    uint16_t portdira;         /* Cached */
-    uint16_t portpullupa;      /* Cached */
-    uint16_t portdirb;         /* Cached */
-    uint16_t portpullupb;      /* Cached */
-    uint16_t pdtra;
-    uint16_t pdtrb;
-    uint16_t periph_pdtra;     /* Imposed by the peripherals */
-    uint16_t periph_portdira;  /* Direction seen from the peripherals */
-    uint16_t periph_pdtrb;     /* Imposed by the peripherals */
-    uint16_t periph_portdirb;  /* Direction seen from the peripherals */
-    sh7750_io_device *devices[NB_DEVICES];     /* External peripherals */
-
-    /* Cache */
-    uint32_t ccr;
-
-    struct intc_desc intc;
-} SH7750State;
-
-static inline int has_bcr3_and_bcr4(SH7750State * s)
-{
-       return (s->cpu->features & SH_FEATURE_BCR3_AND_BCR4);
-}
-/**********************************************************************
- I/O ports
-**********************************************************************/
-
-int sh7750_register_io_device(SH7750State * s, sh7750_io_device * device)
-{
-    int i;
-
-    for (i = 0; i < NB_DEVICES; i++) {
-       if (s->devices[i] == NULL) {
-           s->devices[i] = device;
-           return 0;
-       }
-    }
-    return -1;
-}
-
-static uint16_t portdir(uint32_t v)
-{
-#define EVENPORTMASK(n) ((v & (1<<((n)<<1))) >> (n))
-    return
-       EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
-       EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
-       EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
-       EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
-       EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
-       EVENPORTMASK(0);
-}
-
-static uint16_t portpullup(uint32_t v)
-{
-#define ODDPORTMASK(n) ((v & (1<<(((n)<<1)+1))) >> (n))
-    return
-       ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
-       ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
-       ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
-       ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
-       ODDPORTMASK(1) | ODDPORTMASK(0);
-}
-
-static uint16_t porta_lines(SH7750State * s)
-{
-    return (s->portdira & s->pdtra) |  /* CPU */
-       (s->periph_portdira & s->periph_pdtra) |        /* Peripherals */
-       (~(s->portdira | s->periph_portdira) & s->portpullupa); /* Pullups */
-}
-
-static uint16_t portb_lines(SH7750State * s)
-{
-    return (s->portdirb & s->pdtrb) |  /* CPU */
-       (s->periph_portdirb & s->periph_pdtrb) |        /* Peripherals */
-       (~(s->portdirb | s->periph_portdirb) & s->portpullupb); /* Pullups */
-}
-
-static void gen_port_interrupts(SH7750State * s)
-{
-    /* XXXXX interrupts not generated */
-}
-
-static void porta_changed(SH7750State * s, uint16_t prev)
-{
-    uint16_t currenta, changes;
-    int i, r = 0;
-
-#if 0
-    fprintf(stderr, "porta changed from 0x%04x to 0x%04x\n",
-           prev, porta_lines(s));
-    fprintf(stderr, "pdtra=0x%04x, pctra=0x%08x\n", s->pdtra, s->pctra);
-#endif
-    currenta = porta_lines(s);
-    if (currenta == prev)
-       return;
-    changes = currenta ^ prev;
-
-    for (i = 0; i < NB_DEVICES; i++) {
-       if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
-           r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
-                                              &s->periph_pdtra,
-                                              &s->periph_portdira,
-                                              &s->periph_pdtrb,
-                                              &s->periph_portdirb);
-       }
-    }
-
-    if (r)
-       gen_port_interrupts(s);
-}
-
-static void portb_changed(SH7750State * s, uint16_t prev)
-{
-    uint16_t currentb, changes;
-    int i, r = 0;
-
-    currentb = portb_lines(s);
-    if (currentb == prev)
-       return;
-    changes = currentb ^ prev;
-
-    for (i = 0; i < NB_DEVICES; i++) {
-       if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
-           r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
-                                              &s->periph_pdtra,
-                                              &s->periph_portdira,
-                                              &s->periph_pdtrb,
-                                              &s->periph_portdirb);
-       }
-    }
-
-    if (r)
-       gen_port_interrupts(s);
-}
-
-/**********************************************************************
- Memory
-**********************************************************************/
-
-static void error_access(const char *kind, hwaddr addr)
-{
-    fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") not supported\n",
-           kind, regname(addr), addr);
-}
-
-static void ignore_access(const char *kind, hwaddr addr)
-{
-    fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") ignored\n",
-           kind, regname(addr), addr);
-}
-
-static uint32_t sh7750_mem_readb(void *opaque, hwaddr addr)
-{
-    switch (addr) {
-    default:
-       error_access("byte read", addr);
-        abort();
-    }
-}
-
-static uint32_t sh7750_mem_readw(void *opaque, hwaddr addr)
-{
-    SH7750State *s = opaque;
-
-    switch (addr) {
-    case SH7750_BCR2_A7:
-       return s->bcr2;
-    case SH7750_BCR3_A7:
-       if(!has_bcr3_and_bcr4(s))
-           error_access("word read", addr);
-       return s->bcr3;
-    case SH7750_FRQCR_A7:
-       return 0;
-    case SH7750_PCR_A7:
-       return s->pcr;
-    case SH7750_RFCR_A7:
-       fprintf(stderr,
-               "Read access to refresh count register, incrementing\n");
-       return s->rfcr++;
-    case SH7750_PDTRA_A7:
-       return porta_lines(s);
-    case SH7750_PDTRB_A7:
-       return portb_lines(s);
-    case SH7750_RTCOR_A7:
-    case SH7750_RTCNT_A7:
-    case SH7750_RTCSR_A7:
-       ignore_access("word read", addr);
-       return 0;
-    default:
-       error_access("word read", addr);
-        abort();
-    }
-}
-
-static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
-{
-    SH7750State *s = opaque;
-
-    switch (addr) {
-    case SH7750_BCR1_A7:
-       return s->bcr1;
-    case SH7750_BCR4_A7:
-       if(!has_bcr3_and_bcr4(s))
-           error_access("long read", addr);
-       return s->bcr4;
-    case SH7750_WCR1_A7:
-    case SH7750_WCR2_A7:
-    case SH7750_WCR3_A7:
-    case SH7750_MCR_A7:
-        ignore_access("long read", addr);
-        return 0;
-    case SH7750_MMUCR_A7:
-       return s->cpu->mmucr;
-    case SH7750_PTEH_A7:
-       return s->cpu->pteh;
-    case SH7750_PTEL_A7:
-       return s->cpu->ptel;
-    case SH7750_TTB_A7:
-       return s->cpu->ttb;
-    case SH7750_TEA_A7:
-       return s->cpu->tea;
-    case SH7750_TRA_A7:
-       return s->cpu->tra;
-    case SH7750_EXPEVT_A7:
-       return s->cpu->expevt;
-    case SH7750_INTEVT_A7:
-       return s->cpu->intevt;
-    case SH7750_CCR_A7:
-       return s->ccr;
-    case 0x1f000030:           /* Processor version */
-       return s->cpu->pvr;
-    case 0x1f000040:           /* Cache version */
-       return s->cpu->cvr;
-    case 0x1f000044:           /* Processor revision */
-       return s->cpu->prr;
-    default:
-       error_access("long read", addr);
-        abort();
-    }
-}
-
-#define is_in_sdrmx(a, x) (a >= SH7750_SDMR ## x ## _A7 \
-                       && a <= (SH7750_SDMR ## x ## _A7 + SH7750_SDMR ## x ## _REGNB))
-static void sh7750_mem_writeb(void *opaque, hwaddr addr,
-                             uint32_t mem_value)
-{
-
-    if (is_in_sdrmx(addr, 2) || is_in_sdrmx(addr, 3)) {
-       ignore_access("byte write", addr);
-       return;
-    }
-
-    error_access("byte write", addr);
-    abort();
-}
-
-static void sh7750_mem_writew(void *opaque, hwaddr addr,
-                             uint32_t mem_value)
-{
-    SH7750State *s = opaque;
-    uint16_t temp;
-
-    switch (addr) {
-       /* SDRAM controller */
-    case SH7750_BCR2_A7:
-        s->bcr2 = mem_value;
-        return;
-    case SH7750_BCR3_A7:
-       if(!has_bcr3_and_bcr4(s))
-           error_access("word write", addr);
-       s->bcr3 = mem_value;
-       return;
-    case SH7750_PCR_A7:
-       s->pcr = mem_value;
-       return;
-    case SH7750_RTCNT_A7:
-    case SH7750_RTCOR_A7:
-    case SH7750_RTCSR_A7:
-       ignore_access("word write", addr);
-       return;
-       /* IO ports */
-    case SH7750_PDTRA_A7:
-       temp = porta_lines(s);
-       s->pdtra = mem_value;
-       porta_changed(s, temp);
-       return;
-    case SH7750_PDTRB_A7:
-       temp = portb_lines(s);
-       s->pdtrb = mem_value;
-       portb_changed(s, temp);
-       return;
-    case SH7750_RFCR_A7:
-       fprintf(stderr, "Write access to refresh count register\n");
-       s->rfcr = mem_value;
-       return;
-    case SH7750_GPIOIC_A7:
-       s->gpioic = mem_value;
-       if (mem_value != 0) {
-           fprintf(stderr, "I/O interrupts not implemented\n");
-            abort();
-       }
-       return;
-    default:
-       error_access("word write", addr);
-        abort();
-    }
-}
-
-static void sh7750_mem_writel(void *opaque, hwaddr addr,
-                             uint32_t mem_value)
-{
-    SH7750State *s = opaque;
-    uint16_t temp;
-
-    switch (addr) {
-       /* SDRAM controller */
-    case SH7750_BCR1_A7:
-        s->bcr1 = mem_value;
-        return;
-    case SH7750_BCR4_A7:
-       if(!has_bcr3_and_bcr4(s))
-           error_access("long write", addr);
-       s->bcr4 = mem_value;
-       return;
-    case SH7750_WCR1_A7:
-    case SH7750_WCR2_A7:
-    case SH7750_WCR3_A7:
-    case SH7750_MCR_A7:
-       ignore_access("long write", addr);
-       return;
-       /* IO ports */
-    case SH7750_PCTRA_A7:
-       temp = porta_lines(s);
-       s->pctra = mem_value;
-       s->portdira = portdir(mem_value);
-       s->portpullupa = portpullup(mem_value);
-       porta_changed(s, temp);
-       return;
-    case SH7750_PCTRB_A7:
-       temp = portb_lines(s);
-       s->pctrb = mem_value;
-       s->portdirb = portdir(mem_value);
-       s->portpullupb = portpullup(mem_value);
-       portb_changed(s, temp);
-       return;
-    case SH7750_MMUCR_A7:
-        if (mem_value & MMUCR_TI) {
-            cpu_sh4_invalidate_tlb(s->cpu);
-        }
-        s->cpu->mmucr = mem_value & ~MMUCR_TI;
-        return;
-    case SH7750_PTEH_A7:
-        /* If asid changes, clear all registered tlb entries. */
-       if ((s->cpu->pteh & 0xff) != (mem_value & 0xff))
-           tlb_flush(s->cpu, 1);
-       s->cpu->pteh = mem_value;
-       return;
-    case SH7750_PTEL_A7:
-       s->cpu->ptel = mem_value;
-       return;
-    case SH7750_PTEA_A7:
-       s->cpu->ptea = mem_value & 0x0000000f;
-       return;
-    case SH7750_TTB_A7:
-       s->cpu->ttb = mem_value;
-       return;
-    case SH7750_TEA_A7:
-       s->cpu->tea = mem_value;
-       return;
-    case SH7750_TRA_A7:
-       s->cpu->tra = mem_value & 0x000007ff;
-       return;
-    case SH7750_EXPEVT_A7:
-       s->cpu->expevt = mem_value & 0x000007ff;
-       return;
-    case SH7750_INTEVT_A7:
-       s->cpu->intevt = mem_value & 0x000007ff;
-       return;
-    case SH7750_CCR_A7:
-       s->ccr = mem_value;
-       return;
-    default:
-       error_access("long write", addr);
-        abort();
-    }
-}
-
-static const MemoryRegionOps sh7750_mem_ops = {
-    .old_mmio = {
-        .read = {sh7750_mem_readb,
-                 sh7750_mem_readw,
-                 sh7750_mem_readl },
-        .write = {sh7750_mem_writeb,
-                  sh7750_mem_writew,
-                  sh7750_mem_writel },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-/* sh775x interrupt controller tables for sh_intc.c
- * stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
- */
-
-enum {
-       UNUSED = 0,
-
-       /* interrupt sources */
-       IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
-       IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
-       IRL0, IRL1, IRL2, IRL3,
-       HUDI, GPIOI,
-       DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
-       DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
-       DMAC_DMAE,
-       PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
-       PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
-       TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
-       RTC_ATI, RTC_PRI, RTC_CUI,
-       SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
-       SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
-       WDT,
-       REF_RCMI, REF_ROVI,
-
-       /* interrupt groups */
-       DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
-       /* irl bundle */
-       IRL,
-
-       NR_SOURCES,
-};
-
-static struct intc_vect vectors[] = {
-       INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
-       INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
-       INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
-       INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
-       INTC_VECT(RTC_CUI, 0x4c0),
-       INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
-       INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
-       INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
-       INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
-       INTC_VECT(WDT, 0x560),
-       INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
-};
-
-static struct intc_group groups[] = {
-       INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
-       INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
-       INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
-       INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
-       INTC_GROUP(REF, REF_RCMI, REF_ROVI),
-};
-
-static struct intc_prio_reg prio_registers[] = {
-       { 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
-       { 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
-       { 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
-       { 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
-       { 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0,
-                                                TMU4, TMU3,
-                                                PCIC1, PCIC0_PCISERR } },
-};
-
-/* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
-
-static struct intc_vect vectors_dma4[] = {
-       INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
-       INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
-       INTC_VECT(DMAC_DMAE, 0x6c0),
-};
-
-static struct intc_group groups_dma4[] = {
-       INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
-                  DMAC_DMTE3, DMAC_DMAE),
-};
-
-/* SH7750R and SH7751R both have 8-channel DMA controllers */
-
-static struct intc_vect vectors_dma8[] = {
-       INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
-       INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
-       INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
-       INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
-       INTC_VECT(DMAC_DMAE, 0x6c0),
-};
-
-static struct intc_group groups_dma8[] = {
-       INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
-                  DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
-                  DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
-};
-
-/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
-
-static struct intc_vect vectors_tmu34[] = {
-       INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
-};
-
-static struct intc_mask_reg mask_registers[] = {
-       { 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
-         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-           0, 0, 0, 0, 0, 0, TMU4, TMU3,
-           PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
-           PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
-           PCIC1_PCIDMA3, PCIC0_PCISERR } },
-};
-
-/* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
-
-static struct intc_vect vectors_irlm[] = {
-       INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
-       INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
-};
-
-/* SH7751 and SH7751R both have PCI */
-
-static struct intc_vect vectors_pci[] = {
-       INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
-       INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
-       INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
-       INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
-};
-
-static struct intc_group groups_pci[] = {
-       INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
-                  PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
-};
-
-static struct intc_vect vectors_irl[] = {
-       INTC_VECT(IRL_0, 0x200),
-       INTC_VECT(IRL_1, 0x220),
-       INTC_VECT(IRL_2, 0x240),
-       INTC_VECT(IRL_3, 0x260),
-       INTC_VECT(IRL_4, 0x280),
-       INTC_VECT(IRL_5, 0x2a0),
-       INTC_VECT(IRL_6, 0x2c0),
-       INTC_VECT(IRL_7, 0x2e0),
-       INTC_VECT(IRL_8, 0x300),
-       INTC_VECT(IRL_9, 0x320),
-       INTC_VECT(IRL_A, 0x340),
-       INTC_VECT(IRL_B, 0x360),
-       INTC_VECT(IRL_C, 0x380),
-       INTC_VECT(IRL_D, 0x3a0),
-       INTC_VECT(IRL_E, 0x3c0),
-};
-
-static struct intc_group groups_irl[] = {
-       INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
-               IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
-};
-
-/**********************************************************************
- Memory mapped cache and TLB
-**********************************************************************/
-
-#define MM_REGION_MASK   0x07000000
-#define MM_ICACHE_ADDR   (0)
-#define MM_ICACHE_DATA   (1)
-#define MM_ITLB_ADDR     (2)
-#define MM_ITLB_DATA     (3)
-#define MM_OCACHE_ADDR   (4)
-#define MM_OCACHE_DATA   (5)
-#define MM_UTLB_ADDR     (6)
-#define MM_UTLB_DATA     (7)
-#define MM_REGION_TYPE(addr)  ((addr & MM_REGION_MASK) >> 24)
-
-static uint64_t invalid_read(void *opaque, hwaddr addr)
-{
-    abort();
-
-    return 0;
-}
-
-static uint64_t sh7750_mmct_read(void *opaque, hwaddr addr,
-                                 unsigned size)
-{
-    SH7750State *s = opaque;
-    uint32_t ret = 0;
-
-    if (size != 4) {
-        return invalid_read(opaque, addr);
-    }
-
-    switch (MM_REGION_TYPE(addr)) {
-    case MM_ICACHE_ADDR:
-    case MM_ICACHE_DATA:
-        /* do nothing */
-       break;
-    case MM_ITLB_ADDR:
-        ret = cpu_sh4_read_mmaped_itlb_addr(s->cpu, addr);
-        break;
-    case MM_ITLB_DATA:
-        ret = cpu_sh4_read_mmaped_itlb_data(s->cpu, addr);
-        break;
-    case MM_OCACHE_ADDR:
-    case MM_OCACHE_DATA:
-        /* do nothing */
-       break;
-    case MM_UTLB_ADDR:
-        ret = cpu_sh4_read_mmaped_utlb_addr(s->cpu, addr);
-        break;
-    case MM_UTLB_DATA:
-        ret = cpu_sh4_read_mmaped_utlb_data(s->cpu, addr);
-        break;
-    default:
-        abort();
-    }
-
-    return ret;
-}
-
-static void invalid_write(void *opaque, hwaddr addr,
-                          uint64_t mem_value)
-{
-    abort();
-}
-
-static void sh7750_mmct_write(void *opaque, hwaddr addr,
-                              uint64_t mem_value, unsigned size)
-{
-    SH7750State *s = opaque;
-
-    if (size != 4) {
-        invalid_write(opaque, addr, mem_value);
-    }
-
-    switch (MM_REGION_TYPE(addr)) {
-    case MM_ICACHE_ADDR:
-    case MM_ICACHE_DATA:
-        /* do nothing */
-       break;
-    case MM_ITLB_ADDR:
-        cpu_sh4_write_mmaped_itlb_addr(s->cpu, addr, mem_value);
-        break;
-    case MM_ITLB_DATA:
-        cpu_sh4_write_mmaped_itlb_data(s->cpu, addr, mem_value);
-        abort();
-       break;
-    case MM_OCACHE_ADDR:
-    case MM_OCACHE_DATA:
-        /* do nothing */
-       break;
-    case MM_UTLB_ADDR:
-        cpu_sh4_write_mmaped_utlb_addr(s->cpu, addr, mem_value);
-       break;
-    case MM_UTLB_DATA:
-        cpu_sh4_write_mmaped_utlb_data(s->cpu, addr, mem_value);
-       break;
-    default:
-        abort();
-       break;
-    }
-}
-
-static const MemoryRegionOps sh7750_mmct_ops = {
-    .read = sh7750_mmct_read,
-    .write = sh7750_mmct_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
-{
-    SH7750State *s;
-
-    s = g_malloc0(sizeof(SH7750State));
-    s->cpu = cpu;
-    s->periph_freq = 60000000; /* 60MHz */
-    memory_region_init_io(&s->iomem, &sh7750_mem_ops, s,
-                          "memory", 0x1fc01000);
-
-    memory_region_init_alias(&s->iomem_1f0, "memory-1f0",
-                             &s->iomem, 0x1f000000, 0x1000);
-    memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0);
-
-    memory_region_init_alias(&s->iomem_ff0, "memory-ff0",
-                             &s->iomem, 0x1f000000, 0x1000);
-    memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0);
-
-    memory_region_init_alias(&s->iomem_1f8, "memory-1f8",
-                             &s->iomem, 0x1f800000, 0x1000);
-    memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8);
-
-    memory_region_init_alias(&s->iomem_ff8, "memory-ff8",
-                             &s->iomem, 0x1f800000, 0x1000);
-    memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8);
-
-    memory_region_init_alias(&s->iomem_1fc, "memory-1fc",
-                             &s->iomem, 0x1fc00000, 0x1000);
-    memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc);
-
-    memory_region_init_alias(&s->iomem_ffc, "memory-ffc",
-                             &s->iomem, 0x1fc00000, 0x1000);
-    memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc);
-
-    memory_region_init_io(&s->mmct_iomem, &sh7750_mmct_ops, s,
-                          "cache-and-tlb", 0x08000000);
-    memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
-
-    sh_intc_init(sysmem, &s->intc, NR_SOURCES,
-                _INTC_ARRAY(mask_registers),
-                _INTC_ARRAY(prio_registers));
-
-    sh_intc_register_sources(&s->intc,
-                            _INTC_ARRAY(vectors),
-                            _INTC_ARRAY(groups));
-
-    cpu->intc_handle = &s->intc;
-
-    sh_serial_init(sysmem, 0x1fe00000,
-                   0, s->periph_freq, serial_hds[0],
-                   s->intc.irqs[SCI1_ERI],
-                   s->intc.irqs[SCI1_RXI],
-                   s->intc.irqs[SCI1_TXI],
-                   s->intc.irqs[SCI1_TEI],
-                   NULL);
-    sh_serial_init(sysmem, 0x1fe80000,
-                   SH_SERIAL_FEAT_SCIF,
-                   s->periph_freq, serial_hds[1],
-                   s->intc.irqs[SCIF_ERI],
-                   s->intc.irqs[SCIF_RXI],
-                   s->intc.irqs[SCIF_TXI],
-                   NULL,
-                   s->intc.irqs[SCIF_BRI]);
-
-    tmu012_init(sysmem, 0x1fd80000,
-               TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
-               s->periph_freq,
-               s->intc.irqs[TMU0],
-               s->intc.irqs[TMU1],
-               s->intc.irqs[TMU2_TUNI],
-               s->intc.irqs[TMU2_TICPI]);
-
-    if (cpu->id & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
-        sh_intc_register_sources(&s->intc,
-                                _INTC_ARRAY(vectors_dma4),
-                                _INTC_ARRAY(groups_dma4));
-    }
-
-    if (cpu->id & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
-        sh_intc_register_sources(&s->intc,
-                                _INTC_ARRAY(vectors_dma8),
-                                _INTC_ARRAY(groups_dma8));
-    }
-
-    if (cpu->id & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
-        sh_intc_register_sources(&s->intc,
-                                _INTC_ARRAY(vectors_tmu34),
-                                NULL, 0);
-        tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq,
-                   s->intc.irqs[TMU3],
-                   s->intc.irqs[TMU4],
-                   NULL, NULL);
-    }
-
-    if (cpu->id & (SH_CPU_SH7751_ALL)) {
-        sh_intc_register_sources(&s->intc,
-                                _INTC_ARRAY(vectors_pci),
-                                _INTC_ARRAY(groups_pci));
-    }
-
-    if (cpu->id & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
-        sh_intc_register_sources(&s->intc,
-                                _INTC_ARRAY(vectors_irlm),
-                                NULL, 0);
-    }
-
-    sh_intc_register_sources(&s->intc,
-                               _INTC_ARRAY(vectors_irl),
-                               _INTC_ARRAY(groups_irl));
-    return s;
-}
-
-qemu_irq sh7750_irl(SH7750State *s)
-{
-    sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
-    return qemu_allocate_irqs(sh_intc_set_irl, sh_intc_source(&s->intc, IRL),
-                               1)[0];
-}
diff --git a/hw/sh7750_regnames.c b/hw/sh7750_regnames.c
deleted file mode 100644 (file)
index 5a5a2d8..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#include "hw.h"
-#include "sh.h"
-#include "sh7750_regs.h"
-#include "sh7750_regnames.h"
-
-#define REGNAME(r) {r, #r},
-
-typedef struct {
-    uint32_t regaddr;
-    const char *regname;
-} regname_t;
-
-static regname_t regnames[] = {
-    REGNAME(SH7750_PTEH_A7)
-       REGNAME(SH7750_PTEL_A7)
-       REGNAME(SH7750_PTEA_A7)
-       REGNAME(SH7750_TTB_A7)
-       REGNAME(SH7750_TEA_A7)
-       REGNAME(SH7750_MMUCR_A7)
-       REGNAME(SH7750_CCR_A7)
-       REGNAME(SH7750_QACR0_A7)
-       REGNAME(SH7750_QACR1_A7)
-       REGNAME(SH7750_TRA_A7)
-       REGNAME(SH7750_EXPEVT_A7)
-       REGNAME(SH7750_INTEVT_A7)
-       REGNAME(SH7750_STBCR_A7)
-       REGNAME(SH7750_STBCR2_A7)
-       REGNAME(SH7750_FRQCR_A7)
-       REGNAME(SH7750_WTCNT_A7)
-       REGNAME(SH7750_WTCSR_A7)
-       REGNAME(SH7750_R64CNT_A7)
-       REGNAME(SH7750_RSECCNT_A7)
-       REGNAME(SH7750_RMINCNT_A7)
-       REGNAME(SH7750_RHRCNT_A7)
-       REGNAME(SH7750_RWKCNT_A7)
-       REGNAME(SH7750_RDAYCNT_A7)
-       REGNAME(SH7750_RMONCNT_A7)
-       REGNAME(SH7750_RYRCNT_A7)
-       REGNAME(SH7750_RSECAR_A7)
-       REGNAME(SH7750_RMINAR_A7)
-       REGNAME(SH7750_RHRAR_A7)
-       REGNAME(SH7750_RWKAR_A7)
-       REGNAME(SH7750_RDAYAR_A7)
-       REGNAME(SH7750_RMONAR_A7)
-       REGNAME(SH7750_RCR1_A7)
-       REGNAME(SH7750_RCR2_A7)
-       REGNAME(SH7750_BCR1_A7)
-       REGNAME(SH7750_BCR2_A7)
-       REGNAME(SH7750_WCR1_A7)
-       REGNAME(SH7750_WCR2_A7)
-       REGNAME(SH7750_WCR3_A7)
-       REGNAME(SH7750_MCR_A7)
-       REGNAME(SH7750_PCR_A7)
-       REGNAME(SH7750_RTCSR_A7)
-       REGNAME(SH7750_RTCNT_A7)
-       REGNAME(SH7750_RTCOR_A7)
-       REGNAME(SH7750_RFCR_A7)
-       REGNAME(SH7750_SAR0_A7)
-       REGNAME(SH7750_SAR1_A7)
-       REGNAME(SH7750_SAR2_A7)
-       REGNAME(SH7750_SAR3_A7)
-       REGNAME(SH7750_DAR0_A7)
-       REGNAME(SH7750_DAR1_A7)
-       REGNAME(SH7750_DAR2_A7)
-       REGNAME(SH7750_DAR3_A7)
-       REGNAME(SH7750_DMATCR0_A7)
-       REGNAME(SH7750_DMATCR1_A7)
-       REGNAME(SH7750_DMATCR2_A7)
-       REGNAME(SH7750_DMATCR3_A7)
-       REGNAME(SH7750_CHCR0_A7)
-       REGNAME(SH7750_CHCR1_A7)
-       REGNAME(SH7750_CHCR2_A7)
-       REGNAME(SH7750_CHCR3_A7)
-       REGNAME(SH7750_DMAOR_A7)
-       REGNAME(SH7750_PCTRA_A7)
-       REGNAME(SH7750_PDTRA_A7)
-       REGNAME(SH7750_PCTRB_A7)
-       REGNAME(SH7750_PDTRB_A7)
-       REGNAME(SH7750_GPIOIC_A7)
-       REGNAME(SH7750_ICR_A7)
-       REGNAME(SH7750_BCR3_A7)
-       REGNAME(SH7750_BCR4_A7)
-       REGNAME(SH7750_SDMR2_A7)
-       REGNAME(SH7750_SDMR3_A7) {(uint32_t) - 1, NULL}
-};
-
-const char *regname(uint32_t addr)
-{
-    unsigned int i;
-
-    for (i = 0; regnames[i].regaddr != (uint32_t) - 1; i++) {
-       if (regnames[i].regaddr == addr)
-           return regnames[i].regname;
-    }
-
-    return "<unknown reg>";
-}
index c3f77d5092ca284f9af10cb646b7940c0bcf1d36..9e64e4d353cb4db6e866107ad95f863d933518f9 100644 (file)
@@ -8,9 +8,9 @@
  * This code is licensed under the GPL.
  */
 
-#include "sh_intc.h"
-#include "hw.h"
-#include "sh.h"
+#include "hw/sh_intc.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
 
 //#define DEBUG_INTC
 //#define DEBUG_INTC_SOURCES
index 6f11beedddb1b95ec4bf2eb2b24972bae008d966..b7ddcb096a81b6dc9934023867fce547279c018f 100644 (file)
@@ -2,7 +2,7 @@
 #define __SH_INTC_H__
 
 #include "qemu-common.h"
-#include "irq.h"
+#include "hw/irq.h"
 #include "exec/address-spaces.h"
 
 typedef unsigned char intc_enum;
index 077d95700340dde9d423eccc04260243eb9ddb73..96535dbe018cd8647002ff92f94d89f7516a1d09 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "sysbus.h"
-#include "sh.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
+#include "hw/sysbus.h"
+#include "hw/sh.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
 #include "qemu/bswap.h"
 #include "exec/address-spaces.h"
 
index 21c5b1362d1da305f02166821e8438111ed7d953..40e797c5a234886bb90382df67bf7536efd33a5a 100644 (file)
@@ -24,8 +24,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "sh.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
 #include "char/char.h"
 #include "exec/address-spaces.h"
 
index 64ea23fce65ab0e2681b511574c361448a64b188..b4503230a9ed82f1d27de15e8677e9b2b149efb2 100644 (file)
@@ -8,11 +8,11 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw.h"
-#include "sh.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
 #include "qemu/timer.h"
 #include "exec/address-spaces.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
 //#define DEBUG_TIMER
 
diff --git a/hw/shix.c b/hw/shix.c
deleted file mode 100644 (file)
index 6f2d55a..0000000
--- a/hw/shix.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * SHIX 2.0 board description
- *
- * Copyright (c) 2005 Samuel Tardieu
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-/*
-   Shix 2.0 board by Alexis Polti, described at
-   http://perso.enst.fr/~polti/realisations/shix20/
-
-   More information in target-sh4/README.sh4
-*/
-#include "hw.h"
-#include "sh.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "loader.h"
-#include "exec/address-spaces.h"
-
-#define BIOS_FILENAME "shix_bios.bin"
-#define BIOS_ADDRESS 0xA0000000
-
-static void shix_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    int ret;
-    CPUSH4State *env;
-    struct SH7750State *s;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *rom = g_new(MemoryRegion, 1);
-    MemoryRegion *sdram = g_new(MemoryRegion, 2);
-    
-    if (!cpu_model)
-        cpu_model = "any";
-
-    printf("Initializing CPU\n");
-    env = cpu_init(cpu_model);
-
-    /* Allocate memory space */
-    printf("Allocating ROM\n");
-    memory_region_init_ram(rom, "shix.rom", 0x4000);
-    vmstate_register_ram_global(rom);
-    memory_region_set_readonly(rom, true);
-    memory_region_add_subregion(sysmem, 0x00000000, rom);
-    printf("Allocating SDRAM 1\n");
-    memory_region_init_ram(&sdram[0], "shix.sdram1", 0x01000000);
-    vmstate_register_ram_global(&sdram[0]);
-    memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]);
-    printf("Allocating SDRAM 2\n");
-    memory_region_init_ram(&sdram[1], "shix.sdram2", 0x01000000);
-    vmstate_register_ram_global(&sdram[1]);
-    memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
-
-    /* Load BIOS in 0 (and access it through P2, 0xA0000000) */
-    if (bios_name == NULL)
-        bios_name = BIOS_FILENAME;
-    printf("%s: load BIOS '%s'\n", __func__, bios_name);
-    ret = load_image_targphys(bios_name, 0, 0x4000);
-    if (ret < 0) {             /* Check bios size */
-       fprintf(stderr, "ret=%d\n", ret);
-       fprintf(stderr, "qemu: could not load SHIX bios '%s'\n",
-               bios_name);
-       exit(1);
-    }
-
-    /* Register peripherals */
-    s = sh7750_init(env, sysmem);
-    /* XXXXX Check success */
-    tc58128_init(s, "shix_linux_nand.bin", NULL);
-    fprintf(stderr, "initialization terminated\n");
-}
-
-static QEMUMachine shix_machine = {
-    .name = "shix",
-    .desc = "shix card",
-    .init = shix_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void shix_machine_init(void)
-{
-    qemu_register_machine(&shix_machine);
-}
-
-machine_init(shix_machine_init);
index 136ceebc80312c3e108afe56cb1c955e2dfcaede..b60592b35d363c2522654a563c1456dc3c098f35 100644 (file)
@@ -22,9 +22,9 @@
  * THE SOFTWARE.
  */
 
-#include "sun4m.h"
+#include "hw/sun4m.h"
 #include "monitor/monitor.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 //#define DEBUG_IRQ_COUNT
index af24cc1ae82d81101d19ec84d56db760dbff6106..a7a93688646c27b0d8b0fe9d913598a05c278892 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 #include "sysemu/sysemu.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /*
index 68a4c0cca46d4d7937ca95da422886b7dcdac8db..83f22a03668faea8f8c80e8a7de9d416ccfaa911 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "sun4m.h"
+#include "hw/sun4m.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
-#include "sysbus.h"
+#include "hw/ptimer.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /*
index b7ac7f9bffc8f0fa34ac51d1584543818b28286f..0e019111bbf9c4f4fd5d710f16ac57027427282e 100644 (file)
  */
 
 #include <stdio.h>
-#include "hw.h"
-#include "serial.h"
+#include "hw/hw.h"
+#include "hw/serial.h"
 #include "ui/console.h"
-#include "devices.h"
-#include "sysbus.h"
-#include "qdev-addr.h"
+#include "hw/devices.h"
+#include "hw/sysbus.h"
+#include "hw/qdev-addr.h"
 #include "qemu/range.h"
 #include "ui/pixel_ops.h"
 
@@ -1171,28 +1171,28 @@ typedef void draw_hwc_line_func(SM501State * s, int crt, uint8_t * palette,
                                 int c_y, uint8_t *d, int width);
 
 #define DEPTH 8
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define DEPTH 15
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 15
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define DEPTH 16
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 16
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define DEPTH 32
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 32
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 static draw_line_func * draw_line8_funcs[] = {
     draw_line8_8,
diff --git a/hw/smbios.c b/hw/smbios.c
deleted file mode 100644 (file)
index a7b8bfc..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * SMBIOS Support
- *
- * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
- *
- * Authors:
- *  Alex Williamson <alex.williamson@hp.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 "sysemu/sysemu.h"
-#include "smbios.h"
-#include "loader.h"
-
-/*
- * Structures shared with the BIOS
- */
-struct smbios_header {
-    uint16_t length;
-    uint8_t type;
-} QEMU_PACKED;
-
-struct smbios_field {
-    struct smbios_header header;
-    uint8_t type;
-    uint16_t offset;
-    uint8_t data[];
-} QEMU_PACKED;
-
-struct smbios_table {
-    struct smbios_header header;
-    uint8_t data[];
-} QEMU_PACKED;
-
-#define SMBIOS_FIELD_ENTRY 0
-#define SMBIOS_TABLE_ENTRY 1
-
-
-static uint8_t *smbios_entries;
-static size_t smbios_entries_len;
-static int smbios_type4_count = 0;
-
-static void smbios_validate_table(void)
-{
-    if (smbios_type4_count && smbios_type4_count != smp_cpus) {
-         fprintf(stderr,
-                 "Number of SMBIOS Type 4 tables must match cpu count.\n");
-        exit(1);
-    }
-}
-
-uint8_t *smbios_get_table(size_t *length)
-{
-    smbios_validate_table();
-    *length = smbios_entries_len;
-    return smbios_entries;
-}
-
-/*
- * To avoid unresolvable overlaps in data, don't allow both
- * tables and fields for the same smbios type.
- */
-static void smbios_check_collision(int type, int entry)
-{
-    uint16_t *num_entries = (uint16_t *)smbios_entries;
-    struct smbios_header *header;
-    char *p;
-    int i;
-
-    if (!num_entries)
-        return;
-
-    p = (char *)(num_entries + 1);
-
-    for (i = 0; i < *num_entries; i++) {
-        header = (struct smbios_header *)p;
-        if (entry == SMBIOS_TABLE_ENTRY && header->type == SMBIOS_FIELD_ENTRY) {
-            struct smbios_field *field = (void *)header;
-            if (type == field->type) {
-                fprintf(stderr, "SMBIOS type %d field already defined, "
-                                "cannot add table\n", type);
-                exit(1);
-            }
-        } else if (entry == SMBIOS_FIELD_ENTRY &&
-                   header->type == SMBIOS_TABLE_ENTRY) {
-            struct smbios_structure_header *table = (void *)(header + 1);
-            if (type == table->type) {
-                fprintf(stderr, "SMBIOS type %d table already defined, "
-                                "cannot add field\n", type);
-                exit(1);
-            }
-        }
-        p += le16_to_cpu(header->length);
-    }
-}
-
-void smbios_add_field(int type, int offset, int len, void *data)
-{
-    struct smbios_field *field;
-
-    smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
-
-    if (!smbios_entries) {
-        smbios_entries_len = sizeof(uint16_t);
-        smbios_entries = g_malloc0(smbios_entries_len);
-    }
-    smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
-                                                  sizeof(*field) + len);
-    field = (struct smbios_field *)(smbios_entries + smbios_entries_len);
-    field->header.type = SMBIOS_FIELD_ENTRY;
-    field->header.length = cpu_to_le16(sizeof(*field) + len);
-
-    field->type = type;
-    field->offset = cpu_to_le16(offset);
-    memcpy(field->data, data, len);
-
-    smbios_entries_len += sizeof(*field) + len;
-    (*(uint16_t *)smbios_entries) =
-            cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
-}
-
-static void smbios_build_type_0_fields(const char *t)
-{
-    char buf[1024];
-
-    if (get_param_value(buf, sizeof(buf), "vendor", t))
-        smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "version", t))
-        smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "date", t))
-        smbios_add_field(0, offsetof(struct smbios_type_0,
-                                     bios_release_date_str),
-                                     strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "release", t)) {
-        int major, minor;
-        sscanf(buf, "%d.%d", &major, &minor);
-        smbios_add_field(0, offsetof(struct smbios_type_0,
-                                     system_bios_major_release), 1, &major);
-        smbios_add_field(0, offsetof(struct smbios_type_0,
-                                     system_bios_minor_release), 1, &minor);
-    }
-}
-
-static void smbios_build_type_1_fields(const char *t)
-{
-    char buf[1024];
-
-    if (get_param_value(buf, sizeof(buf), "manufacturer", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "product", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "version", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "serial", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "uuid", t)) {
-        if (qemu_uuid_parse(buf, qemu_uuid) != 0) {
-            fprintf(stderr, "Invalid SMBIOS UUID string\n");
-            exit(1);
-        }
-    }
-    if (get_param_value(buf, sizeof(buf), "sku", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "family", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
-                         strlen(buf) + 1, buf);
-}
-
-int smbios_entry_add(const char *t)
-{
-    char buf[1024];
-
-    if (get_param_value(buf, sizeof(buf), "file", t)) {
-        struct smbios_structure_header *header;
-        struct smbios_table *table;
-        int size = get_image_size(buf);
-
-        if (size == -1 || size < sizeof(struct smbios_structure_header)) {
-            fprintf(stderr, "Cannot read smbios file %s\n", buf);
-            exit(1);
-        }
-
-        if (!smbios_entries) {
-            smbios_entries_len = sizeof(uint16_t);
-            smbios_entries = g_malloc0(smbios_entries_len);
-        }
-
-        smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
-                                                      sizeof(*table) + size);
-        table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
-        table->header.type = SMBIOS_TABLE_ENTRY;
-        table->header.length = cpu_to_le16(sizeof(*table) + size);
-
-        if (load_image(buf, table->data) != size) {
-            fprintf(stderr, "Failed to load smbios file %s", buf);
-            exit(1);
-        }
-
-        header = (struct smbios_structure_header *)(table->data);
-        smbios_check_collision(header->type, SMBIOS_TABLE_ENTRY);
-        if (header->type == 4) {
-            smbios_type4_count++;
-        }
-
-        smbios_entries_len += sizeof(*table) + size;
-        (*(uint16_t *)smbios_entries) =
-                cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
-        return 0;
-    }
-
-    if (get_param_value(buf, sizeof(buf), "type", t)) {
-        unsigned long type = strtoul(buf, NULL, 0);
-        switch (type) {
-        case 0:
-            smbios_build_type_0_fields(t);
-            return 0;
-        case 1:
-            smbios_build_type_1_fields(t);
-            return 0;
-        default:
-            fprintf(stderr, "Don't know how to build fields for SMBIOS type "
-                    "%ld\n", type);
-            exit(1);
-        }
-    }
-
-    fprintf(stderr, "smbios: must specify type= or file=\n");
-    return -1;
-}
index a9085915906f04867316d5e4965fa95df33cec89..9626415bcaab73c781499f2e3adf260590438db9 100644 (file)
@@ -9,9 +9,9 @@
 
 /* TODO: Implement PEC.  */
 
-#include "hw.h"
-#include "i2c.h"
-#include "smbus.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
+#include "hw/smbus.h"
 
 //#define DEBUG_SMBUS 1
 
index 6ed45bd03d9a2446d29a68b929956ec9ffbcf1f0..c3db620e00cb8f6d69ea70801b743f2e61c5696a 100644 (file)
@@ -25,7 +25,7 @@
  * THE SOFTWARE.
  */
 
-#include "i2c.h"
+#include "hw/i2c.h"
 
 #define TYPE_SMBUS_DEVICE "smbus-device"
 #define SMBUS_DEVICE(obj) \
index d36dc7bbe3e34680c6b1318d6e712a343cfa1d5b..dff8403d6ce90e864db134d4b426ed309b0fc7dd 100644 (file)
@@ -22,9 +22,9 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "i2c.h"
-#include "smbus.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
+#include "hw/smbus.h"
 
 //#define DEBUG
 
index 16db3a743cfae92b8a4d7980d3525832bdde54f2..732ebd3bb0a41c3e86be786e014e61582ce828d6 100644 (file)
  * GNU GPL, version 2 or (at your option) any later version.
  *
  */
-#include "hw.h"
-#include "pc.h"
-#include "pm_smbus.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pm_smbus.h"
+#include "hw/pci/pci.h"
 #include "sysemu/sysemu.h"
-#include "i2c.h"
-#include "smbus.h"
+#include "hw/i2c.h"
+#include "hw/smbus.h"
 
-#include "ich9.h"
+#include "hw/ich9.h"
 
 #define TYPE_ICH9_SMB_DEVICE "ICH9 SMB"
 #define ICH9_SMB_DEVICE(obj) \
index 67fd074d85c287f7a9ee2215e7b3fddc145fb1fa..c2feae6eb8e905690d118e17a5a3ad0afb355591 100644 (file)
@@ -7,9 +7,9 @@
  * This code is licensed under the GPL
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
-#include "devices.h"
+#include "hw/devices.h"
 /* For crc32 */
 #include <zlib.h>
 
index 64e8ee1d13517cfa74e75ae4bf65b952a2eecd96..db5d60938898b14fa195d35af8c1b2f38d6e9541 100644 (file)
@@ -19,7 +19,7 @@
  */
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "soc_dma.h"
+#include "hw/soc_dma.h"
 
 static void transfer_mem2mem(struct soc_dma_ch_s *ch)
 {
diff --git a/hw/spapr.c b/hw/spapr.c
deleted file mode 100644 (file)
index fadf70f..0000000
+++ /dev/null
@@ -1,964 +0,0 @@
-/*
- * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
- *
- * Copyright (c) 2004-2007 Fabrice Bellard
- * Copyright (c) 2007 Jocelyn Mayer
- * Copyright (c) 2010 David Gibson, IBM Corporation.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-#include "sysemu/sysemu.h"
-#include "hw.h"
-#include "elf.h"
-#include "net/net.h"
-#include "sysemu/blockdev.h"
-#include "sysemu/cpus.h"
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
-
-#include "hw/boards.h"
-#include "hw/ppc.h"
-#include "hw/loader.h"
-
-#include "hw/spapr.h"
-#include "hw/spapr_vio.h"
-#include "hw/spapr_pci.h"
-#include "hw/xics.h"
-#include "hw/pci/msi.h"
-
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
-#include "pci/pci.h"
-
-#include "exec/address-spaces.h"
-#include "hw/usb.h"
-#include "qemu/config-file.h"
-
-#include <libfdt.h>
-
-/* SLOF memory layout:
- *
- * SLOF raw image loaded at 0, copies its romfs right below the flat
- * device-tree, then position SLOF itself 31M below that
- *
- * So we set FW_OVERHEAD to 40MB which should account for all of that
- * and more
- *
- * We load our kernel at 4M, leaving space for SLOF initial image
- */
-#define FDT_MAX_SIZE            0x10000
-#define RTAS_MAX_SIZE           0x10000
-#define FW_MAX_SIZE             0x400000
-#define FW_FILE_NAME            "slof.bin"
-#define FW_OVERHEAD             0x2800000
-#define KERNEL_LOAD_ADDR        FW_MAX_SIZE
-
-#define MIN_RMA_SLOF            128UL
-
-#define TIMEBASE_FREQ           512000000ULL
-
-#define MAX_CPUS                256
-#define XICS_IRQS               1024
-
-#define PHANDLE_XICP            0x00001111
-
-#define HTAB_SIZE(spapr)        (1ULL << ((spapr)->htab_shift))
-
-sPAPREnvironment *spapr;
-
-int spapr_allocate_irq(int hint, bool lsi)
-{
-    int irq;
-
-    if (hint) {
-        irq = hint;
-        /* FIXME: we should probably check for collisions somehow */
-    } else {
-        irq = spapr->next_irq++;
-    }
-
-    /* Configure irq type */
-    if (!xics_get_qirq(spapr->icp, irq)) {
-        return 0;
-    }
-
-    xics_set_irq_type(spapr->icp, irq, lsi);
-
-    return irq;
-}
-
-/* Allocate block of consequtive IRQs, returns a number of the first */
-int spapr_allocate_irq_block(int num, bool lsi)
-{
-    int first = -1;
-    int i;
-
-    for (i = 0; i < num; ++i) {
-        int irq;
-
-        irq = spapr_allocate_irq(0, lsi);
-        if (!irq) {
-            return -1;
-        }
-
-        if (0 == i) {
-            first = irq;
-        }
-
-        /* If the above doesn't create a consecutive block then that's
-         * an internal bug */
-        assert(irq == (first + i));
-    }
-
-    return first;
-}
-
-static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
-{
-    int ret = 0, offset;
-    CPUPPCState *env;
-    CPUState *cpu;
-    char cpu_model[32];
-    int smt = kvmppc_smt_threads();
-    uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
-
-    assert(spapr->cpu_model);
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
-        uint32_t associativity[] = {cpu_to_be32(0x5),
-                                    cpu_to_be32(0x0),
-                                    cpu_to_be32(0x0),
-                                    cpu_to_be32(0x0),
-                                    cpu_to_be32(cpu->numa_node),
-                                    cpu_to_be32(cpu->cpu_index)};
-
-        if ((cpu->cpu_index % smt) != 0) {
-            continue;
-        }
-
-        snprintf(cpu_model, 32, "/cpus/%s@%x", spapr->cpu_model,
-                 cpu->cpu_index);
-
-        offset = fdt_path_offset(fdt, cpu_model);
-        if (offset < 0) {
-            return offset;
-        }
-
-        if (nb_numa_nodes > 1) {
-            ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
-                              sizeof(associativity));
-            if (ret < 0) {
-                return ret;
-            }
-        }
-
-        ret = fdt_setprop(fdt, offset, "ibm,pft-size",
-                          pft_size_prop, sizeof(pft_size_prop));
-        if (ret < 0) {
-            return ret;
-        }
-    }
-    return ret;
-}
-
-
-static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
-                                     size_t maxsize)
-{
-    size_t maxcells = maxsize / sizeof(uint32_t);
-    int i, j, count;
-    uint32_t *p = prop;
-
-    for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
-        struct ppc_one_seg_page_size *sps = &env->sps.sps[i];
-
-        if (!sps->page_shift) {
-            break;
-        }
-        for (count = 0; count < PPC_PAGE_SIZES_MAX_SZ; count++) {
-            if (sps->enc[count].page_shift == 0) {
-                break;
-            }
-        }
-        if ((p - prop) >= (maxcells - 3 - count * 2)) {
-            break;
-        }
-        *(p++) = cpu_to_be32(sps->page_shift);
-        *(p++) = cpu_to_be32(sps->slb_enc);
-        *(p++) = cpu_to_be32(count);
-        for (j = 0; j < count; j++) {
-            *(p++) = cpu_to_be32(sps->enc[j].page_shift);
-            *(p++) = cpu_to_be32(sps->enc[j].pte_enc);
-        }
-    }
-
-    return (p - prop) * sizeof(uint32_t);
-}
-
-#define _FDT(exp) \
-    do { \
-        int ret = (exp);                                           \
-        if (ret < 0) {                                             \
-            fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
-                    #exp, fdt_strerror(ret));                      \
-            exit(1);                                               \
-        }                                                          \
-    } while (0)
-
-
-static void *spapr_create_fdt_skel(const char *cpu_model,
-                                   hwaddr initrd_base,
-                                   hwaddr initrd_size,
-                                   hwaddr kernel_size,
-                                   const char *boot_device,
-                                   const char *kernel_cmdline,
-                                   uint32_t epow_irq)
-{
-    void *fdt;
-    CPUPPCState *env;
-    uint32_t start_prop = cpu_to_be32(initrd_base);
-    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
-    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
-        "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
-    char qemu_hypertas_prop[] = "hcall-memop1";
-    uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
-    uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
-    char *modelname;
-    int i, smt = kvmppc_smt_threads();
-    unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
-
-    fdt = g_malloc0(FDT_MAX_SIZE);
-    _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
-
-    if (kernel_size) {
-        _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR, kernel_size)));
-    }
-    if (initrd_size) {
-        _FDT((fdt_add_reservemap_entry(fdt, initrd_base, initrd_size)));
-    }
-    _FDT((fdt_finish_reservemap(fdt)));
-
-    /* Root node */
-    _FDT((fdt_begin_node(fdt, "")));
-    _FDT((fdt_property_string(fdt, "device_type", "chrp")));
-    _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
-    _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
-
-    _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
-    _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
-
-    /* /chosen */
-    _FDT((fdt_begin_node(fdt, "chosen")));
-
-    /* Set Form1_affinity */
-    _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
-
-    _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));
-    _FDT((fdt_property(fdt, "linux,initrd-start",
-                       &start_prop, sizeof(start_prop))));
-    _FDT((fdt_property(fdt, "linux,initrd-end",
-                       &end_prop, sizeof(end_prop))));
-    if (kernel_size) {
-        uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
-                              cpu_to_be64(kernel_size) };
-
-        _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
-    }
-    if (boot_device) {
-        _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
-    }
-    _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
-    _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
-    _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
-
-    _FDT((fdt_end_node(fdt)));
-
-    /* cpus */
-    _FDT((fdt_begin_node(fdt, "cpus")));
-
-    _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
-    _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
-
-    modelname = g_strdup(cpu_model);
-
-    for (i = 0; i < strlen(modelname); i++) {
-        modelname[i] = toupper(modelname[i]);
-    }
-
-    /* This is needed during FDT finalization */
-    spapr->cpu_model = g_strdup(modelname);
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        CPUState *cpu = CPU(ppc_env_get_cpu(env));
-        int index = cpu->cpu_index;
-        uint32_t servers_prop[smp_threads];
-        uint32_t gservers_prop[smp_threads * 2];
-        char *nodename;
-        uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
-                           0xffffffff, 0xffffffff};
-        uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;
-        uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
-        uint32_t page_sizes_prop[64];
-        size_t page_sizes_prop_size;
-
-        if ((index % smt) != 0) {
-            continue;
-        }
-
-        nodename = g_strdup_printf("%s@%x", modelname, index);
-
-        _FDT((fdt_begin_node(fdt, nodename)));
-
-        g_free(nodename);
-
-        _FDT((fdt_property_cell(fdt, "reg", index)));
-        _FDT((fdt_property_string(fdt, "device_type", "cpu")));
-
-        _FDT((fdt_property_cell(fdt, "cpu-version", env->spr[SPR_PVR])));
-        _FDT((fdt_property_cell(fdt, "dcache-block-size",
-                                env->dcache_line_size)));
-        _FDT((fdt_property_cell(fdt, "icache-block-size",
-                                env->icache_line_size)));
-        _FDT((fdt_property_cell(fdt, "timebase-frequency", tbfreq)));
-        _FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));
-        _FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));
-        _FDT((fdt_property_string(fdt, "status", "okay")));
-        _FDT((fdt_property(fdt, "64-bit", NULL, 0)));
-
-        /* Build interrupt servers and gservers properties */
-        for (i = 0; i < smp_threads; i++) {
-            servers_prop[i] = cpu_to_be32(index + i);
-            /* Hack, direct the group queues back to cpu 0 */
-            gservers_prop[i*2] = cpu_to_be32(index + i);
-            gservers_prop[i*2 + 1] = 0;
-        }
-        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-server#s",
-                           servers_prop, sizeof(servers_prop))));
-        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
-                           gservers_prop, sizeof(gservers_prop))));
-
-        if (env->mmu_model & POWERPC_MMU_1TSEG) {
-            _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
-                               segs, sizeof(segs))));
-        }
-
-        /* Advertise VMX/VSX (vector extensions) if available
-         *   0 / no property == no vector extensions
-         *   1               == VMX / Altivec available
-         *   2               == VSX available */
-        if (env->insns_flags & PPC_ALTIVEC) {
-            uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
-
-            _FDT((fdt_property_cell(fdt, "ibm,vmx", vmx)));
-        }
-
-        /* Advertise DFP (Decimal Floating Point) if available
-         *   0 / no property == no DFP
-         *   1               == DFP available */
-        if (env->insns_flags2 & PPC2_DFP) {
-            _FDT((fdt_property_cell(fdt, "ibm,dfp", 1)));
-        }
-
-        page_sizes_prop_size = create_page_sizes_prop(env, page_sizes_prop,
-                                                      sizeof(page_sizes_prop));
-        if (page_sizes_prop_size) {
-            _FDT((fdt_property(fdt, "ibm,segment-page-sizes",
-                               page_sizes_prop, page_sizes_prop_size)));
-        }
-
-        _FDT((fdt_end_node(fdt)));
-    }
-
-    g_free(modelname);
-
-    _FDT((fdt_end_node(fdt)));
-
-    /* RTAS */
-    _FDT((fdt_begin_node(fdt, "rtas")));
-
-    _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop,
-                       sizeof(hypertas_prop))));
-    _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas_prop,
-                       sizeof(qemu_hypertas_prop))));
-
-    _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
-        refpoints, sizeof(refpoints))));
-
-    _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
-
-    _FDT((fdt_end_node(fdt)));
-
-    /* interrupt controller */
-    _FDT((fdt_begin_node(fdt, "interrupt-controller")));
-
-    _FDT((fdt_property_string(fdt, "device_type",
-                              "PowerPC-External-Interrupt-Presentation")));
-    _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
-    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
-    _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
-                       interrupt_server_ranges_prop,
-                       sizeof(interrupt_server_ranges_prop))));
-    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
-    _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
-    _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
-
-    _FDT((fdt_end_node(fdt)));
-
-    /* vdevice */
-    _FDT((fdt_begin_node(fdt, "vdevice")));
-
-    _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
-    _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
-    _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
-    _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
-    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
-    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
-
-    _FDT((fdt_end_node(fdt)));
-
-    /* event-sources */
-    spapr_events_fdt_skel(fdt, epow_irq);
-
-    _FDT((fdt_end_node(fdt))); /* close root node */
-    _FDT((fdt_finish(fdt)));
-
-    return fdt;
-}
-
-static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
-{
-    uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
-                                cpu_to_be32(0x0), cpu_to_be32(0x0),
-                                cpu_to_be32(0x0)};
-    char mem_name[32];
-    hwaddr node0_size, mem_start;
-    uint64_t mem_reg_property[2];
-    int i, off;
-
-    /* memory node(s) */
-    node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
-    if (spapr->rma_size > node0_size) {
-        spapr->rma_size = node0_size;
-    }
-
-    /* RMA */
-    mem_reg_property[0] = 0;
-    mem_reg_property[1] = cpu_to_be64(spapr->rma_size);
-    off = fdt_add_subnode(fdt, 0, "memory@0");
-    _FDT(off);
-    _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
-    _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
-                      sizeof(mem_reg_property))));
-    _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
-                      sizeof(associativity))));
-
-    /* RAM: Node 0 */
-    if (node0_size > spapr->rma_size) {
-        mem_reg_property[0] = cpu_to_be64(spapr->rma_size);
-        mem_reg_property[1] = cpu_to_be64(node0_size - spapr->rma_size);
-
-        sprintf(mem_name, "memory@" TARGET_FMT_lx, spapr->rma_size);
-        off = fdt_add_subnode(fdt, 0, mem_name);
-        _FDT(off);
-        _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
-        _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
-                          sizeof(mem_reg_property))));
-        _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
-                          sizeof(associativity))));
-    }
-
-    /* RAM: Node 1 and beyond */
-    mem_start = node0_size;
-    for (i = 1; i < nb_numa_nodes; i++) {
-        mem_reg_property[0] = cpu_to_be64(mem_start);
-        mem_reg_property[1] = cpu_to_be64(node_mem[i]);
-        associativity[3] = associativity[4] = cpu_to_be32(i);
-        sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
-        off = fdt_add_subnode(fdt, 0, mem_name);
-        _FDT(off);
-        _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
-        _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
-                          sizeof(mem_reg_property))));
-        _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
-                          sizeof(associativity))));
-        mem_start += node_mem[i];
-    }
-
-    return 0;
-}
-
-static void spapr_finalize_fdt(sPAPREnvironment *spapr,
-                               hwaddr fdt_addr,
-                               hwaddr rtas_addr,
-                               hwaddr rtas_size)
-{
-    int ret;
-    void *fdt;
-    sPAPRPHBState *phb;
-
-    fdt = g_malloc(FDT_MAX_SIZE);
-
-    /* open out the base tree into a temp buffer for the final tweaks */
-    _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE)));
-
-    ret = spapr_populate_memory(spapr, fdt);
-    if (ret < 0) {
-        fprintf(stderr, "couldn't setup memory nodes in fdt\n");
-        exit(1);
-    }
-
-    ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
-    if (ret < 0) {
-        fprintf(stderr, "couldn't setup vio devices in fdt\n");
-        exit(1);
-    }
-
-    QLIST_FOREACH(phb, &spapr->phbs, list) {
-        ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt);
-    }
-
-    if (ret < 0) {
-        fprintf(stderr, "couldn't setup PCI devices in fdt\n");
-        exit(1);
-    }
-
-    /* RTAS */
-    ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
-    if (ret < 0) {
-        fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
-    }
-
-    /* Advertise NUMA via ibm,associativity */
-    ret = spapr_fixup_cpu_dt(fdt, spapr);
-    if (ret < 0) {
-        fprintf(stderr, "Couldn't finalize CPU device tree properties\n");
-    }
-
-    if (!spapr->has_graphics) {
-        spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
-    }
-
-    _FDT((fdt_pack(fdt)));
-
-    if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
-        hw_error("FDT too big ! 0x%x bytes (max is 0x%x)\n",
-                 fdt_totalsize(fdt), FDT_MAX_SIZE);
-        exit(1);
-    }
-
-    cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
-
-    g_free(fdt);
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
-}
-
-static void emulate_spapr_hypercall(PowerPCCPU *cpu)
-{
-    CPUPPCState *env = &cpu->env;
-
-    if (msr_pr) {
-        hcall_dprintf("Hypercall made with MSR[PR]=1\n");
-        env->gpr[3] = H_PRIVILEGE;
-    } else {
-        env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]);
-    }
-}
-
-static void spapr_reset_htab(sPAPREnvironment *spapr)
-{
-    long shift;
-
-    /* allocate hash page table.  For now we always make this 16mb,
-     * later we should probably make it scale to the size of guest
-     * RAM */
-
-    shift = kvmppc_reset_htab(spapr->htab_shift);
-
-    if (shift > 0) {
-        /* Kernel handles htab, we don't need to allocate one */
-        spapr->htab_shift = shift;
-    } else {
-        if (!spapr->htab) {
-            /* Allocate an htab if we don't yet have one */
-            spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr));
-        }
-
-        /* And clear it */
-        memset(spapr->htab, 0, HTAB_SIZE(spapr));
-    }
-
-    /* Update the RMA size if necessary */
-    if (spapr->vrma_adjust) {
-        spapr->rma_size = kvmppc_rma_size(ram_size, spapr->htab_shift);
-    }
-}
-
-static void ppc_spapr_reset(void)
-{
-    /* Reset the hash table & recalc the RMA */
-    spapr_reset_htab(spapr);
-
-    qemu_devices_reset();
-
-    /* Load the fdt */
-    spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr,
-                       spapr->rtas_size);
-
-    /* Set up the entry state */
-    first_cpu->gpr[3] = spapr->fdt_addr;
-    first_cpu->gpr[5] = 0;
-    first_cpu->halted = 0;
-    first_cpu->nip = spapr->entry_point;
-
-}
-
-static void spapr_cpu_reset(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-
-    /* All CPUs start halted.  CPU0 is unhalted from the machine level
-     * reset code and the rest are explicitly started up by the guest
-     * using an RTAS call */
-    env->halted = 1;
-
-    env->spr[SPR_HIOR] = 0;
-
-    env->external_htab = spapr->htab;
-    env->htab_base = -1;
-    env->htab_mask = HTAB_SIZE(spapr) - 1;
-    env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
-        (spapr->htab_shift - 18);
-}
-
-static void spapr_create_nvram(sPAPREnvironment *spapr)
-{
-    QemuOpts *machine_opts;
-    DeviceState *dev;
-
-    dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
-
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        const char *drivename;
-
-        drivename = qemu_opt_get(machine_opts, "nvram");
-        if (drivename) {
-            BlockDriverState *bs;
-
-            bs = bdrv_find(drivename);
-            if (!bs) {
-                fprintf(stderr, "No such block device \"%s\" for nvram\n",
-                        drivename);
-                exit(1);
-            }
-            qdev_prop_set_drive_nofail(dev, "drive", bs);
-        }
-    }
-
-    qdev_init_nofail(dev);
-
-    spapr->nvram = (struct sPAPRNVRAM *)dev;
-}
-
-/* Returns whether we want to use VGA or not */
-static int spapr_vga_init(PCIBus *pci_bus)
-{
-    switch (vga_interface_type) {
-    case VGA_NONE:
-    case VGA_STD:
-        return pci_vga_init(pci_bus) != NULL;
-    default:
-        fprintf(stderr, "This vga model is not supported,"
-                "currently it only supports -vga std\n");
-        exit(0);
-        break;
-    }
-}
-
-/* pSeries LPAR / sPAPR hardware init */
-static void ppc_spapr_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    PCIHostState *phb;
-    int i;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    hwaddr rma_alloc_size;
-    uint32_t initrd_base = 0;
-    long kernel_size = 0, initrd_size = 0;
-    long load_limit, rtas_limit, fw_size;
-    char *filename;
-
-    msi_supported = true;
-
-    spapr = g_malloc0(sizeof(*spapr));
-    QLIST_INIT(&spapr->phbs);
-
-    cpu_ppc_hypercall = emulate_spapr_hypercall;
-
-    /* Allocate RMA if necessary */
-    rma_alloc_size = kvmppc_alloc_rma("ppc_spapr.rma", sysmem);
-
-    if (rma_alloc_size == -1) {
-        hw_error("qemu: Unable to create RMA\n");
-        exit(1);
-    }
-
-    if (rma_alloc_size && (rma_alloc_size < ram_size)) {
-        spapr->rma_size = rma_alloc_size;
-    } else {
-        spapr->rma_size = ram_size;
-
-        /* With KVM, we don't actually know whether KVM supports an
-         * unbounded RMA (PR KVM) or is limited by the hash table size
-         * (HV KVM using VRMA), so we always assume the latter
-         *
-         * In that case, we also limit the initial allocations for RTAS
-         * etc... to 256M since we have no way to know what the VRMA size
-         * is going to be as it depends on the size of the hash table
-         * isn't determined yet.
-         */
-        if (kvm_enabled()) {
-            spapr->vrma_adjust = 1;
-            spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
-        }
-    }
-
-    /* We place the device tree and RTAS just below either the top of the RMA,
-     * or just below 2GB, whichever is lowere, so that it can be
-     * processed with 32-bit real mode code if necessary */
-    rtas_limit = MIN(spapr->rma_size, 0x80000000);
-    spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
-    spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
-    load_limit = spapr->fdt_addr - FW_OVERHEAD;
-
-    /* We aim for a hash table of size 1/128 the size of RAM.  The
-     * normal rule of thumb is 1/64 the size of RAM, but that's much
-     * more than needed for the Linux guests we support. */
-    spapr->htab_shift = 18; /* Minimum architected size */
-    while (spapr->htab_shift <= 46) {
-        if ((1ULL << (spapr->htab_shift + 7)) >= ram_size) {
-            break;
-        }
-        spapr->htab_shift++;
-    }
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = kvm_enabled() ? "host" : "POWER7";
-    }
-    for (i = 0; i < smp_cpus; i++) {
-        cpu = cpu_ppc_init(cpu_model);
-        if (cpu == NULL) {
-            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
-            exit(1);
-        }
-        env = &cpu->env;
-
-        /* Set time-base frequency to 512 MHz */
-        cpu_ppc_tb_init(env, TIMEBASE_FREQ);
-
-        /* PAPR always has exception vectors in RAM not ROM */
-        env->hreset_excp_prefix = 0;
-
-        /* Tell KVM that we're in PAPR mode */
-        if (kvm_enabled()) {
-            kvmppc_set_papr(cpu);
-        }
-
-        qemu_register_reset(spapr_cpu_reset, cpu);
-    }
-
-    /* allocate RAM */
-    spapr->ram_limit = ram_size;
-    if (spapr->ram_limit > rma_alloc_size) {
-        ram_addr_t nonrma_base = rma_alloc_size;
-        ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
-
-        memory_region_init_ram(ram, "ppc_spapr.ram", nonrma_size);
-        vmstate_register_ram_global(ram);
-        memory_region_add_subregion(sysmem, nonrma_base, ram);
-    }
-
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
-    spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr,
-                                           rtas_limit - spapr->rtas_addr);
-    if (spapr->rtas_size < 0) {
-        hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
-        exit(1);
-    }
-    if (spapr->rtas_size > RTAS_MAX_SIZE) {
-        hw_error("RTAS too big ! 0x%lx bytes (max is 0x%x)\n",
-                 spapr->rtas_size, RTAS_MAX_SIZE);
-        exit(1);
-    }
-    g_free(filename);
-
-
-    /* Set up Interrupt Controller */
-    spapr->icp = xics_system_init(XICS_IRQS);
-    spapr->next_irq = XICS_IRQ_BASE;
-
-    /* Set up EPOW events infrastructure */
-    spapr_events_init(spapr);
-
-    /* Set up IOMMU */
-    spapr_iommu_init();
-
-    /* Set up VIO bus */
-    spapr->vio_bus = spapr_vio_bus_init();
-
-    for (i = 0; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_hds[i]) {
-            spapr_vty_create(spapr->vio_bus, serial_hds[i]);
-        }
-    }
-
-    /* We always have at least the nvram device on VIO */
-    spapr_create_nvram(spapr);
-
-    /* Set up PCI */
-    spapr_pci_rtas_init();
-
-    phb = spapr_create_phb(spapr, 0, "pci");
-
-    for (i = 0; i < nb_nics; i++) {
-        NICInfo *nd = &nd_table[i];
-
-        if (!nd->model) {
-            nd->model = g_strdup("ibmveth");
-        }
-
-        if (strcmp(nd->model, "ibmveth") == 0) {
-            spapr_vlan_create(spapr->vio_bus, nd);
-        } else {
-            pci_nic_init_nofail(&nd_table[i], nd->model, NULL);
-        }
-    }
-
-    for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
-        spapr_vscsi_create(spapr->vio_bus);
-    }
-
-    /* Graphics */
-    if (spapr_vga_init(phb->bus)) {
-        spapr->has_graphics = true;
-    }
-
-    if (usb_enabled(spapr->has_graphics)) {
-        pci_create_simple(phb->bus, -1, "pci-ohci");
-        if (spapr->has_graphics) {
-            usbdevice_create("keyboard");
-            usbdevice_create("mouse");
-        }
-    }
-
-    if (spapr->rma_size < (MIN_RMA_SLOF << 20)) {
-        fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
-                "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
-        exit(1);
-    }
-
-    if (kernel_filename) {
-        uint64_t lowaddr = 0;
-
-        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
-                               NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename,
-                                              KERNEL_LOAD_ADDR,
-                                              load_limit - KERNEL_LOAD_ADDR);
-        }
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-
-        /* load initrd */
-        if (initrd_filename) {
-            /* Try to locate the initrd in the gap between the kernel
-             * and the firmware. Add a bit of space just in case
-             */
-            initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff;
-            initrd_size = load_image_targphys(initrd_filename, initrd_base,
-                                              load_limit - initrd_base);
-            if (initrd_size < 0) {
-                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                        initrd_filename);
-                exit(1);
-            }
-        } else {
-            initrd_base = 0;
-            initrd_size = 0;
-        }
-    }
-
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
-    fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
-    if (fw_size < 0) {
-        hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
-        exit(1);
-    }
-    g_free(filename);
-
-    spapr->entry_point = 0x100;
-
-    /* Prepare the device tree */
-    spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
-                                            initrd_base, initrd_size,
-                                            kernel_size,
-                                            boot_device, kernel_cmdline,
-                                            spapr->epow_irq);
-    assert(spapr->fdt_skel != NULL);
-}
-
-static QEMUMachine spapr_machine = {
-    .name = "pseries",
-    .desc = "pSeries Logical Partition (PAPR compliant)",
-    .init = ppc_spapr_init,
-    .reset = ppc_spapr_reset,
-    .block_default_type = IF_SCSI,
-    .max_cpus = MAX_CPUS,
-    .no_parallel = 1,
-    .boot_order = NULL,
-};
-
-static void spapr_machine_init(void)
-{
-    qemu_register_machine(&spapr_machine);
-}
-
-machine_init(spapr_machine_init);
diff --git a/hw/spapr_events.c b/hw/spapr_events.c
deleted file mode 100644 (file)
index ce78f09..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
- *
- * RTAS events handling
- *
- * Copyright (c) 2012 David Gibson, IBM Corporation.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-#include "cpu.h"
-#include "sysemu/sysemu.h"
-#include "char/char.h"
-#include "hw/qdev.h"
-#include "sysemu/device_tree.h"
-
-#include "hw/spapr.h"
-#include "hw/spapr_vio.h"
-
-#include <libfdt.h>
-
-struct rtas_error_log {
-    uint32_t summary;
-#define RTAS_LOG_VERSION_MASK                   0xff000000
-#define   RTAS_LOG_VERSION_6                    0x06000000
-#define RTAS_LOG_SEVERITY_MASK                  0x00e00000
-#define   RTAS_LOG_SEVERITY_ALREADY_REPORTED    0x00c00000
-#define   RTAS_LOG_SEVERITY_FATAL               0x00a00000
-#define   RTAS_LOG_SEVERITY_ERROR               0x00800000
-#define   RTAS_LOG_SEVERITY_ERROR_SYNC          0x00600000
-#define   RTAS_LOG_SEVERITY_WARNING             0x00400000
-#define   RTAS_LOG_SEVERITY_EVENT               0x00200000
-#define   RTAS_LOG_SEVERITY_NO_ERROR            0x00000000
-#define RTAS_LOG_DISPOSITION_MASK               0x00180000
-#define   RTAS_LOG_DISPOSITION_FULLY_RECOVERED  0x00000000
-#define   RTAS_LOG_DISPOSITION_LIMITED_RECOVERY 0x00080000
-#define   RTAS_LOG_DISPOSITION_NOT_RECOVERED    0x00100000
-#define RTAS_LOG_OPTIONAL_PART_PRESENT          0x00040000
-#define RTAS_LOG_INITIATOR_MASK                 0x0000f000
-#define   RTAS_LOG_INITIATOR_UNKNOWN            0x00000000
-#define   RTAS_LOG_INITIATOR_CPU                0x00001000
-#define   RTAS_LOG_INITIATOR_PCI                0x00002000
-#define   RTAS_LOG_INITIATOR_MEMORY             0x00004000
-#define   RTAS_LOG_INITIATOR_HOTPLUG            0x00006000
-#define RTAS_LOG_TARGET_MASK                    0x00000f00
-#define   RTAS_LOG_TARGET_UNKNOWN               0x00000000
-#define   RTAS_LOG_TARGET_CPU                   0x00000100
-#define   RTAS_LOG_TARGET_PCI                   0x00000200
-#define   RTAS_LOG_TARGET_MEMORY                0x00000400
-#define   RTAS_LOG_TARGET_HOTPLUG               0x00000600
-#define RTAS_LOG_TYPE_MASK                      0x000000ff
-#define   RTAS_LOG_TYPE_OTHER                   0x00000000
-#define   RTAS_LOG_TYPE_RETRY                   0x00000001
-#define   RTAS_LOG_TYPE_TCE_ERR                 0x00000002
-#define   RTAS_LOG_TYPE_INTERN_DEV_FAIL         0x00000003
-#define   RTAS_LOG_TYPE_TIMEOUT                 0x00000004
-#define   RTAS_LOG_TYPE_DATA_PARITY             0x00000005
-#define   RTAS_LOG_TYPE_ADDR_PARITY             0x00000006
-#define   RTAS_LOG_TYPE_CACHE_PARITY            0x00000007
-#define   RTAS_LOG_TYPE_ADDR_INVALID            0x00000008
-#define   RTAS_LOG_TYPE_ECC_UNCORR              0x00000009
-#define   RTAS_LOG_TYPE_ECC_CORR                0x0000000a
-#define   RTAS_LOG_TYPE_EPOW                    0x00000040
-    uint32_t extended_length;
-} QEMU_PACKED;
-
-struct rtas_event_log_v6 {
-    uint8_t b0;
-#define RTAS_LOG_V6_B0_VALID                          0x80
-#define RTAS_LOG_V6_B0_UNRECOVERABLE_ERROR            0x40
-#define RTAS_LOG_V6_B0_RECOVERABLE_ERROR              0x20
-#define RTAS_LOG_V6_B0_DEGRADED_OPERATION             0x10
-#define RTAS_LOG_V6_B0_PREDICTIVE_ERROR               0x08
-#define RTAS_LOG_V6_B0_NEW_LOG                        0x04
-#define RTAS_LOG_V6_B0_BIGENDIAN                      0x02
-    uint8_t _resv1;
-    uint8_t b2;
-#define RTAS_LOG_V6_B2_POWERPC_FORMAT                 0x80
-#define RTAS_LOG_V6_B2_LOG_FORMAT_MASK                0x0f
-#define   RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT    0x0e
-    uint8_t _resv2[9];
-    uint32_t company;
-#define RTAS_LOG_V6_COMPANY_IBM                 0x49424d00 /* IBM<null> */
-} QEMU_PACKED;
-
-struct rtas_event_log_v6_section_header {
-    uint16_t section_id;
-    uint16_t section_length;
-    uint8_t section_version;
-    uint8_t section_subtype;
-    uint16_t creator_component_id;
-} QEMU_PACKED;
-
-struct rtas_event_log_v6_maina {
-#define RTAS_LOG_V6_SECTION_ID_MAINA                0x5048 /* PH */
-    struct rtas_event_log_v6_section_header hdr;
-    uint32_t creation_date; /* BCD: YYYYMMDD */
-    uint32_t creation_time; /* BCD: HHMMSS00 */
-    uint8_t _platform1[8];
-    char creator_id;
-    uint8_t _resv1[2];
-    uint8_t section_count;
-    uint8_t _resv2[4];
-    uint8_t _platform2[8];
-    uint32_t plid;
-    uint8_t _platform3[4];
-} QEMU_PACKED;
-
-struct rtas_event_log_v6_mainb {
-#define RTAS_LOG_V6_SECTION_ID_MAINB                0x5548 /* UH */
-    struct rtas_event_log_v6_section_header hdr;
-    uint8_t subsystem_id;
-    uint8_t _platform1;
-    uint8_t event_severity;
-    uint8_t event_subtype;
-    uint8_t _platform2[4];
-    uint8_t _resv1[2];
-    uint16_t action_flags;
-    uint8_t _resv2[4];
-} QEMU_PACKED;
-
-struct rtas_event_log_v6_epow {
-#define RTAS_LOG_V6_SECTION_ID_EPOW                 0x4550 /* EP */
-    struct rtas_event_log_v6_section_header hdr;
-    uint8_t sensor_value;
-#define RTAS_LOG_V6_EPOW_ACTION_RESET                    0
-#define RTAS_LOG_V6_EPOW_ACTION_WARN_COOLING             1
-#define RTAS_LOG_V6_EPOW_ACTION_WARN_POWER               2
-#define RTAS_LOG_V6_EPOW_ACTION_SYSTEM_SHUTDOWN          3
-#define RTAS_LOG_V6_EPOW_ACTION_SYSTEM_HALT              4
-#define RTAS_LOG_V6_EPOW_ACTION_MAIN_ENCLOSURE           5
-#define RTAS_LOG_V6_EPOW_ACTION_POWER_OFF                7
-    uint8_t event_modifier;
-#define RTAS_LOG_V6_EPOW_MODIFIER_NORMAL                 1
-#define RTAS_LOG_V6_EPOW_MODIFIER_ON_UPS                 2
-#define RTAS_LOG_V6_EPOW_MODIFIER_CRITICAL               3
-#define RTAS_LOG_V6_EPOW_MODIFIER_TEMPERATURE            4
-    uint8_t extended_modifier;
-#define RTAS_LOG_V6_EPOW_XMODIFIER_SYSTEM_WIDE           0
-#define RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC    1
-    uint8_t _resv;
-    uint64_t reason_code;
-} QEMU_PACKED;
-
-struct epow_log_full {
-    struct rtas_error_log hdr;
-    struct rtas_event_log_v6 v6hdr;
-    struct rtas_event_log_v6_maina maina;
-    struct rtas_event_log_v6_mainb mainb;
-    struct rtas_event_log_v6_epow epow;
-} QEMU_PACKED;
-
-#define EVENT_MASK_INTERNAL_ERRORS           0x80000000
-#define EVENT_MASK_EPOW                      0x40000000
-#define EVENT_MASK_HOTPLUG                   0x10000000
-#define EVENT_MASK_IO                        0x08000000
-
-#define _FDT(exp) \
-    do { \
-        int ret = (exp);                                           \
-        if (ret < 0) {                                             \
-            fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
-                    #exp, fdt_strerror(ret));                      \
-            exit(1);                                               \
-        }                                                          \
-    } while (0)
-
-void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq)
-{
-    uint32_t epow_irq_ranges[] = {cpu_to_be32(epow_irq), cpu_to_be32(1)};
-    uint32_t epow_interrupts[] = {cpu_to_be32(epow_irq), 0};
-
-    _FDT((fdt_begin_node(fdt, "event-sources")));
-
-    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
-    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
-    _FDT((fdt_property(fdt, "interrupt-ranges",
-                       epow_irq_ranges, sizeof(epow_irq_ranges))));
-
-    _FDT((fdt_begin_node(fdt, "epow-events")));
-    _FDT((fdt_property(fdt, "interrupts",
-                       epow_interrupts, sizeof(epow_interrupts))));
-    _FDT((fdt_end_node(fdt)));
-
-    _FDT((fdt_end_node(fdt)));
-}
-
-static struct epow_log_full *pending_epow;
-static uint32_t next_plid;
-
-static void spapr_powerdown_req(Notifier *n, void *opaque)
-{
-    sPAPREnvironment *spapr = container_of(n, sPAPREnvironment, epow_notifier);
-    struct rtas_error_log *hdr;
-    struct rtas_event_log_v6 *v6hdr;
-    struct rtas_event_log_v6_maina *maina;
-    struct rtas_event_log_v6_mainb *mainb;
-    struct rtas_event_log_v6_epow *epow;
-    struct tm tm;
-    int year;
-
-    if (pending_epow) {
-        /* For now, we just throw away earlier events if two come
-         * along before any are consumed.  This is sufficient for our
-         * powerdown messages, but we'll need more if we do more
-         * general error/event logging */
-        g_free(pending_epow);
-    }
-    pending_epow = g_malloc0(sizeof(*pending_epow));
-    hdr = &pending_epow->hdr;
-    v6hdr = &pending_epow->v6hdr;
-    maina = &pending_epow->maina;
-    mainb = &pending_epow->mainb;
-    epow = &pending_epow->epow;
-
-    hdr->summary = cpu_to_be32(RTAS_LOG_VERSION_6
-                               | RTAS_LOG_SEVERITY_EVENT
-                               | RTAS_LOG_DISPOSITION_NOT_RECOVERED
-                               | RTAS_LOG_OPTIONAL_PART_PRESENT
-                               | RTAS_LOG_TYPE_EPOW);
-    hdr->extended_length = cpu_to_be32(sizeof(*pending_epow)
-                                       - sizeof(pending_epow->hdr));
-
-    v6hdr->b0 = RTAS_LOG_V6_B0_VALID | RTAS_LOG_V6_B0_NEW_LOG
-        | RTAS_LOG_V6_B0_BIGENDIAN;
-    v6hdr->b2 = RTAS_LOG_V6_B2_POWERPC_FORMAT
-        | RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT;
-    v6hdr->company = cpu_to_be32(RTAS_LOG_V6_COMPANY_IBM);
-
-    maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA);
-    maina->hdr.section_length = cpu_to_be16(sizeof(*maina));
-    /* FIXME: section version, subtype and creator id? */
-    qemu_get_timedate(&tm, spapr->rtc_offset);
-    year = tm.tm_year + 1900;
-    maina->creation_date = cpu_to_be32((to_bcd(year / 100) << 24)
-                                       | (to_bcd(year % 100) << 16)
-                                       | (to_bcd(tm.tm_mon + 1) << 8)
-                                       | to_bcd(tm.tm_mday));
-    maina->creation_time = cpu_to_be32((to_bcd(tm.tm_hour) << 24)
-                                       | (to_bcd(tm.tm_min) << 16)
-                                       | (to_bcd(tm.tm_sec) << 8));
-    maina->creator_id = 'H'; /* Hypervisor */
-    maina->section_count = 3; /* Main-A, Main-B and EPOW */
-    maina->plid = next_plid++;
-
-    mainb->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINB);
-    mainb->hdr.section_length = cpu_to_be16(sizeof(*mainb));
-    /* FIXME: section version, subtype and creator id? */
-    mainb->subsystem_id = 0xa0; /* External environment */
-    mainb->event_severity = 0x00; /* Informational / non-error */
-    mainb->event_subtype = 0xd0; /* Normal shutdown */
-
-    epow->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_EPOW);
-    epow->hdr.section_length = cpu_to_be16(sizeof(*epow));
-    epow->hdr.section_version = 2; /* includes extended modifier */
-    /* FIXME: section subtype and creator id? */
-    epow->sensor_value = RTAS_LOG_V6_EPOW_ACTION_SYSTEM_SHUTDOWN;
-    epow->event_modifier = RTAS_LOG_V6_EPOW_MODIFIER_NORMAL;
-    epow->extended_modifier = RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC;
-
-    qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->epow_irq));
-}
-
-static void check_exception(sPAPREnvironment *spapr,
-                            uint32_t token, uint32_t nargs,
-                            target_ulong args,
-                            uint32_t nret, target_ulong rets)
-{
-    uint32_t mask, buf, len;
-    uint64_t xinfo;
-
-    if ((nargs < 6) || (nargs > 7) || nret != 1) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    xinfo = rtas_ld(args, 1);
-    mask = rtas_ld(args, 2);
-    buf = rtas_ld(args, 4);
-    len = rtas_ld(args, 5);
-    if (nargs == 7) {
-        xinfo |= (uint64_t)rtas_ld(args, 6) << 32;
-    }
-
-    if ((mask & EVENT_MASK_EPOW) && pending_epow) {
-        if (sizeof(*pending_epow) < len) {
-            len = sizeof(*pending_epow);
-        }
-
-        cpu_physical_memory_write(buf, pending_epow, len);
-        g_free(pending_epow);
-        pending_epow = NULL;
-        rtas_st(rets, 0, 0);
-    } else {
-        rtas_st(rets, 0, 1);
-    }
-}
-
-void spapr_events_init(sPAPREnvironment *spapr)
-{
-    spapr->epow_irq = spapr_allocate_msi(0);
-    spapr->epow_notifier.notify = spapr_powerdown_req;
-    qemu_register_powerdown_notifier(&spapr->epow_notifier);
-    spapr_rtas_register("check-exception", check_exception);
-}
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
deleted file mode 100644 (file)
index 77c052f..0000000
+++ /dev/null
@@ -1,772 +0,0 @@
-#include "sysemu/sysemu.h"
-#include "cpu.h"
-#include "sysemu/sysemu.h"
-#include "helper_regs.h"
-#include "hw/spapr.h"
-
-#define HPTES_PER_GROUP 8
-
-#define HPTE_V_SSIZE_SHIFT      62
-#define HPTE_V_AVPN_SHIFT       7
-#define HPTE_V_AVPN             0x3fffffffffffff80ULL
-#define HPTE_V_AVPN_VAL(x)      (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
-#define HPTE_V_COMPARE(x, y)    (!(((x) ^ (y)) & 0xffffffffffffff80UL))
-#define HPTE_V_BOLTED           0x0000000000000010ULL
-#define HPTE_V_LOCK             0x0000000000000008ULL
-#define HPTE_V_LARGE            0x0000000000000004ULL
-#define HPTE_V_SECONDARY        0x0000000000000002ULL
-#define HPTE_V_VALID            0x0000000000000001ULL
-
-#define HPTE_R_PP0              0x8000000000000000ULL
-#define HPTE_R_TS               0x4000000000000000ULL
-#define HPTE_R_KEY_HI           0x3000000000000000ULL
-#define HPTE_R_RPN_SHIFT        12
-#define HPTE_R_RPN              0x3ffffffffffff000ULL
-#define HPTE_R_FLAGS            0x00000000000003ffULL
-#define HPTE_R_PP               0x0000000000000003ULL
-#define HPTE_R_N                0x0000000000000004ULL
-#define HPTE_R_G                0x0000000000000008ULL
-#define HPTE_R_M                0x0000000000000010ULL
-#define HPTE_R_I                0x0000000000000020ULL
-#define HPTE_R_W                0x0000000000000040ULL
-#define HPTE_R_WIMG             0x0000000000000078ULL
-#define HPTE_R_C                0x0000000000000080ULL
-#define HPTE_R_R                0x0000000000000100ULL
-#define HPTE_R_KEY_LO           0x0000000000000e00ULL
-
-#define HPTE_V_1TB_SEG          0x4000000000000000ULL
-#define HPTE_V_VRMA_MASK        0x4001ffffff000000ULL
-
-static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
-                                     target_ulong pte_index)
-{
-    target_ulong rb, va_low;
-
-    rb = (v & ~0x7fULL) << 16; /* AVA field */
-    va_low = pte_index >> 3;
-    if (v & HPTE_V_SECONDARY) {
-        va_low = ~va_low;
-    }
-    /* xor vsid from AVA */
-    if (!(v & HPTE_V_1TB_SEG)) {
-        va_low ^= v >> 12;
-    } else {
-        va_low ^= v >> 24;
-    }
-    va_low &= 0x7ff;
-    if (v & HPTE_V_LARGE) {
-        rb |= 1;                         /* L field */
-#if 0 /* Disable that P7 specific bit for now */
-        if (r & 0xff000) {
-            /* non-16MB large page, must be 64k */
-            /* (masks depend on page size) */
-            rb |= 0x1000;                /* page encoding in LP field */
-            rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
-            rb |= (va_low & 0xfe);       /* AVAL field */
-        }
-#endif
-    } else {
-        /* 4kB page */
-        rb |= (va_low & 0x7ff) << 12;   /* remaining 11b of AVA */
-    }
-    rb |= (v >> 54) & 0x300;            /* B field */
-    return rb;
-}
-
-static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                            target_ulong opcode, target_ulong *args)
-{
-    CPUPPCState *env = &cpu->env;
-    target_ulong flags = args[0];
-    target_ulong pte_index = args[1];
-    target_ulong pteh = args[2];
-    target_ulong ptel = args[3];
-    target_ulong page_shift = 12;
-    target_ulong raddr;
-    target_ulong i;
-    uint8_t *hpte;
-
-    /* only handle 4k and 16M pages for now */
-    if (pteh & HPTE_V_LARGE) {
-#if 0 /* We don't support 64k pages yet */
-        if ((ptel & 0xf000) == 0x1000) {
-            /* 64k page */
-        } else
-#endif
-        if ((ptel & 0xff000) == 0) {
-            /* 16M page */
-            page_shift = 24;
-            /* lowest AVA bit must be 0 for 16M pages */
-            if (pteh & 0x80) {
-                return H_PARAMETER;
-            }
-        } else {
-            return H_PARAMETER;
-        }
-    }
-
-    raddr = (ptel & HPTE_R_RPN) & ~((1ULL << page_shift) - 1);
-
-    if (raddr < spapr->ram_limit) {
-        /* Regular RAM - should have WIMG=0010 */
-        if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
-            return H_PARAMETER;
-        }
-    } else {
-        /* Looks like an IO address */
-        /* FIXME: What WIMG combinations could be sensible for IO?
-         * For now we allow WIMG=010x, but are there others? */
-        /* FIXME: Should we check against registered IO addresses? */
-        if ((ptel & (HPTE_R_W | HPTE_R_I | HPTE_R_M)) != HPTE_R_I) {
-            return H_PARAMETER;
-        }
-    }
-
-    pteh &= ~0x60ULL;
-
-    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
-        return H_PARAMETER;
-    }
-    if (likely((flags & H_EXACT) == 0)) {
-        pte_index &= ~7ULL;
-        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
-        for (i = 0; ; ++i) {
-            if (i == 8) {
-                return H_PTEG_FULL;
-            }
-            if ((ldq_p(hpte) & HPTE_V_VALID) == 0) {
-                break;
-            }
-            hpte += HASH_PTE_SIZE_64;
-        }
-    } else {
-        i = 0;
-        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
-        if (ldq_p(hpte) & HPTE_V_VALID) {
-            return H_PTEG_FULL;
-        }
-    }
-    stq_p(hpte + (HASH_PTE_SIZE_64/2), ptel);
-    /* eieio();  FIXME: need some sort of barrier for smp? */
-    stq_p(hpte, pteh);
-
-    args[0] = pte_index + i;
-    return H_SUCCESS;
-}
-
-enum {
-    REMOVE_SUCCESS = 0,
-    REMOVE_NOT_FOUND = 1,
-    REMOVE_PARM = 2,
-    REMOVE_HW = 3,
-};
-
-static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
-                                target_ulong avpn,
-                                target_ulong flags,
-                                target_ulong *vp, target_ulong *rp)
-{
-    uint8_t *hpte;
-    target_ulong v, r, rb;
-
-    if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
-        return REMOVE_PARM;
-    }
-
-    hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
-
-    v = ldq_p(hpte);
-    r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
-
-    if ((v & HPTE_V_VALID) == 0 ||
-        ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
-        ((flags & H_ANDCOND) && (v & avpn) != 0)) {
-        return REMOVE_NOT_FOUND;
-    }
-    *vp = v;
-    *rp = r;
-    stq_p(hpte, 0);
-    rb = compute_tlbie_rb(v, r, ptex);
-    ppc_tlb_invalidate_one(env, rb);
-    return REMOVE_SUCCESS;
-}
-
-static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                             target_ulong opcode, target_ulong *args)
-{
-    CPUPPCState *env = &cpu->env;
-    target_ulong flags = args[0];
-    target_ulong pte_index = args[1];
-    target_ulong avpn = args[2];
-    int ret;
-
-    ret = remove_hpte(env, pte_index, avpn, flags,
-                      &args[0], &args[1]);
-
-    switch (ret) {
-    case REMOVE_SUCCESS:
-        return H_SUCCESS;
-
-    case REMOVE_NOT_FOUND:
-        return H_NOT_FOUND;
-
-    case REMOVE_PARM:
-        return H_PARAMETER;
-
-    case REMOVE_HW:
-        return H_HARDWARE;
-    }
-
-    assert(0);
-}
-
-#define H_BULK_REMOVE_TYPE             0xc000000000000000ULL
-#define   H_BULK_REMOVE_REQUEST        0x4000000000000000ULL
-#define   H_BULK_REMOVE_RESPONSE       0x8000000000000000ULL
-#define   H_BULK_REMOVE_END            0xc000000000000000ULL
-#define H_BULK_REMOVE_CODE             0x3000000000000000ULL
-#define   H_BULK_REMOVE_SUCCESS        0x0000000000000000ULL
-#define   H_BULK_REMOVE_NOT_FOUND      0x1000000000000000ULL
-#define   H_BULK_REMOVE_PARM           0x2000000000000000ULL
-#define   H_BULK_REMOVE_HW             0x3000000000000000ULL
-#define H_BULK_REMOVE_RC               0x0c00000000000000ULL
-#define H_BULK_REMOVE_FLAGS            0x0300000000000000ULL
-#define   H_BULK_REMOVE_ABSOLUTE       0x0000000000000000ULL
-#define   H_BULK_REMOVE_ANDCOND        0x0100000000000000ULL
-#define   H_BULK_REMOVE_AVPN           0x0200000000000000ULL
-#define H_BULK_REMOVE_PTEX             0x00ffffffffffffffULL
-
-#define H_BULK_REMOVE_MAX_BATCH        4
-
-static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                  target_ulong opcode, target_ulong *args)
-{
-    CPUPPCState *env = &cpu->env;
-    int i;
-
-    for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
-        target_ulong *tsh = &args[i*2];
-        target_ulong tsl = args[i*2 + 1];
-        target_ulong v, r, ret;
-
-        if ((*tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) {
-            break;
-        } else if ((*tsh & H_BULK_REMOVE_TYPE) != H_BULK_REMOVE_REQUEST) {
-            return H_PARAMETER;
-        }
-
-        *tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS;
-        *tsh |= H_BULK_REMOVE_RESPONSE;
-
-        if ((*tsh & H_BULK_REMOVE_ANDCOND) && (*tsh & H_BULK_REMOVE_AVPN)) {
-            *tsh |= H_BULK_REMOVE_PARM;
-            return H_PARAMETER;
-        }
-
-        ret = remove_hpte(env, *tsh & H_BULK_REMOVE_PTEX, tsl,
-                          (*tsh & H_BULK_REMOVE_FLAGS) >> 26,
-                          &v, &r);
-
-        *tsh |= ret << 60;
-
-        switch (ret) {
-        case REMOVE_SUCCESS:
-            *tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43;
-            break;
-
-        case REMOVE_PARM:
-            return H_PARAMETER;
-
-        case REMOVE_HW:
-            return H_HARDWARE;
-        }
-    }
-
-    return H_SUCCESS;
-}
-
-static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                              target_ulong opcode, target_ulong *args)
-{
-    CPUPPCState *env = &cpu->env;
-    target_ulong flags = args[0];
-    target_ulong pte_index = args[1];
-    target_ulong avpn = args[2];
-    uint8_t *hpte;
-    target_ulong v, r, rb;
-
-    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
-        return H_PARAMETER;
-    }
-
-    hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
-
-    v = ldq_p(hpte);
-    r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
-
-    if ((v & HPTE_V_VALID) == 0 ||
-        ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
-        return H_NOT_FOUND;
-    }
-
-    r &= ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
-           HPTE_R_KEY_HI | HPTE_R_KEY_LO);
-    r |= (flags << 55) & HPTE_R_PP0;
-    r |= (flags << 48) & HPTE_R_KEY_HI;
-    r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
-    rb = compute_tlbie_rb(v, r, pte_index);
-    stq_p(hpte, v & ~HPTE_V_VALID);
-    ppc_tlb_invalidate_one(env, rb);
-    stq_p(hpte + (HASH_PTE_SIZE_64/2), r);
-    /* Don't need a memory barrier, due to qemu's global lock */
-    stq_p(hpte, v);
-    return H_SUCCESS;
-}
-
-static target_ulong h_read(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                           target_ulong opcode, target_ulong *args)
-{
-    CPUPPCState *env = &cpu->env;
-    target_ulong flags = args[0];
-    target_ulong pte_index = args[1];
-    uint8_t *hpte;
-    int i, ridx, n_entries = 1;
-
-    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
-        return H_PARAMETER;
-    }
-
-    if (flags & H_READ_4) {
-        /* Clear the two low order bits */
-        pte_index &= ~(3ULL);
-        n_entries = 4;
-    }
-
-    hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
-
-    for (i = 0, ridx = 0; i < n_entries; i++) {
-        args[ridx++] = ldq_p(hpte);
-        args[ridx++] = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
-        hpte += HASH_PTE_SIZE_64;
-    }
-
-    return H_SUCCESS;
-}
-
-static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                               target_ulong opcode, target_ulong *args)
-{
-    /* FIXME: actually implement this */
-    return H_HARDWARE;
-}
-
-#define FLAGS_REGISTER_VPA         0x0000200000000000ULL
-#define FLAGS_REGISTER_DTL         0x0000400000000000ULL
-#define FLAGS_REGISTER_SLBSHADOW   0x0000600000000000ULL
-#define FLAGS_DEREGISTER_VPA       0x0000a00000000000ULL
-#define FLAGS_DEREGISTER_DTL       0x0000c00000000000ULL
-#define FLAGS_DEREGISTER_SLBSHADOW 0x0000e00000000000ULL
-
-#define VPA_MIN_SIZE           640
-#define VPA_SIZE_OFFSET        0x4
-#define VPA_SHARED_PROC_OFFSET 0x9
-#define VPA_SHARED_PROC_VAL    0x2
-
-static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa)
-{
-    uint16_t size;
-    uint8_t tmp;
-
-    if (vpa == 0) {
-        hcall_dprintf("Can't cope with registering a VPA at logical 0\n");
-        return H_HARDWARE;
-    }
-
-    if (vpa % env->dcache_line_size) {
-        return H_PARAMETER;
-    }
-    /* FIXME: bounds check the address */
-
-    size = lduw_be_phys(vpa + 0x4);
-
-    if (size < VPA_MIN_SIZE) {
-        return H_PARAMETER;
-    }
-
-    /* VPA is not allowed to cross a page boundary */
-    if ((vpa / 4096) != ((vpa + size - 1) / 4096)) {
-        return H_PARAMETER;
-    }
-
-    env->vpa_addr = vpa;
-
-    tmp = ldub_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET);
-    tmp |= VPA_SHARED_PROC_VAL;
-    stb_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp);
-
-    return H_SUCCESS;
-}
-
-static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa)
-{
-    if (env->slb_shadow_addr) {
-        return H_RESOURCE;
-    }
-
-    if (env->dtl_addr) {
-        return H_RESOURCE;
-    }
-
-    env->vpa_addr = 0;
-    return H_SUCCESS;
-}
-
-static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr)
-{
-    uint32_t size;
-
-    if (addr == 0) {
-        hcall_dprintf("Can't cope with SLB shadow at logical 0\n");
-        return H_HARDWARE;
-    }
-
-    size = ldl_be_phys(addr + 0x4);
-    if (size < 0x8) {
-        return H_PARAMETER;
-    }
-
-    if ((addr / 4096) != ((addr + size - 1) / 4096)) {
-        return H_PARAMETER;
-    }
-
-    if (!env->vpa_addr) {
-        return H_RESOURCE;
-    }
-
-    env->slb_shadow_addr = addr;
-    env->slb_shadow_size = size;
-
-    return H_SUCCESS;
-}
-
-static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr)
-{
-    env->slb_shadow_addr = 0;
-    env->slb_shadow_size = 0;
-    return H_SUCCESS;
-}
-
-static target_ulong register_dtl(CPUPPCState *env, target_ulong addr)
-{
-    uint32_t size;
-
-    if (addr == 0) {
-        hcall_dprintf("Can't cope with DTL at logical 0\n");
-        return H_HARDWARE;
-    }
-
-    size = ldl_be_phys(addr + 0x4);
-
-    if (size < 48) {
-        return H_PARAMETER;
-    }
-
-    if (!env->vpa_addr) {
-        return H_RESOURCE;
-    }
-
-    env->dtl_addr = addr;
-    env->dtl_size = size;
-
-    return H_SUCCESS;
-}
-
-static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr)
-{
-    env->dtl_addr = 0;
-    env->dtl_size = 0;
-
-    return H_SUCCESS;
-}
-
-static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                   target_ulong opcode, target_ulong *args)
-{
-    target_ulong flags = args[0];
-    target_ulong procno = args[1];
-    target_ulong vpa = args[2];
-    target_ulong ret = H_PARAMETER;
-    CPUPPCState *tenv;
-    CPUState *tcpu;
-
-    tcpu = qemu_get_cpu(procno);
-    if (!tcpu) {
-        return H_PARAMETER;
-    }
-    tenv = tcpu->env_ptr;
-
-    switch (flags) {
-    case FLAGS_REGISTER_VPA:
-        ret = register_vpa(tenv, vpa);
-        break;
-
-    case FLAGS_DEREGISTER_VPA:
-        ret = deregister_vpa(tenv, vpa);
-        break;
-
-    case FLAGS_REGISTER_SLBSHADOW:
-        ret = register_slb_shadow(tenv, vpa);
-        break;
-
-    case FLAGS_DEREGISTER_SLBSHADOW:
-        ret = deregister_slb_shadow(tenv, vpa);
-        break;
-
-    case FLAGS_REGISTER_DTL:
-        ret = register_dtl(tenv, vpa);
-        break;
-
-    case FLAGS_DEREGISTER_DTL:
-        ret = deregister_dtl(tenv, vpa);
-        break;
-    }
-
-    return ret;
-}
-
-static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                           target_ulong opcode, target_ulong *args)
-{
-    CPUPPCState *env = &cpu->env;
-    CPUState *cs = CPU(cpu);
-
-    env->msr |= (1ULL << MSR_EE);
-    hreg_compute_hflags(env);
-    if (!cpu_has_work(cs)) {
-        env->halted = 1;
-        env->exception_index = EXCP_HLT;
-        cs->exit_request = 1;
-    }
-    return H_SUCCESS;
-}
-
-static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                           target_ulong opcode, target_ulong *args)
-{
-    target_ulong rtas_r3 = args[0];
-    uint32_t token = ldl_be_phys(rtas_r3);
-    uint32_t nargs = ldl_be_phys(rtas_r3 + 4);
-    uint32_t nret = ldl_be_phys(rtas_r3 + 8);
-
-    return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12,
-                           nret, rtas_r3 + 12 + 4*nargs);
-}
-
-static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                   target_ulong opcode, target_ulong *args)
-{
-    target_ulong size = args[0];
-    target_ulong addr = args[1];
-
-    switch (size) {
-    case 1:
-        args[0] = ldub_phys(addr);
-        return H_SUCCESS;
-    case 2:
-        args[0] = lduw_phys(addr);
-        return H_SUCCESS;
-    case 4:
-        args[0] = ldl_phys(addr);
-        return H_SUCCESS;
-    case 8:
-        args[0] = ldq_phys(addr);
-        return H_SUCCESS;
-    }
-    return H_PARAMETER;
-}
-
-static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                    target_ulong opcode, target_ulong *args)
-{
-    target_ulong size = args[0];
-    target_ulong addr = args[1];
-    target_ulong val  = args[2];
-
-    switch (size) {
-    case 1:
-        stb_phys(addr, val);
-        return H_SUCCESS;
-    case 2:
-        stw_phys(addr, val);
-        return H_SUCCESS;
-    case 4:
-        stl_phys(addr, val);
-        return H_SUCCESS;
-    case 8:
-        stq_phys(addr, val);
-        return H_SUCCESS;
-    }
-    return H_PARAMETER;
-}
-
-static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                    target_ulong opcode, target_ulong *args)
-{
-    target_ulong dst   = args[0]; /* Destination address */
-    target_ulong src   = args[1]; /* Source address */
-    target_ulong esize = args[2]; /* Element size (0=1,1=2,2=4,3=8) */
-    target_ulong count = args[3]; /* Element count */
-    target_ulong op    = args[4]; /* 0 = copy, 1 = invert */
-    uint64_t tmp;
-    unsigned int mask = (1 << esize) - 1;
-    int step = 1 << esize;
-
-    if (count > 0x80000000) {
-        return H_PARAMETER;
-    }
-
-    if ((dst & mask) || (src & mask) || (op > 1)) {
-        return H_PARAMETER;
-    }
-
-    if (dst >= src && dst < (src + (count << esize))) {
-            dst = dst + ((count - 1) << esize);
-            src = src + ((count - 1) << esize);
-            step = -step;
-    }
-
-    while (count--) {
-        switch (esize) {
-        case 0:
-            tmp = ldub_phys(src);
-            break;
-        case 1:
-            tmp = lduw_phys(src);
-            break;
-        case 2:
-            tmp = ldl_phys(src);
-            break;
-        case 3:
-            tmp = ldq_phys(src);
-            break;
-        default:
-            return H_PARAMETER;
-        }
-        if (op == 1) {
-            tmp = ~tmp;
-        }
-        switch (esize) {
-        case 0:
-            stb_phys(dst, tmp);
-            break;
-        case 1:
-            stw_phys(dst, tmp);
-            break;
-        case 2:
-            stl_phys(dst, tmp);
-            break;
-        case 3:
-            stq_phys(dst, tmp);
-            break;
-        }
-        dst = dst + step;
-        src = src + step;
-    }
-
-    return H_SUCCESS;
-}
-
-static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                   target_ulong opcode, target_ulong *args)
-{
-    /* Nothing to do on emulation, KVM will trap this in the kernel */
-    return H_SUCCESS;
-}
-
-static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                   target_ulong opcode, target_ulong *args)
-{
-    /* Nothing to do on emulation, KVM will trap this in the kernel */
-    return H_SUCCESS;
-}
-
-static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
-static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
-
-void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
-{
-    spapr_hcall_fn *slot;
-
-    if (opcode <= MAX_HCALL_OPCODE) {
-        assert((opcode & 0x3) == 0);
-
-        slot = &papr_hypercall_table[opcode / 4];
-    } else {
-        assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
-
-        slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
-    }
-
-    assert(!(*slot));
-    *slot = fn;
-}
-
-target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
-                             target_ulong *args)
-{
-    if ((opcode <= MAX_HCALL_OPCODE)
-        && ((opcode & 0x3) == 0)) {
-        spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
-
-        if (fn) {
-            return fn(cpu, spapr, opcode, args);
-        }
-    } else if ((opcode >= KVMPPC_HCALL_BASE) &&
-               (opcode <= KVMPPC_HCALL_MAX)) {
-        spapr_hcall_fn fn = kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
-
-        if (fn) {
-            return fn(cpu, spapr, opcode, args);
-        }
-    }
-
-    hcall_dprintf("Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode);
-    return H_FUNCTION;
-}
-
-static void hypercall_register_types(void)
-{
-    /* hcall-pft */
-    spapr_register_hypercall(H_ENTER, h_enter);
-    spapr_register_hypercall(H_REMOVE, h_remove);
-    spapr_register_hypercall(H_PROTECT, h_protect);
-    spapr_register_hypercall(H_READ, h_read);
-
-    /* hcall-bulk */
-    spapr_register_hypercall(H_BULK_REMOVE, h_bulk_remove);
-
-    /* hcall-dabr */
-    spapr_register_hypercall(H_SET_DABR, h_set_dabr);
-
-    /* hcall-splpar */
-    spapr_register_hypercall(H_REGISTER_VPA, h_register_vpa);
-    spapr_register_hypercall(H_CEDE, h_cede);
-
-    /* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate
-     * here between the "CI" and the "CACHE" variants, they will use whatever
-     * mapping attributes qemu is using. When using KVM, the kernel will
-     * enforce the attributes more strongly
-     */
-    spapr_register_hypercall(H_LOGICAL_CI_LOAD, h_logical_load);
-    spapr_register_hypercall(H_LOGICAL_CI_STORE, h_logical_store);
-    spapr_register_hypercall(H_LOGICAL_CACHE_LOAD, h_logical_load);
-    spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store);
-    spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi);
-    spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
-    spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP, h_logical_memop);
-
-    /* qemu/KVM-PPC specific hcalls */
-    spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
-}
-
-type_init(hypercall_register_types)
diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c
deleted file mode 100644 (file)
index d8a098c..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * QEMU sPAPR IOMMU (TCE) code
- *
- * Copyright (c) 2010 David Gibson, IBM Corporation <dwg@au1.ibm.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "hw.h"
-#include "sysemu/kvm.h"
-#include "qdev.h"
-#include "kvm_ppc.h"
-#include "sysemu/dma.h"
-#include "exec/address-spaces.h"
-
-#include "hw/spapr.h"
-
-#include <libfdt.h>
-
-/* #define DEBUG_TCE */
-
-enum sPAPRTCEAccess {
-    SPAPR_TCE_FAULT = 0,
-    SPAPR_TCE_RO = 1,
-    SPAPR_TCE_WO = 2,
-    SPAPR_TCE_RW = 3,
-};
-
-typedef struct sPAPRTCETable sPAPRTCETable;
-
-struct sPAPRTCETable {
-    DMAContext dma;
-    uint32_t liobn;
-    uint32_t window_size;
-    sPAPRTCE *table;
-    bool bypass;
-    int fd;
-    QLIST_ENTRY(sPAPRTCETable) list;
-};
-
-
-QLIST_HEAD(spapr_tce_tables, sPAPRTCETable) spapr_tce_tables;
-
-static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
-{
-    sPAPRTCETable *tcet;
-
-    QLIST_FOREACH(tcet, &spapr_tce_tables, list) {
-        if (tcet->liobn == liobn) {
-            return tcet;
-        }
-    }
-
-    return NULL;
-}
-
-static int spapr_tce_translate(DMAContext *dma,
-                               dma_addr_t addr,
-                               hwaddr *paddr,
-                               hwaddr *len,
-                               DMADirection dir)
-{
-    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-    enum sPAPRTCEAccess access = (dir == DMA_DIRECTION_FROM_DEVICE)
-        ? SPAPR_TCE_WO : SPAPR_TCE_RO;
-    uint64_t tce;
-
-#ifdef DEBUG_TCE
-    fprintf(stderr, "spapr_tce_translate liobn=0x%" PRIx32 " addr=0x"
-            DMA_ADDR_FMT "\n", tcet->liobn, addr);
-#endif
-
-    if (tcet->bypass) {
-        *paddr = addr;
-        *len = (hwaddr)-1;
-        return 0;
-    }
-
-    /* Check if we are in bound */
-    if (addr >= tcet->window_size) {
-#ifdef DEBUG_TCE
-        fprintf(stderr, "spapr_tce_translate out of bounds\n");
-#endif
-        return -EFAULT;
-    }
-
-    tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT].tce;
-
-    /* Check TCE */
-    if (!(tce & access)) {
-        return -EPERM;
-    }
-
-    /* How much til end of page ? */
-    *len = ((~addr) & SPAPR_TCE_PAGE_MASK) + 1;
-
-    /* Translate */
-    *paddr = (tce & ~SPAPR_TCE_PAGE_MASK) |
-        (addr & SPAPR_TCE_PAGE_MASK);
-
-#ifdef DEBUG_TCE
-    fprintf(stderr, " ->  *paddr=0x" TARGET_FMT_plx ", *len=0x"
-            TARGET_FMT_plx "\n", *paddr, *len);
-#endif
-
-    return 0;
-}
-
-DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size)
-{
-    sPAPRTCETable *tcet;
-
-    if (spapr_tce_find_by_liobn(liobn)) {
-        fprintf(stderr, "Attempted to create TCE table with duplicate"
-                " LIOBN 0x%x\n", liobn);
-        return NULL;
-    }
-
-    if (!window_size) {
-        return NULL;
-    }
-
-    tcet = g_malloc0(sizeof(*tcet));
-    dma_context_init(&tcet->dma, &address_space_memory, spapr_tce_translate, NULL, NULL);
-
-    tcet->liobn = liobn;
-    tcet->window_size = window_size;
-
-    if (kvm_enabled()) {
-        tcet->table = kvmppc_create_spapr_tce(liobn,
-                                              window_size,
-                                              &tcet->fd);
-    }
-
-    if (!tcet->table) {
-        size_t table_size = (window_size >> SPAPR_TCE_PAGE_SHIFT)
-            * sizeof(sPAPRTCE);
-        tcet->table = g_malloc0(table_size);
-    }
-
-#ifdef DEBUG_TCE
-    fprintf(stderr, "spapr_iommu: New TCE table, liobn=0x%x, context @ %p, "
-            "table @ %p, fd=%d\n", liobn, &tcet->dma, tcet->table, tcet->fd);
-#endif
-
-    QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
-
-    return &tcet->dma;
-}
-
-void spapr_tce_free(DMAContext *dma)
-{
-
-    if (dma) {
-        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-
-        QLIST_REMOVE(tcet, list);
-
-        if (!kvm_enabled() ||
-            (kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
-                                     tcet->window_size) != 0)) {
-            g_free(tcet->table);
-        }
-
-        g_free(tcet);
-    }
-}
-
-void spapr_tce_set_bypass(DMAContext *dma, bool bypass)
-{
-    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-
-    tcet->bypass = bypass;
-}
-
-void spapr_tce_reset(DMAContext *dma)
-{
-    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-    size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
-        * sizeof(sPAPRTCE);
-
-    tcet->bypass = false;
-    memset(tcet->table, 0, table_size);
-}
-
-static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
-                                target_ulong tce)
-{
-    sPAPRTCE *tcep;
-
-    if (ioba >= tcet->window_size) {
-        hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
-                      TARGET_FMT_lx "\n", ioba);
-        return H_PARAMETER;
-    }
-
-    tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT);
-    tcep->tce = tce;
-
-    return H_SUCCESS;
-}
-
-static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                              target_ulong opcode, target_ulong *args)
-{
-    target_ulong liobn = args[0];
-    target_ulong ioba = args[1];
-    target_ulong tce = args[2];
-    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
-
-    if (liobn & 0xFFFFFFFF00000000ULL) {
-        hcall_dprintf("spapr_vio_put_tce on out-of-boundsw LIOBN "
-                      TARGET_FMT_lx "\n", liobn);
-        return H_PARAMETER;
-    }
-
-    ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
-
-    if (tcet) {
-        return put_tce_emu(tcet, ioba, tce);
-    }
-#ifdef DEBUG_TCE
-    fprintf(stderr, "%s on liobn=" TARGET_FMT_lx /*%s*/
-            "  ioba 0x" TARGET_FMT_lx "  TCE 0x" TARGET_FMT_lx "\n",
-            __func__, liobn, /*dev->qdev.id, */ioba, tce);
-#endif
-
-    return H_PARAMETER;
-}
-
-void spapr_iommu_init(void)
-{
-    QLIST_INIT(&spapr_tce_tables);
-
-    /* hcall-tce */
-    spapr_register_hypercall(H_PUT_TCE, h_put_tce);
-}
-
-int spapr_dma_dt(void *fdt, int node_off, const char *propname,
-                 uint32_t liobn, uint64_t window, uint32_t size)
-{
-    uint32_t dma_prop[5];
-    int ret;
-
-    dma_prop[0] = cpu_to_be32(liobn);
-    dma_prop[1] = cpu_to_be32(window >> 32);
-    dma_prop[2] = cpu_to_be32(window & 0xFFFFFFFF);
-    dma_prop[3] = 0; /* window size is 32 bits */
-    dma_prop[4] = cpu_to_be32(size);
-
-    ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2);
-    if (ret < 0) {
-        return ret;
-    }
-
-    ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2);
-    if (ret < 0) {
-        return ret;
-    }
-
-    ret = fdt_setprop(fdt, node_off, propname, dma_prop, sizeof(dma_prop));
-    if (ret < 0) {
-        return ret;
-    }
-
-    return 0;
-}
-
-int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
-                      DMAContext *iommu)
-{
-    if (!iommu) {
-        return 0;
-    }
-
-    if (iommu->translate == spapr_tce_translate) {
-        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, iommu);
-        return spapr_dma_dt(fdt, node_off, propname,
-                tcet->liobn, 0, tcet->window_size);
-    }
-
-    return -1;
-}
index 0ace2eb1f3c3ff7877822433203d016248894e48..19701e7e406dc33d5d6d5f5507713605b63080d1 100644 (file)
@@ -24,7 +24,7 @@
  * THE SOFTWARE.
  *
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "net/net.h"
 #include "hw/qdev.h"
 #include "hw/spapr.h"
index 4eacbcfd5815b0e5152e5f272c587da61a235abf..36adbc5592428db42ec9e7524ced3e3925c6ee92 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pci/pci.h"
-#include "pci/msi.h"
-#include "pci/msix.h"
-#include "pci/pci_host.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
+#include "hw/pci/pci_host.h"
 #include "hw/spapr.h"
 #include "hw/spapr_pci.h"
 #include "exec/address-spaces.h"
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
deleted file mode 100644 (file)
index 5ec787f..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
- *
- * Hypercall based emulated RTAS
- *
- * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-#include "cpu.h"
-#include "sysemu/sysemu.h"
-#include "char/char.h"
-#include "hw/qdev.h"
-#include "sysemu/device_tree.h"
-
-#include "hw/spapr.h"
-#include "hw/spapr_vio.h"
-
-#include <libfdt.h>
-
-#define TOKEN_BASE      0x2000
-#define TOKEN_MAX       0x100
-
-static void rtas_display_character(sPAPREnvironment *spapr,
-                                   uint32_t token, uint32_t nargs,
-                                   target_ulong args,
-                                   uint32_t nret, target_ulong rets)
-{
-    uint8_t c = rtas_ld(args, 0);
-    VIOsPAPRDevice *sdev = vty_lookup(spapr, 0);
-
-    if (!sdev) {
-        rtas_st(rets, 0, -1);
-    } else {
-        vty_putchars(sdev, &c, sizeof(c));
-        rtas_st(rets, 0, 0);
-    }
-}
-
-static void rtas_get_time_of_day(sPAPREnvironment *spapr,
-                                 uint32_t token, uint32_t nargs,
-                                 target_ulong args,
-                                 uint32_t nret, target_ulong rets)
-{
-    struct tm tm;
-
-    if (nret != 8) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    qemu_get_timedate(&tm, spapr->rtc_offset);
-
-    rtas_st(rets, 0, 0); /* Success */
-    rtas_st(rets, 1, tm.tm_year + 1900);
-    rtas_st(rets, 2, tm.tm_mon + 1);
-    rtas_st(rets, 3, tm.tm_mday);
-    rtas_st(rets, 4, tm.tm_hour);
-    rtas_st(rets, 5, tm.tm_min);
-    rtas_st(rets, 6, tm.tm_sec);
-    rtas_st(rets, 7, 0); /* we don't do nanoseconds */
-}
-
-static void rtas_set_time_of_day(sPAPREnvironment *spapr,
-                                 uint32_t token, uint32_t nargs,
-                                 target_ulong args,
-                                 uint32_t nret, target_ulong rets)
-{
-    struct tm tm;
-
-    tm.tm_year = rtas_ld(args, 0) - 1900;
-    tm.tm_mon = rtas_ld(args, 1) - 1;
-    tm.tm_mday = rtas_ld(args, 2);
-    tm.tm_hour = rtas_ld(args, 3);
-    tm.tm_min = rtas_ld(args, 4);
-    tm.tm_sec = rtas_ld(args, 5);
-
-    /* Just generate a monitor event for the change */
-    rtc_change_mon_event(&tm);
-    spapr->rtc_offset = qemu_timedate_diff(&tm);
-
-    rtas_st(rets, 0, 0); /* Success */
-}
-
-static void rtas_power_off(sPAPREnvironment *spapr,
-                           uint32_t token, uint32_t nargs, target_ulong args,
-                           uint32_t nret, target_ulong rets)
-{
-    if (nargs != 2 || nret != 1) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-    qemu_system_shutdown_request();
-    rtas_st(rets, 0, 0);
-}
-
-static void rtas_system_reboot(sPAPREnvironment *spapr,
-                               uint32_t token, uint32_t nargs,
-                               target_ulong args,
-                               uint32_t nret, target_ulong rets)
-{
-    if (nargs != 0 || nret != 1) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-    qemu_system_reset_request();
-    rtas_st(rets, 0, 0);
-}
-
-static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
-                                         uint32_t token, uint32_t nargs,
-                                         target_ulong args,
-                                         uint32_t nret, target_ulong rets)
-{
-    target_ulong id;
-    CPUPPCState *env;
-    CPUState *cpu;
-
-    if (nargs != 1 || nret != 2) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    id = rtas_ld(args, 0);
-    for (env = first_cpu; env; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
-        if (cpu->cpu_index != id) {
-            continue;
-        }
-
-        if (env->halted) {
-            rtas_st(rets, 1, 0);
-        } else {
-            rtas_st(rets, 1, 2);
-        }
-
-        rtas_st(rets, 0, 0);
-        return;
-    }
-
-    /* Didn't find a matching cpu */
-    rtas_st(rets, 0, -3);
-}
-
-static void rtas_start_cpu(sPAPREnvironment *spapr,
-                           uint32_t token, uint32_t nargs,
-                           target_ulong args,
-                           uint32_t nret, target_ulong rets)
-{
-    target_ulong id, start, r3;
-    CPUState *cpu;
-    CPUPPCState *env;
-
-    if (nargs != 3 || nret != 1) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    id = rtas_ld(args, 0);
-    start = rtas_ld(args, 1);
-    r3 = rtas_ld(args, 2);
-
-    for (env = first_cpu; env; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
-
-        if (cpu->cpu_index != id) {
-            continue;
-        }
-
-        if (!env->halted) {
-            rtas_st(rets, 0, -1);
-            return;
-        }
-
-        /* This will make sure qemu state is up to date with kvm, and
-         * mark it dirty so our changes get flushed back before the
-         * new cpu enters */
-        kvm_cpu_synchronize_state(env);
-
-        env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
-        env->nip = start;
-        env->gpr[3] = r3;
-        env->halted = 0;
-
-        qemu_cpu_kick(cpu);
-
-        rtas_st(rets, 0, 0);
-        return;
-    }
-
-    /* Didn't find a matching cpu */
-    rtas_st(rets, 0, -3);
-}
-
-static struct rtas_call {
-    const char *name;
-    spapr_rtas_fn fn;
-} rtas_table[TOKEN_MAX];
-
-struct rtas_call *rtas_next = rtas_table;
-
-target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
-                             uint32_t token, uint32_t nargs, target_ulong args,
-                             uint32_t nret, target_ulong rets)
-{
-    if ((token >= TOKEN_BASE)
-        && ((token - TOKEN_BASE) < TOKEN_MAX)) {
-        struct rtas_call *call = rtas_table + (token - TOKEN_BASE);
-
-        if (call->fn) {
-            call->fn(spapr, token, nargs, args, nret, rets);
-            return H_SUCCESS;
-        }
-    }
-
-    /* HACK: Some Linux early debug code uses RTAS display-character,
-     * but assumes the token value is 0xa (which it is on some real
-     * machines) without looking it up in the device tree.  This
-     * special case makes this work */
-    if (token == 0xa) {
-        rtas_display_character(spapr, 0xa, nargs, args, nret, rets);
-        return H_SUCCESS;
-    }
-
-    hcall_dprintf("Unknown RTAS token 0x%x\n", token);
-    rtas_st(rets, 0, -3);
-    return H_PARAMETER;
-}
-
-int spapr_rtas_register(const char *name, spapr_rtas_fn fn)
-{
-    int i;
-
-    for (i = 0; i < (rtas_next - rtas_table); i++) {
-        if (strcmp(name, rtas_table[i].name) == 0) {
-            fprintf(stderr, "RTAS call \"%s\" registered twice\n", name);
-            exit(1);
-        }
-    }
-
-    assert(rtas_next < (rtas_table + TOKEN_MAX));
-
-    rtas_next->name = name;
-    rtas_next->fn = fn;
-
-    return (rtas_next++ - rtas_table) + TOKEN_BASE;
-}
-
-int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
-                                 hwaddr rtas_size)
-{
-    int ret;
-    int i;
-
-    ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
-    if (ret < 0) {
-        fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n",
-                fdt_strerror(ret));
-        return ret;
-    }
-
-    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "linux,rtas-base",
-                                    rtas_addr);
-    if (ret < 0) {
-        fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
-                fdt_strerror(ret));
-        return ret;
-    }
-
-    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
-                                    rtas_addr);
-    if (ret < 0) {
-        fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
-                fdt_strerror(ret));
-        return ret;
-    }
-
-    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "rtas-size",
-                                    rtas_size);
-    if (ret < 0) {
-        fprintf(stderr, "Couldn't add rtas-size property: %s\n",
-                fdt_strerror(ret));
-        return ret;
-    }
-
-    for (i = 0; i < TOKEN_MAX; i++) {
-        struct rtas_call *call = &rtas_table[i];
-
-        if (!call->name) {
-            continue;
-        }
-
-        ret = qemu_devtree_setprop_cell(fdt, "/rtas", call->name,
-                                        i + TOKEN_BASE);
-        if (ret < 0) {
-            fprintf(stderr, "Couldn't add rtas token for %s: %s\n",
-                    call->name, fdt_strerror(ret));
-            return ret;
-        }
-
-    }
-    return 0;
-}
-
-static void core_rtas_register_types(void)
-{
-    spapr_rtas_register("display-character", rtas_display_character);
-    spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
-    spapr_rtas_register("set-time-of-day", rtas_set_time_of_day);
-    spapr_rtas_register("power-off", rtas_power_off);
-    spapr_rtas_register("system-reboot", rtas_system_reboot);
-    spapr_rtas_register("query-cpu-stopped-state",
-                        rtas_query_cpu_stopped_state);
-    spapr_rtas_register("start-cpu", rtas_start_cpu);
-}
-
-type_init(core_rtas_register_types)
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
deleted file mode 100644 (file)
index 34c9ca6..0000000
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- * QEMU sPAPR VIO code
- *
- * Copyright (c) 2010 David Gibson, IBM Corporation <dwg@au1.ibm.com>
- * Based on the s390 virtio bus code:
- * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "hw.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "monitor/monitor.h"
-#include "loader.h"
-#include "elf.h"
-#include "hw/sysbus.h"
-#include "sysemu/kvm.h"
-#include "sysemu/device_tree.h"
-#include "kvm_ppc.h"
-
-#include "hw/spapr.h"
-#include "hw/spapr_vio.h"
-#include "hw/xics.h"
-
-#ifdef CONFIG_FDT
-#include <libfdt.h>
-#endif /* CONFIG_FDT */
-
-/* #define DEBUG_SPAPR */
-
-#ifdef DEBUG_SPAPR
-#define dprintf(fmt, ...) \
-    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
-#else
-#define dprintf(fmt, ...) \
-    do { } while (0)
-#endif
-
-static Property spapr_vio_props[] = {
-    DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, irq, 0), \
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static const TypeInfo spapr_vio_bus_info = {
-    .name = TYPE_SPAPR_VIO_BUS,
-    .parent = TYPE_BUS,
-    .instance_size = sizeof(VIOsPAPRBus),
-};
-
-VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
-{
-    BusChild *kid;
-    VIOsPAPRDevice *dev = NULL;
-
-    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        dev = (VIOsPAPRDevice *)kid->child;
-        if (dev->reg == reg) {
-            return dev;
-        }
-    }
-
-    return NULL;
-}
-
-static char *vio_format_dev_name(VIOsPAPRDevice *dev)
-{
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
-    char *name;
-
-    /* Device tree style name device@reg */
-    name = g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
-
-    return name;
-}
-
-#ifdef CONFIG_FDT
-static int vio_make_devnode(VIOsPAPRDevice *dev,
-                            void *fdt)
-{
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
-    int vdevice_off, node_off, ret;
-    char *dt_name;
-
-    vdevice_off = fdt_path_offset(fdt, "/vdevice");
-    if (vdevice_off < 0) {
-        return vdevice_off;
-    }
-
-    dt_name = vio_format_dev_name(dev);
-    node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
-    g_free(dt_name);
-    if (node_off < 0) {
-        return node_off;
-    }
-
-    ret = fdt_setprop_cell(fdt, node_off, "reg", dev->reg);
-    if (ret < 0) {
-        return ret;
-    }
-
-    if (pc->dt_type) {
-        ret = fdt_setprop_string(fdt, node_off, "device_type",
-                                 pc->dt_type);
-        if (ret < 0) {
-            return ret;
-        }
-    }
-
-    if (pc->dt_compatible) {
-        ret = fdt_setprop_string(fdt, node_off, "compatible",
-                                 pc->dt_compatible);
-        if (ret < 0) {
-            return ret;
-        }
-    }
-
-    if (dev->irq) {
-        uint32_t ints_prop[] = {cpu_to_be32(dev->irq), 0};
-
-        ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
-                          sizeof(ints_prop));
-        if (ret < 0) {
-            return ret;
-        }
-    }
-
-    ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma);
-    if (ret < 0) {
-        return ret;
-    }
-
-    if (pc->devnode) {
-        ret = (pc->devnode)(dev, fdt, node_off);
-        if (ret < 0) {
-            return ret;
-        }
-    }
-
-    return node_off;
-}
-#endif /* CONFIG_FDT */
-
-/*
- * CRQ handling
- */
-static target_ulong h_reg_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                              target_ulong opcode, target_ulong *args)
-{
-    target_ulong reg = args[0];
-    target_ulong queue_addr = args[1];
-    target_ulong queue_len = args[2];
-    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-
-    if (!dev) {
-        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
-        return H_PARAMETER;
-    }
-
-    /* We can't grok a queue size bigger than 256M for now */
-    if (queue_len < 0x1000 || queue_len > 0x10000000) {
-        hcall_dprintf("Queue size too small or too big (0x" TARGET_FMT_lx
-                      ")\n", queue_len);
-        return H_PARAMETER;
-    }
-
-    /* Check queue alignment */
-    if (queue_addr & 0xfff) {
-        hcall_dprintf("Queue not aligned (0x" TARGET_FMT_lx ")\n", queue_addr);
-        return H_PARAMETER;
-    }
-
-    /* Check if device supports CRQs */
-    if (!dev->crq.SendFunc) {
-        hcall_dprintf("Device does not support CRQ\n");
-        return H_NOT_FOUND;
-    }
-
-    /* Already a queue ? */
-    if (dev->crq.qsize) {
-        hcall_dprintf("CRQ already registered\n");
-        return H_RESOURCE;
-    }
-    dev->crq.qladdr = queue_addr;
-    dev->crq.qsize = queue_len;
-    dev->crq.qnext = 0;
-
-    dprintf("CRQ for dev 0x" TARGET_FMT_lx " registered at 0x"
-            TARGET_FMT_lx "/0x" TARGET_FMT_lx "\n",
-            reg, queue_addr, queue_len);
-    return H_SUCCESS;
-}
-
-static target_ulong free_crq(VIOsPAPRDevice *dev)
-{
-    dev->crq.qladdr = 0;
-    dev->crq.qsize = 0;
-    dev->crq.qnext = 0;
-
-    dprintf("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
-
-    return H_SUCCESS;
-}
-
-static target_ulong h_free_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                               target_ulong opcode, target_ulong *args)
-{
-    target_ulong reg = args[0];
-    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-
-    if (!dev) {
-        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
-        return H_PARAMETER;
-    }
-
-    return free_crq(dev);
-}
-
-static target_ulong h_send_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                               target_ulong opcode, target_ulong *args)
-{
-    target_ulong reg = args[0];
-    target_ulong msg_hi = args[1];
-    target_ulong msg_lo = args[2];
-    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    uint64_t crq_mangle[2];
-
-    if (!dev) {
-        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
-        return H_PARAMETER;
-    }
-    crq_mangle[0] = cpu_to_be64(msg_hi);
-    crq_mangle[1] = cpu_to_be64(msg_lo);
-
-    if (dev->crq.SendFunc) {
-        return dev->crq.SendFunc(dev, (uint8_t *)crq_mangle);
-    }
-
-    return H_HARDWARE;
-}
-
-static target_ulong h_enable_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                 target_ulong opcode, target_ulong *args)
-{
-    target_ulong reg = args[0];
-    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-
-    if (!dev) {
-        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
-        return H_PARAMETER;
-    }
-
-    return 0;
-}
-
-/* Returns negative error, 0 success, or positive: queue full */
-int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
-{
-    int rc;
-    uint8_t byte;
-
-    if (!dev->crq.qsize) {
-        fprintf(stderr, "spapr_vio_send_creq on uninitialized queue\n");
-        return -1;
-    }
-
-    /* Maybe do a fast path for KVM just writing to the pages */
-    rc = spapr_vio_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
-    if (rc) {
-        return rc;
-    }
-    if (byte != 0) {
-        return 1;
-    }
-
-    rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
-                             &crq[8], 8);
-    if (rc) {
-        return rc;
-    }
-
-    kvmppc_eieio();
-
-    rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext, crq, 8);
-    if (rc) {
-        return rc;
-    }
-
-    dev->crq.qnext = (dev->crq.qnext + 16) % dev->crq.qsize;
-
-    if (dev->signal_state & 1) {
-        qemu_irq_pulse(spapr_vio_qirq(dev));
-    }
-
-    return 0;
-}
-
-/* "quiesce" handling */
-
-static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
-{
-    if (dev->dma) {
-        spapr_tce_reset(dev->dma);
-    }
-    free_crq(dev);
-}
-
-static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
-                                uint32_t nargs, target_ulong args,
-                                uint32_t nret, target_ulong rets)
-{
-    VIOsPAPRBus *bus = spapr->vio_bus;
-    VIOsPAPRDevice *dev;
-    uint32_t unit, enable;
-
-    if (nargs != 2) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-    unit = rtas_ld(args, 0);
-    enable = rtas_ld(args, 1);
-    dev = spapr_vio_find_by_reg(bus, unit);
-    if (!dev) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    if (!dev->dma) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    spapr_tce_set_bypass(dev->dma, !!enable);
-
-    rtas_st(rets, 0, 0);
-}
-
-static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
-                         uint32_t nargs, target_ulong args,
-                         uint32_t nret, target_ulong rets)
-{
-    VIOsPAPRBus *bus = spapr->vio_bus;
-    BusChild *kid;
-    VIOsPAPRDevice *dev = NULL;
-
-    if (nargs != 0) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        dev = (VIOsPAPRDevice *)kid->child;
-        spapr_vio_quiesce_one(dev);
-    }
-
-    rtas_st(rets, 0, 0);
-}
-
-static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
-{
-    VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
-    BusChild *kid;
-    VIOsPAPRDevice *other;
-
-    /*
-     * Check for a device other than the given one which is already
-     * using the requested address. We have to open code this because
-     * the given dev might already be in the list.
-     */
-    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child);
-
-        if (other != dev && other->reg == dev->reg) {
-            return other;
-        }
-    }
-
-    return 0;
-}
-
-static void spapr_vio_busdev_reset(DeviceState *qdev)
-{
-    VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
-
-    /* Shut down the request queue and TCEs if necessary */
-    spapr_vio_quiesce_one(dev);
-
-    dev->signal_state = 0;
-
-    if (pc->reset) {
-        pc->reset(dev);
-    }
-}
-
-static int spapr_vio_busdev_init(DeviceState *qdev)
-{
-    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
-    char *id;
-
-    if (dev->reg != -1) {
-        /*
-         * Explicitly assigned address, just verify that no-one else
-         * is using it.  other mechanism). We have to open code this
-         * rather than using spapr_vio_find_by_reg() because sdev
-         * itself is already in the list.
-         */
-        VIOsPAPRDevice *other = reg_conflict(dev);
-
-        if (other) {
-            fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
-                    object_get_typename(OBJECT(qdev)),
-                    object_get_typename(OBJECT(&other->qdev)),
-                    dev->reg);
-            return -1;
-        }
-    } else {
-        /* Need to assign an address */
-        VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
-
-        do {
-            dev->reg = bus->next_reg++;
-        } while (reg_conflict(dev));
-    }
-
-    /* Don't overwrite ids assigned on the command line */
-    if (!dev->qdev.id) {
-        id = vio_format_dev_name(dev);
-        dev->qdev.id = id;
-    }
-
-    dev->irq = spapr_allocate_msi(dev->irq);
-    if (!dev->irq) {
-        return -1;
-    }
-
-    if (pc->rtce_window_size) {
-        uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
-        dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
-    }
-
-    return pc->init(dev);
-}
-
-static target_ulong h_vio_signal(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                 target_ulong opcode,
-                                 target_ulong *args)
-{
-    target_ulong reg = args[0];
-    target_ulong mode = args[1];
-    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    VIOsPAPRDeviceClass *pc;
-
-    if (!dev) {
-        return H_PARAMETER;
-    }
-
-    pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
-
-    if (mode & ~pc->signal_mask) {
-        return H_PARAMETER;
-    }
-
-    dev->signal_state = mode;
-
-    return H_SUCCESS;
-}
-
-VIOsPAPRBus *spapr_vio_bus_init(void)
-{
-    VIOsPAPRBus *bus;
-    BusState *qbus;
-    DeviceState *dev;
-
-    /* Create bridge device */
-    dev = qdev_create(NULL, "spapr-vio-bridge");
-    qdev_init_nofail(dev);
-
-    /* Create bus on bridge device */
-
-    qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
-    bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
-    bus->next_reg = 0x71000000;
-
-    /* hcall-vio */
-    spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
-
-    /* hcall-crq */
-    spapr_register_hypercall(H_REG_CRQ, h_reg_crq);
-    spapr_register_hypercall(H_FREE_CRQ, h_free_crq);
-    spapr_register_hypercall(H_SEND_CRQ, h_send_crq);
-    spapr_register_hypercall(H_ENABLE_CRQ, h_enable_crq);
-
-    /* RTAS calls */
-    spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
-    spapr_rtas_register("quiesce", rtas_quiesce);
-
-    return bus;
-}
-
-/* Represents sPAPR hcall VIO devices */
-
-static int spapr_vio_bridge_init(SysBusDevice *dev)
-{
-    /* nothing */
-    return 0;
-}
-
-static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = spapr_vio_bridge_init;
-    dc->no_user = 1;
-}
-
-static const TypeInfo spapr_vio_bridge_info = {
-    .name          = "spapr-vio-bridge",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SysBusDevice),
-    .class_init    = spapr_vio_bridge_class_init,
-};
-
-static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *k = DEVICE_CLASS(klass);
-    k->init = spapr_vio_busdev_init;
-    k->reset = spapr_vio_busdev_reset;
-    k->bus_type = TYPE_SPAPR_VIO_BUS;
-    k->props = spapr_vio_props;
-}
-
-static const TypeInfo spapr_vio_type_info = {
-    .name = TYPE_VIO_SPAPR_DEVICE,
-    .parent = TYPE_DEVICE,
-    .instance_size = sizeof(VIOsPAPRDevice),
-    .abstract = true,
-    .class_size = sizeof(VIOsPAPRDeviceClass),
-    .class_init = vio_spapr_device_class_init,
-};
-
-static void spapr_vio_register_types(void)
-{
-    type_register_static(&spapr_vio_bus_info);
-    type_register_static(&spapr_vio_bridge_info);
-    type_register_static(&spapr_vio_type_info);
-}
-
-type_init(spapr_vio_register_types)
-
-#ifdef CONFIG_FDT
-static int compare_reg(const void *p1, const void *p2)
-{
-    VIOsPAPRDevice const *dev1, *dev2;
-
-    dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
-    dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
-
-    if (dev1->reg < dev2->reg) {
-        return -1;
-    }
-    if (dev1->reg == dev2->reg) {
-        return 0;
-    }
-
-    /* dev1->reg > dev2->reg */
-    return 1;
-}
-
-int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
-{
-    DeviceState *qdev, **qdevs;
-    BusChild *kid;
-    int i, num, ret = 0;
-
-    /* Count qdevs on the bus list */
-    num = 0;
-    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        num++;
-    }
-
-    /* Copy out into an array of pointers */
-    qdevs = g_malloc(sizeof(qdev) * num);
-    num = 0;
-    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        qdevs[num++] = kid->child;
-    }
-
-    /* Sort the array */
-    qsort(qdevs, num, sizeof(qdev), compare_reg);
-
-    /* Hack alert. Give the devices to libfdt in reverse order, we happen
-     * to know that will mean they are in forward order in the tree. */
-    for (i = num - 1; i >= 0; i--) {
-        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
-
-        ret = vio_make_devnode(dev, fdt);
-
-        if (ret < 0) {
-            goto out;
-        }
-    }
-
-    ret = 0;
-out:
-    free(qdevs);
-
-    return ret;
-}
-
-int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
-{
-    VIOsPAPRDevice *dev;
-    char *name, *path;
-    int ret, offset;
-
-    dev = spapr_vty_get_default(bus);
-    if (!dev)
-        return 0;
-
-    offset = fdt_path_offset(fdt, "/chosen");
-    if (offset < 0) {
-        return offset;
-    }
-
-    name = vio_format_dev_name(dev);
-    path = g_strdup_printf("/vdevice/%s", name);
-
-    ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
-
-    g_free(name);
-    g_free(path);
-
-    return ret;
-}
-#endif /* CONFIG_FDT */
index 7fc0e13f9fdfb0d6d6f567672a23402950156bef..27940949ce5c472699a07c540484875fffeb8354 100644 (file)
  *  - Add indirect descriptors support
  *  - Maybe do autosense (PAPR seems to mandate it, linux doesn't care)
  */
-#include "hw.h"
-#include "scsi.h"
-#include "scsi-defs.h"
-#include "srp.h"
+#include "hw/hw.h"
+#include "hw/scsi.h"
+#include "hw/scsi-defs.h"
+#include "hw/srp.h"
 #include "hw/qdev.h"
 #include "hw/spapr.h"
 #include "hw/spapr_vio.h"
index 5c63eaafa97160044d641e539775cc92d23256d8..be08571d230b96c8f15910c5d71989713fab9a47 100644 (file)
@@ -1,4 +1,4 @@
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "char/char.h"
 #include "hw/spapr.h"
 #include "hw/spapr_vio.h"
index a39a511c527013e80fdeb2f883e2b5e4ea6f3ab3..71bbddf8c31c8e441360c7a762aaefe508e01e07 100644 (file)
@@ -1,8 +1,10 @@
-obj-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
+obj-y = lance.o tcx.o sun4m_iommu.o slavio_intctl.o
 obj-y += slavio_timer.o slavio_misc.o sparc32_dma.o
-obj-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o
+obj-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o
 
 # GRLIB
 obj-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += sun4m.o leon3.o
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
new file mode 100644 (file)
index 0000000..f58061f
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * QEMU Leon3 System Emulator
+ *
+ * Copyright (c) 2010-2011 AdaCore
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "qemu/timer.h"
+#include "hw/ptimer.h"
+#include "char/char.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "trace.h"
+#include "exec/address-spaces.h"
+
+#include "hw/grlib.h"
+
+/* Default system clock.  */
+#define CPU_CLK (40 * 1000 * 1000)
+
+#define PROM_FILENAME        "u-boot.bin"
+
+#define MAX_PILS 16
+
+typedef struct ResetData {
+    SPARCCPU *cpu;
+    uint32_t  entry;            /* save kernel entry in case of reset */
+} ResetData;
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetData *s   = (ResetData *)opaque;
+    CPUSPARCState  *env = &s->cpu->env;
+
+    cpu_reset(CPU(s->cpu));
+
+    env->halted = 0;
+    env->pc     = s->entry;
+    env->npc    = s->entry + 4;
+}
+
+void leon3_irq_ack(void *irq_manager, int intno)
+{
+    grlib_irqmp_ack((DeviceState *)irq_manager, intno);
+}
+
+static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
+{
+    CPUSPARCState *env = (CPUSPARCState *)opaque;
+
+    assert(env != NULL);
+
+    env->pil_in = pil_in;
+
+    if (env->pil_in && (env->interrupt_index == 0 ||
+                        (env->interrupt_index & ~15) == TT_EXTINT)) {
+        unsigned int i;
+
+        for (i = 15; i > 0; i--) {
+            if (env->pil_in & (1 << i)) {
+                int old_interrupt = env->interrupt_index;
+
+                env->interrupt_index = TT_EXTINT | i;
+                if (old_interrupt != env->interrupt_index) {
+                    trace_leon3_set_irq(i);
+                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                }
+                break;
+            }
+        }
+    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
+        trace_leon3_reset_irq(env->interrupt_index & 15);
+        env->interrupt_index = 0;
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void leon3_generic_hw_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    SPARCCPU *cpu;
+    CPUSPARCState   *env;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *prom = g_new(MemoryRegion, 1);
+    int         ret;
+    char       *filename;
+    qemu_irq   *cpu_irqs = NULL;
+    int         bios_size;
+    int         prom_size;
+    ResetData  *reset_info;
+
+    /* Init CPU */
+    if (!cpu_model) {
+        cpu_model = "LEON3";
+    }
+
+    cpu = cpu_sparc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    cpu_sparc_set_id(env, 0);
+
+    /* Reset data */
+    reset_info        = g_malloc0(sizeof(ResetData));
+    reset_info->cpu   = cpu;
+    qemu_register_reset(main_cpu_reset, reset_info);
+
+    /* Allocate IRQ manager */
+    grlib_irqmp_create(0x80000200, env, &cpu_irqs, MAX_PILS, &leon3_set_pil_in);
+
+    env->qemu_irq_ack = leon3_irq_manager;
+
+    /* Allocate RAM */
+    if ((uint64_t)ram_size > (1UL << 30)) {
+        fprintf(stderr,
+                "qemu: Too much memory for this machine: %d, maximum 1G\n",
+                (unsigned int)(ram_size / (1024 * 1024)));
+        exit(1);
+    }
+
+    memory_region_init_ram(ram, "leon3.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, 0x40000000, ram);
+
+    /* Allocate BIOS */
+    prom_size = 8 * 1024 * 1024; /* 8Mb */
+    memory_region_init_ram(prom, "Leon3.bios", prom_size);
+    vmstate_register_ram_global(prom);
+    memory_region_set_readonly(prom, true);
+    memory_region_add_subregion(address_space_mem, 0x00000000, prom);
+
+    /* Load boot prom */
+    if (bios_name == NULL) {
+        bios_name = PROM_FILENAME;
+    }
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+
+    bios_size = get_image_size(filename);
+
+    if (bios_size > prom_size) {
+        fprintf(stderr, "qemu: could not load prom '%s': file too big\n",
+                filename);
+        exit(1);
+    }
+
+    if (bios_size > 0) {
+        ret = load_image_targphys(filename, 0x00000000, bios_size);
+        if (ret < 0 || ret > prom_size) {
+            fprintf(stderr, "qemu: could not load prom '%s'\n", filename);
+            exit(1);
+        }
+    } else if (kernel_filename == NULL) {
+        fprintf(stderr, "Can't read bios image %s\n", filename);
+        exit(1);
+    }
+
+    /* Can directly load an application. */
+    if (kernel_filename != NULL) {
+        long     kernel_size;
+        uint64_t entry;
+
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+                               1 /* big endian */, ELF_MACHINE, 0);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+        if (bios_size <= 0) {
+            /* If there is no bios/monitor, start the application.  */
+            env->pc = entry;
+            env->npc = entry + 4;
+            reset_info->entry = entry;
+        }
+    }
+
+    /* Allocate timers */
+    grlib_gptimer_create(0x80000300, 2, CPU_CLK, cpu_irqs, 6);
+
+    /* Allocate uart */
+    if (serial_hds[0]) {
+        grlib_apbuart_create(0x80000100, serial_hds[0], cpu_irqs[3]);
+    }
+}
+
+static QEMUMachine leon3_generic_machine = {
+    .name     = "leon3_generic",
+    .desc     = "Leon-3 generic",
+    .init     = leon3_generic_hw_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void leon3_machine_init(void)
+{
+    qemu_register_machine(&leon3_generic_machine);
+}
+
+machine_init(leon3_machine_init);
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
new file mode 100644 (file)
index 0000000..37bd041
--- /dev/null
@@ -0,0 +1,1936 @@
+/*
+ * QEMU Sun4m & Sun4d & Sun4c System Emulator
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "hw/sun4m.h"
+#include "hw/nvram.h"
+#include "hw/sparc32_dma.h"
+#include "hw/fdc.h"
+#include "sysemu/sysemu.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "hw/firmware_abi.h"
+#include "hw/esp.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
+#include "hw/fw_cfg.h"
+#include "hw/escc.h"
+#include "hw/empty_slot.h"
+#include "hw/qdev-addr.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "sysemu/blockdev.h"
+#include "trace.h"
+
+/*
+ * Sun4m architecture was used in the following machines:
+ *
+ * SPARCserver 6xxMP/xx
+ * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15),
+ * SPARCclassic X (4/10)
+ * SPARCstation LX/ZX (4/30)
+ * SPARCstation Voyager
+ * SPARCstation 10/xx, SPARCserver 10/xx
+ * SPARCstation 5, SPARCserver 5
+ * SPARCstation 20/xx, SPARCserver 20
+ * SPARCstation 4
+ *
+ * Sun4d architecture was used in the following machines:
+ *
+ * SPARCcenter 2000
+ * SPARCserver 1000
+ *
+ * Sun4c architecture was used in the following machines:
+ * SPARCstation 1/1+, SPARCserver 1/1+
+ * SPARCstation SLC
+ * SPARCstation IPC
+ * SPARCstation ELC
+ * SPARCstation IPX
+ *
+ * See for example: http://www.sunhelp.org/faq/sunref1.html
+ */
+
+#define KERNEL_LOAD_ADDR     0x00004000
+#define CMDLINE_ADDR         0x007ff000
+#define INITRD_LOAD_ADDR     0x00800000
+#define PROM_SIZE_MAX        (1024 * 1024)
+#define PROM_VADDR           0xffd00000
+#define PROM_FILENAME        "openbios-sparc32"
+#define CFG_ADDR             0xd00000510ULL
+#define FW_CFG_SUN4M_DEPTH   (FW_CFG_ARCH_LOCAL + 0x00)
+
+#define MAX_CPUS 16
+#define MAX_PILS 16
+#define MAX_VSIMMS 4
+
+#define ESCC_CLOCK 4915200
+
+struct sun4m_hwdef {
+    hwaddr iommu_base, iommu_pad_base, iommu_pad_len, slavio_base;
+    hwaddr intctl_base, counter_base, nvram_base, ms_kb_base;
+    hwaddr serial_base, fd_base;
+    hwaddr afx_base, idreg_base, dma_base, esp_base, le_base;
+    hwaddr tcx_base, cs_base, apc_base, aux1_base, aux2_base;
+    hwaddr bpp_base, dbri_base, sx_base;
+    struct {
+        hwaddr reg_base, vram_base;
+    } vsimm[MAX_VSIMMS];
+    hwaddr ecc_base;
+    uint64_t max_mem;
+    const char * const default_cpu_model;
+    uint32_t ecc_version;
+    uint32_t iommu_version;
+    uint16_t machine_id;
+    uint8_t nvram_machine_id;
+};
+
+#define MAX_IOUNITS 5
+
+struct sun4d_hwdef {
+    hwaddr iounit_bases[MAX_IOUNITS], slavio_base;
+    hwaddr counter_base, nvram_base, ms_kb_base;
+    hwaddr serial_base;
+    hwaddr espdma_base, esp_base;
+    hwaddr ledma_base, le_base;
+    hwaddr tcx_base;
+    hwaddr sbi_base;
+    uint64_t max_mem;
+    const char * const default_cpu_model;
+    uint32_t iounit_version;
+    uint16_t machine_id;
+    uint8_t nvram_machine_id;
+};
+
+struct sun4c_hwdef {
+    hwaddr iommu_base, slavio_base;
+    hwaddr intctl_base, counter_base, nvram_base, ms_kb_base;
+    hwaddr serial_base, fd_base;
+    hwaddr idreg_base, dma_base, esp_base, le_base;
+    hwaddr tcx_base, aux1_base;
+    uint64_t max_mem;
+    const char * const default_cpu_model;
+    uint32_t iommu_version;
+    uint16_t machine_id;
+    uint8_t nvram_machine_id;
+};
+
+int DMA_get_channel_mode (int nchan)
+{
+    return 0;
+}
+int DMA_read_memory (int nchan, void *buf, int pos, int size)
+{
+    return 0;
+}
+int DMA_write_memory (int nchan, void *buf, int pos, int size)
+{
+    return 0;
+}
+void DMA_hold_DREQ (int nchan) {}
+void DMA_release_DREQ (int nchan) {}
+void DMA_schedule(int nchan) {}
+
+void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
+{
+}
+
+void DMA_register_channel (int nchan,
+                           DMA_transfer_handler transfer_handler,
+                           void *opaque)
+{
+}
+
+static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+{
+    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
+    return 0;
+}
+
+static void nvram_init(M48t59State *nvram, uint8_t *macaddr,
+                       const char *cmdline, const char *boot_devices,
+                       ram_addr_t RAM_size, uint32_t kernel_size,
+                       int width, int height, int depth,
+                       int nvram_machine_id, const char *arch)
+{
+    unsigned int i;
+    uint32_t start, end;
+    uint8_t image[0x1ff0];
+    struct OpenBIOS_nvpart_v1 *part_header;
+
+    memset(image, '\0', sizeof(image));
+
+    start = 0;
+
+    // OpenBIOS nvram variables
+    // Variable partition
+    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
+    part_header->signature = OPENBIOS_PART_SYSTEM;
+    pstrcpy(part_header->name, sizeof(part_header->name), "system");
+
+    end = start + sizeof(struct OpenBIOS_nvpart_v1);
+    for (i = 0; i < nb_prom_envs; i++)
+        end = OpenBIOS_set_var(image, end, prom_envs[i]);
+
+    // End marker
+    image[end++] = '\0';
+
+    end = start + ((end - start + 15) & ~15);
+    OpenBIOS_finish_partition(part_header, end - start);
+
+    // free partition
+    start = end;
+    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
+    part_header->signature = OPENBIOS_PART_FREE;
+    pstrcpy(part_header->name, sizeof(part_header->name), "free");
+
+    end = 0x1fd0;
+    OpenBIOS_finish_partition(part_header, end - start);
+
+    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr,
+                    nvram_machine_id);
+
+    for (i = 0; i < sizeof(image); i++)
+        m48t59_write(nvram, i, image[i]);
+}
+
+static DeviceState *slavio_intctl;
+
+void sun4m_pic_info(Monitor *mon, const QDict *qdict)
+{
+    if (slavio_intctl)
+        slavio_pic_info(mon, slavio_intctl);
+}
+
+void sun4m_irq_info(Monitor *mon, const QDict *qdict)
+{
+    if (slavio_intctl)
+        slavio_irq_info(mon, slavio_intctl);
+}
+
+void cpu_check_irqs(CPUSPARCState *env)
+{
+    if (env->pil_in && (env->interrupt_index == 0 ||
+                        (env->interrupt_index & ~15) == TT_EXTINT)) {
+        unsigned int i;
+
+        for (i = 15; i > 0; i--) {
+            if (env->pil_in & (1 << i)) {
+                int old_interrupt = env->interrupt_index;
+
+                env->interrupt_index = TT_EXTINT | i;
+                if (old_interrupt != env->interrupt_index) {
+                    trace_sun4m_cpu_interrupt(i);
+                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                }
+                break;
+            }
+        }
+    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
+        trace_sun4m_cpu_reset_interrupt(env->interrupt_index & 15);
+        env->interrupt_index = 0;
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void cpu_kick_irq(SPARCCPU *cpu)
+{
+    CPUSPARCState *env = &cpu->env;
+
+    env->halted = 0;
+    cpu_check_irqs(env);
+    qemu_cpu_kick(CPU(cpu));
+}
+
+static void cpu_set_irq(void *opaque, int irq, int level)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    if (level) {
+        trace_sun4m_cpu_set_irq_raise(irq);
+        env->pil_in |= 1 << irq;
+        cpu_kick_irq(cpu);
+    } else {
+        trace_sun4m_cpu_set_irq_lower(irq);
+        env->pil_in &= ~(1 << irq);
+        cpu_check_irqs(env);
+    }
+}
+
+static void dummy_cpu_set_irq(void *opaque, int irq, int level)
+{
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+    env->halted = 0;
+}
+
+static void secondary_cpu_reset(void *opaque)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+    env->halted = 1;
+}
+
+static void cpu_halt_signal(void *opaque, int irq, int level)
+{
+    if (level && cpu_single_env)
+        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return addr - 0xf0000000ULL;
+}
+
+static unsigned long sun4m_load_kernel(const char *kernel_filename,
+                                       const char *initrd_filename,
+                                       ram_addr_t RAM_size)
+{
+    int linux_boot;
+    unsigned int i;
+    long initrd_size, kernel_size;
+    uint8_t *ptr;
+
+    linux_boot = (kernel_filename != NULL);
+
+    kernel_size = 0;
+    if (linux_boot) {
+        int bswap_needed;
+
+#ifdef BSWAP_NEEDED
+        bswap_needed = 1;
+#else
+        bswap_needed = 0;
+#endif
+        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+                               NULL, NULL, NULL, 1, ELF_MACHINE, 0);
+        if (kernel_size < 0)
+            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
+                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
+                                    TARGET_PAGE_SIZE);
+        if (kernel_size < 0)
+            kernel_size = load_image_targphys(kernel_filename,
+                                              KERNEL_LOAD_ADDR,
+                                              RAM_size - KERNEL_LOAD_ADDR);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+
+        /* load initrd */
+        initrd_size = 0;
+        if (initrd_filename) {
+            initrd_size = load_image_targphys(initrd_filename,
+                                              INITRD_LOAD_ADDR,
+                                              RAM_size - INITRD_LOAD_ADDR);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+        }
+        if (initrd_size > 0) {
+            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
+                ptr = rom_ptr(KERNEL_LOAD_ADDR + i);
+                if (ldl_p(ptr) == 0x48647253) { // HdrS
+                    stl_p(ptr + 16, INITRD_LOAD_ADDR);
+                    stl_p(ptr + 20, initrd_size);
+                    break;
+                }
+            }
+        }
+    }
+    return kernel_size;
+}
+
+static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "iommu");
+    qdev_prop_set_uint32(dev, "version", version);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, irq);
+    sysbus_mmio_map(s, 0, addr);
+
+    return s;
+}
+
+static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq,
+                              void *iommu, qemu_irq *dev_irq, int is_ledma)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "sparc32_dma");
+    qdev_prop_set_ptr(dev, "iommu_opaque", iommu);
+    qdev_prop_set_uint32(dev, "is_ledma", is_ledma);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, parent_irq);
+    *dev_irq = qdev_get_gpio_in(dev, 0);
+    sysbus_mmio_map(s, 0, daddr);
+
+    return s;
+}
+
+static void lance_init(NICInfo *nd, hwaddr leaddr,
+                       void *dma_opaque, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    qemu_irq reset;
+
+    qemu_check_nic_model(&nd_table[0], "lance");
+
+    dev = qdev_create(NULL, "lance");
+    qdev_set_nic_properties(dev, nd);
+    qdev_prop_set_ptr(dev, "dma", dma_opaque);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(s, 0, leaddr);
+    sysbus_connect_irq(s, 0, irq);
+    reset = qdev_get_gpio_in(dev, 0);
+    qdev_connect_gpio_out(dma_opaque, 0, reset);
+}
+
+static DeviceState *slavio_intctl_init(hwaddr addr,
+                                       hwaddr addrg,
+                                       qemu_irq **parent_irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    unsigned int i, j;
+
+    dev = qdev_create(NULL, "slavio_intctl");
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+
+    for (i = 0; i < MAX_CPUS; i++) {
+        for (j = 0; j < MAX_PILS; j++) {
+            sysbus_connect_irq(s, i * MAX_PILS + j, parent_irq[i][j]);
+        }
+    }
+    sysbus_mmio_map(s, 0, addrg);
+    for (i = 0; i < MAX_CPUS; i++) {
+        sysbus_mmio_map(s, i + 1, addr + i * TARGET_PAGE_SIZE);
+    }
+
+    return dev;
+}
+
+#define SYS_TIMER_OFFSET      0x10000ULL
+#define CPU_TIMER_OFFSET(cpu) (0x1000ULL * cpu)
+
+static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq,
+                                  qemu_irq *cpu_irqs, unsigned int num_cpus)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    unsigned int i;
+
+    dev = qdev_create(NULL, "slavio_timer");
+    qdev_prop_set_uint32(dev, "num_cpus", num_cpus);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, master_irq);
+    sysbus_mmio_map(s, 0, addr + SYS_TIMER_OFFSET);
+
+    for (i = 0; i < MAX_CPUS; i++) {
+        sysbus_mmio_map(s, i + 1, addr + (hwaddr)CPU_TIMER_OFFSET(i));
+        sysbus_connect_irq(s, i + 1, cpu_irqs[i]);
+    }
+}
+
+static qemu_irq  slavio_system_powerdown;
+
+static void slavio_powerdown_req(Notifier *n, void *opaque)
+{
+    qemu_irq_raise(slavio_system_powerdown);
+}
+
+static Notifier slavio_system_powerdown_notifier = {
+    .notify = slavio_powerdown_req
+};
+
+#define MISC_LEDS 0x01600000
+#define MISC_CFG  0x01800000
+#define MISC_DIAG 0x01a00000
+#define MISC_MDM  0x01b00000
+#define MISC_SYS  0x01f00000
+
+static void slavio_misc_init(hwaddr base,
+                             hwaddr aux1_base,
+                             hwaddr aux2_base, qemu_irq irq,
+                             qemu_irq fdc_tc)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "slavio_misc");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    if (base) {
+        /* 8 bit registers */
+        /* Slavio control */
+        sysbus_mmio_map(s, 0, base + MISC_CFG);
+        /* Diagnostics */
+        sysbus_mmio_map(s, 1, base + MISC_DIAG);
+        /* Modem control */
+        sysbus_mmio_map(s, 2, base + MISC_MDM);
+        /* 16 bit registers */
+        /* ss600mp diag LEDs */
+        sysbus_mmio_map(s, 3, base + MISC_LEDS);
+        /* 32 bit registers */
+        /* System control */
+        sysbus_mmio_map(s, 4, base + MISC_SYS);
+    }
+    if (aux1_base) {
+        /* AUX 1 (Misc System Functions) */
+        sysbus_mmio_map(s, 5, aux1_base);
+    }
+    if (aux2_base) {
+        /* AUX 2 (Software Powerdown Control) */
+        sysbus_mmio_map(s, 6, aux2_base);
+    }
+    sysbus_connect_irq(s, 0, irq);
+    sysbus_connect_irq(s, 1, fdc_tc);
+    slavio_system_powerdown = qdev_get_gpio_in(dev, 0);
+    qemu_register_powerdown_notifier(&slavio_system_powerdown_notifier);
+}
+
+static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "eccmemctl");
+    qdev_prop_set_uint32(dev, "version", version);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, irq);
+    sysbus_mmio_map(s, 0, base);
+    if (version == 0) { // SS-600MP only
+        sysbus_mmio_map(s, 1, base + 0x1000);
+    }
+}
+
+static void apc_init(hwaddr power_base, qemu_irq cpu_halt)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "apc");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    /* Power management (APC) XXX: not a Slavio device */
+    sysbus_mmio_map(s, 0, power_base);
+    sysbus_connect_irq(s, 0, cpu_halt);
+}
+
+static void tcx_init(hwaddr addr, int vram_size, int width,
+                     int height, int depth)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "SUNW,tcx");
+    qdev_prop_set_taddr(dev, "addr", addr);
+    qdev_prop_set_uint32(dev, "vram_size", vram_size);
+    qdev_prop_set_uint16(dev, "width", width);
+    qdev_prop_set_uint16(dev, "height", height);
+    qdev_prop_set_uint16(dev, "depth", depth);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    /* 8-bit plane */
+    sysbus_mmio_map(s, 0, addr + 0x00800000ULL);
+    /* DAC */
+    sysbus_mmio_map(s, 1, addr + 0x00200000ULL);
+    /* TEC (dummy) */
+    sysbus_mmio_map(s, 2, addr + 0x00700000ULL);
+    /* THC 24 bit: NetBSD writes here even with 8-bit display: dummy */
+    sysbus_mmio_map(s, 3, addr + 0x00301000ULL);
+    if (depth == 24) {
+        /* 24-bit plane */
+        sysbus_mmio_map(s, 4, addr + 0x02000000ULL);
+        /* Control plane */
+        sysbus_mmio_map(s, 5, addr + 0x0a000000ULL);
+    } else {
+        /* THC 8 bit (dummy) */
+        sysbus_mmio_map(s, 4, addr + 0x00300000ULL);
+    }
+}
+
+/* NCR89C100/MACIO Internal ID register */
+static const uint8_t idreg_data[] = { 0xfe, 0x81, 0x01, 0x03 };
+
+static void idreg_init(hwaddr addr)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "macio_idreg");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+    cpu_physical_memory_write_rom(addr, idreg_data, sizeof(idreg_data));
+}
+
+typedef struct IDRegState {
+    SysBusDevice busdev;
+    MemoryRegion mem;
+} IDRegState;
+
+static int idreg_init1(SysBusDevice *dev)
+{
+    IDRegState *s = FROM_SYSBUS(IDRegState, dev);
+
+    memory_region_init_ram(&s->mem, "sun4m.idreg", sizeof(idreg_data));
+    vmstate_register_ram_global(&s->mem);
+    memory_region_set_readonly(&s->mem, true);
+    sysbus_init_mmio(dev, &s->mem);
+    return 0;
+}
+
+static void idreg_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = idreg_init1;
+}
+
+static const TypeInfo idreg_info = {
+    .name          = "macio_idreg",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(IDRegState),
+    .class_init    = idreg_class_init,
+};
+
+typedef struct AFXState {
+    SysBusDevice busdev;
+    MemoryRegion mem;
+} AFXState;
+
+/* SS-5 TCX AFX register */
+static void afx_init(hwaddr addr)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "tcx_afx");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+}
+
+static int afx_init1(SysBusDevice *dev)
+{
+    AFXState *s = FROM_SYSBUS(AFXState, dev);
+
+    memory_region_init_ram(&s->mem, "sun4m.afx", 4);
+    vmstate_register_ram_global(&s->mem);
+    sysbus_init_mmio(dev, &s->mem);
+    return 0;
+}
+
+static void afx_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = afx_init1;
+}
+
+static const TypeInfo afx_info = {
+    .name          = "tcx_afx",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AFXState),
+    .class_init    = afx_class_init,
+};
+
+typedef struct PROMState {
+    SysBusDevice busdev;
+    MemoryRegion prom;
+} PROMState;
+
+/* Boot PROM (OpenBIOS) */
+static uint64_t translate_prom_address(void *opaque, uint64_t addr)
+{
+    hwaddr *base_addr = (hwaddr *)opaque;
+    return addr + *base_addr - PROM_VADDR;
+}
+
+static void prom_init(hwaddr addr, const char *bios_name)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    char *filename;
+    int ret;
+
+    dev = qdev_create(NULL, "openprom");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+
+    /* load boot prom */
+    if (bios_name == NULL) {
+        bios_name = PROM_FILENAME;
+    }
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (filename) {
+        ret = load_elf(filename, translate_prom_address, &addr, NULL,
+                       NULL, NULL, 1, ELF_MACHINE, 0);
+        if (ret < 0 || ret > PROM_SIZE_MAX) {
+            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
+        }
+        g_free(filename);
+    } else {
+        ret = -1;
+    }
+    if (ret < 0 || ret > PROM_SIZE_MAX) {
+        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
+        exit(1);
+    }
+}
+
+static int prom_init1(SysBusDevice *dev)
+{
+    PROMState *s = FROM_SYSBUS(PROMState, dev);
+
+    memory_region_init_ram(&s->prom, "sun4m.prom", PROM_SIZE_MAX);
+    vmstate_register_ram_global(&s->prom);
+    memory_region_set_readonly(&s->prom, true);
+    sysbus_init_mmio(dev, &s->prom);
+    return 0;
+}
+
+static Property prom_properties[] = {
+    {/* end of property list */},
+};
+
+static void prom_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = prom_init1;
+    dc->props = prom_properties;
+}
+
+static const TypeInfo prom_info = {
+    .name          = "openprom",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PROMState),
+    .class_init    = prom_class_init,
+};
+
+typedef struct RamDevice
+{
+    SysBusDevice busdev;
+    MemoryRegion ram;
+    uint64_t size;
+} RamDevice;
+
+/* System RAM */
+static int ram_init1(SysBusDevice *dev)
+{
+    RamDevice *d = FROM_SYSBUS(RamDevice, dev);
+
+    memory_region_init_ram(&d->ram, "sun4m.ram", d->size);
+    vmstate_register_ram_global(&d->ram);
+    sysbus_init_mmio(dev, &d->ram);
+    return 0;
+}
+
+static void ram_init(hwaddr addr, ram_addr_t RAM_size,
+                     uint64_t max_mem)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    RamDevice *d;
+
+    /* allocate RAM */
+    if ((uint64_t)RAM_size > max_mem) {
+        fprintf(stderr,
+                "qemu: Too much memory for this machine: %d, maximum %d\n",
+                (unsigned int)(RAM_size / (1024 * 1024)),
+                (unsigned int)(max_mem / (1024 * 1024)));
+        exit(1);
+    }
+    dev = qdev_create(NULL, "memory");
+    s = SYS_BUS_DEVICE(dev);
+
+    d = FROM_SYSBUS(RamDevice, s);
+    d->size = RAM_size;
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+}
+
+static Property ram_properties[] = {
+    DEFINE_PROP_UINT64("size", RamDevice, size, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ram_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = ram_init1;
+    dc->props = ram_properties;
+}
+
+static const TypeInfo ram_info = {
+    .name          = "memory",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(RamDevice),
+    .class_init    = ram_class_init,
+};
+
+static void cpu_devinit(const char *cpu_model, unsigned int id,
+                        uint64_t prom_addr, qemu_irq **cpu_irqs)
+{
+    SPARCCPU *cpu;
+    CPUSPARCState *env;
+
+    cpu = cpu_sparc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    cpu_sparc_set_id(env, id);
+    if (id == 0) {
+        qemu_register_reset(main_cpu_reset, cpu);
+    } else {
+        qemu_register_reset(secondary_cpu_reset, cpu);
+        env->halted = 1;
+    }
+    *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
+    env->prom_addr = prom_addr;
+}
+
+static void dummy_fdc_tc(void *opaque, int irq, int level)
+{
+}
+
+static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, 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)
+{
+    unsigned int i;
+    void *iommu, *espdma, *ledma, *nvram;
+    qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
+        espdma_irq, ledma_irq;
+    qemu_irq esp_reset, dma_enable;
+    qemu_irq fdc_tc;
+    qemu_irq *cpu_halt;
+    unsigned long kernel_size;
+    DriveInfo *fd[MAX_FD];
+    void *fw_cfg;
+    unsigned int num_vsimms;
+
+    /* init CPUs */
+    if (!cpu_model)
+        cpu_model = hwdef->default_cpu_model;
+
+    for(i = 0; i < smp_cpus; i++) {
+        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
+    }
+
+    for (i = smp_cpus; i < MAX_CPUS; i++)
+        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
+
+
+    /* set up devices */
+    ram_init(0, RAM_size, hwdef->max_mem);
+    /* models without ECC don't trap when missing ram is accessed */
+    if (!hwdef->ecc_base) {
+        empty_slot_init(RAM_size, hwdef->max_mem - RAM_size);
+    }
+
+    prom_init(hwdef->slavio_base, bios_name);
+
+    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
+                                       hwdef->intctl_base + 0x10000ULL,
+                                       cpu_irqs);
+
+    for (i = 0; i < 32; i++) {
+        slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i);
+    }
+    for (i = 0; i < MAX_CPUS; i++) {
+        slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i);
+    }
+
+    if (hwdef->idreg_base) {
+        idreg_init(hwdef->idreg_base);
+    }
+
+    if (hwdef->afx_base) {
+        afx_init(hwdef->afx_base);
+    }
+
+    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
+                       slavio_irq[30]);
+
+    if (hwdef->iommu_pad_base) {
+        /* On the real hardware (SS-5, LX) the MMU is not padded, but aliased.
+           Software shouldn't use aliased addresses, neither should it crash
+           when does. Using empty_slot instead of aliasing can help with
+           debugging such accesses */
+        empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len);
+    }
+
+    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[18],
+                              iommu, &espdma_irq, 0);
+
+    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
+                             slavio_irq[16], iommu, &ledma_irq, 1);
+
+    if (graphic_depth != 8 && graphic_depth != 24) {
+        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
+        exit (1);
+    }
+    num_vsimms = 0;
+    if (num_vsimms == 0) {
+        tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
+                 graphic_depth);
+    }
+
+    for (i = num_vsimms; i < MAX_VSIMMS; i++) {
+        /* vsimm registers probed by OBP */
+        if (hwdef->vsimm[i].reg_base) {
+            empty_slot_init(hwdef->vsimm[i].reg_base, 0x2000);
+        }
+    }
+
+    if (hwdef->sx_base) {
+        empty_slot_init(hwdef->sx_base, 0x2000);
+    }
+
+    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
+
+    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 8);
+
+    slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus);
+
+    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
+                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
+    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
+       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
+    escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
+              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
+
+    cpu_halt = qemu_allocate_irqs(cpu_halt_signal, NULL, 1);
+    if (hwdef->apc_base) {
+        apc_init(hwdef->apc_base, cpu_halt[0]);
+    }
+
+    if (hwdef->fd_base) {
+        /* there is zero or one floppy drive */
+        memset(fd, 0, sizeof(fd));
+        fd[0] = drive_get(IF_FLOPPY, 0, 0);
+        sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd,
+                          &fdc_tc);
+    } else {
+        fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1);
+    }
+
+    slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base,
+                     slavio_irq[30], fdc_tc);
+
+    if (drive_get_max_bus(IF_SCSI) > 0) {
+        fprintf(stderr, "qemu: too many SCSI bus\n");
+        exit(1);
+    }
+
+    esp_init(hwdef->esp_base, 2,
+             espdma_memory_read, espdma_memory_write,
+             espdma, espdma_irq, &esp_reset, &dma_enable);
+
+    qdev_connect_gpio_out(espdma, 0, esp_reset);
+    qdev_connect_gpio_out(espdma, 1, dma_enable);
+
+    if (hwdef->cs_base) {
+        sysbus_create_simple("SUNW,CS4231", hwdef->cs_base,
+                             slavio_irq[5]);
+    }
+
+    if (hwdef->dbri_base) {
+        /* ISDN chip with attached CS4215 audio codec */
+        /* prom space */
+        empty_slot_init(hwdef->dbri_base+0x1000, 0x30);
+        /* reg space */
+        empty_slot_init(hwdef->dbri_base+0x10000, 0x100);
+    }
+
+    if (hwdef->bpp_base) {
+        /* parallel port */
+        empty_slot_init(hwdef->bpp_base, 0x20);
+    }
+
+    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
+                                    RAM_size);
+
+    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
+               boot_device, RAM_size, kernel_size, graphic_width,
+               graphic_height, graphic_depth, hwdef->nvram_machine_id,
+               "Sun4m");
+
+    if (hwdef->ecc_base)
+        ecc_init(hwdef->ecc_base, slavio_irq[28],
+                 hwdef->ecc_version);
+
+    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+    if (kernel_cmdline) {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
+        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
+        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
+                       strlen(kernel_cmdline) + 1);
+    } else {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
+        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
+    }
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
+    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+}
+
+enum {
+    ss2_id = 0,
+    ss5_id = 32,
+    vger_id,
+    lx_id,
+    ss4_id,
+    scls_id,
+    sbook_id,
+    ss10_id = 64,
+    ss20_id,
+    ss600mp_id,
+    ss1000_id = 96,
+    ss2000_id,
+};
+
+static const struct sun4m_hwdef sun4m_hwdefs[] = {
+    /* SS-5 */
+    {
+        .iommu_base   = 0x10000000,
+        .iommu_pad_base = 0x10004000,
+        .iommu_pad_len  = 0x0fffb000,
+        .tcx_base     = 0x50000000,
+        .cs_base      = 0x6c000000,
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .apc_base     = 0x6a000000,
+        .afx_base     = 0x6e000000,
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = ss5_id,
+        .iommu_version = 0x05000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "Fujitsu MB86904",
+    },
+    /* SS-10 */
+    {
+        .iommu_base   = 0xfe0000000ULL,
+        .tcx_base     = 0xe20000000ULL,
+        .slavio_base  = 0xff0000000ULL,
+        .ms_kb_base   = 0xff1000000ULL,
+        .serial_base  = 0xff1100000ULL,
+        .nvram_base   = 0xff1200000ULL,
+        .fd_base      = 0xff1700000ULL,
+        .counter_base = 0xff1300000ULL,
+        .intctl_base  = 0xff1400000ULL,
+        .idreg_base   = 0xef0000000ULL,
+        .dma_base     = 0xef0400000ULL,
+        .esp_base     = 0xef0800000ULL,
+        .le_base      = 0xef0c00000ULL,
+        .apc_base     = 0xefa000000ULL, // XXX should not exist
+        .aux1_base    = 0xff1800000ULL,
+        .aux2_base    = 0xff1a01000ULL,
+        .ecc_base     = 0xf00000000ULL,
+        .ecc_version  = 0x10000000, // version 0, implementation 1
+        .nvram_machine_id = 0x72,
+        .machine_id = ss10_id,
+        .iommu_version = 0x03000000,
+        .max_mem = 0xf00000000ULL,
+        .default_cpu_model = "TI SuperSparc II",
+    },
+    /* SS-600MP */
+    {
+        .iommu_base   = 0xfe0000000ULL,
+        .tcx_base     = 0xe20000000ULL,
+        .slavio_base  = 0xff0000000ULL,
+        .ms_kb_base   = 0xff1000000ULL,
+        .serial_base  = 0xff1100000ULL,
+        .nvram_base   = 0xff1200000ULL,
+        .counter_base = 0xff1300000ULL,
+        .intctl_base  = 0xff1400000ULL,
+        .dma_base     = 0xef0081000ULL,
+        .esp_base     = 0xef0080000ULL,
+        .le_base      = 0xef0060000ULL,
+        .apc_base     = 0xefa000000ULL, // XXX should not exist
+        .aux1_base    = 0xff1800000ULL,
+        .aux2_base    = 0xff1a01000ULL, // XXX should not exist
+        .ecc_base     = 0xf00000000ULL,
+        .ecc_version  = 0x00000000, // version 0, implementation 0
+        .nvram_machine_id = 0x71,
+        .machine_id = ss600mp_id,
+        .iommu_version = 0x01000000,
+        .max_mem = 0xf00000000ULL,
+        .default_cpu_model = "TI SuperSparc II",
+    },
+    /* SS-20 */
+    {
+        .iommu_base   = 0xfe0000000ULL,
+        .tcx_base     = 0xe20000000ULL,
+        .slavio_base  = 0xff0000000ULL,
+        .ms_kb_base   = 0xff1000000ULL,
+        .serial_base  = 0xff1100000ULL,
+        .nvram_base   = 0xff1200000ULL,
+        .fd_base      = 0xff1700000ULL,
+        .counter_base = 0xff1300000ULL,
+        .intctl_base  = 0xff1400000ULL,
+        .idreg_base   = 0xef0000000ULL,
+        .dma_base     = 0xef0400000ULL,
+        .esp_base     = 0xef0800000ULL,
+        .le_base      = 0xef0c00000ULL,
+        .bpp_base     = 0xef4800000ULL,
+        .apc_base     = 0xefa000000ULL, // XXX should not exist
+        .aux1_base    = 0xff1800000ULL,
+        .aux2_base    = 0xff1a01000ULL,
+        .dbri_base    = 0xee0000000ULL,
+        .sx_base      = 0xf80000000ULL,
+        .vsimm        = {
+            {
+                .reg_base  = 0x9c000000ULL,
+                .vram_base = 0xfc000000ULL
+            }, {
+                .reg_base  = 0x90000000ULL,
+                .vram_base = 0xf0000000ULL
+            }, {
+                .reg_base  = 0x94000000ULL
+            }, {
+                .reg_base  = 0x98000000ULL
+            }
+        },
+        .ecc_base     = 0xf00000000ULL,
+        .ecc_version  = 0x20000000, // version 0, implementation 2
+        .nvram_machine_id = 0x72,
+        .machine_id = ss20_id,
+        .iommu_version = 0x13000000,
+        .max_mem = 0xf00000000ULL,
+        .default_cpu_model = "TI SuperSparc II",
+    },
+    /* Voyager */
+    {
+        .iommu_base   = 0x10000000,
+        .tcx_base     = 0x50000000,
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .apc_base     = 0x71300000, // pmc
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = vger_id,
+        .iommu_version = 0x05000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "Fujitsu MB86904",
+    },
+    /* LX */
+    {
+        .iommu_base   = 0x10000000,
+        .iommu_pad_base = 0x10004000,
+        .iommu_pad_len  = 0x0fffb000,
+        .tcx_base     = 0x50000000,
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = lx_id,
+        .iommu_version = 0x04000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "TI MicroSparc I",
+    },
+    /* SS-4 */
+    {
+        .iommu_base   = 0x10000000,
+        .tcx_base     = 0x50000000,
+        .cs_base      = 0x6c000000,
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .apc_base     = 0x6a000000,
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = ss4_id,
+        .iommu_version = 0x05000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "Fujitsu MB86904",
+    },
+    /* SPARCClassic */
+    {
+        .iommu_base   = 0x10000000,
+        .tcx_base     = 0x50000000,
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .apc_base     = 0x6a000000,
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = scls_id,
+        .iommu_version = 0x05000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "TI MicroSparc I",
+    },
+    /* SPARCbook */
+    {
+        .iommu_base   = 0x10000000,
+        .tcx_base     = 0x50000000, // XXX
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .apc_base     = 0x6a000000,
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = sbook_id,
+        .iommu_version = 0x05000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "TI MicroSparc I",
+    },
+};
+
+/* SPARCstation 5 hardware initialisation */
+static void ss5_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[0], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCstation 10 hardware initialisation */
+static void ss10_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[1], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCserver 600MP hardware initialisation */
+static void ss600mp_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[2], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCstation 20 hardware initialisation */
+static void ss20_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[3], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCstation Voyager hardware initialisation */
+static void vger_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[4], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCstation LX hardware initialisation */
+static void ss_lx_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[5], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCstation 4 hardware initialisation */
+static void ss4_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[6], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCClassic hardware initialisation */
+static void scls_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[7], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCbook hardware initialisation */
+static void sbook_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[8], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+static QEMUMachine ss5_machine = {
+    .name = "SS-5",
+    .desc = "Sun4m platform, SPARCstation 5",
+    .init = ss5_init,
+    .block_default_type = IF_SCSI,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss10_machine = {
+    .name = "SS-10",
+    .desc = "Sun4m platform, SPARCstation 10",
+    .init = ss10_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss600mp_machine = {
+    .name = "SS-600MP",
+    .desc = "Sun4m platform, SPARCserver 600MP",
+    .init = ss600mp_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss20_machine = {
+    .name = "SS-20",
+    .desc = "Sun4m platform, SPARCstation 20",
+    .init = ss20_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine voyager_machine = {
+    .name = "Voyager",
+    .desc = "Sun4m platform, SPARCstation Voyager",
+    .init = vger_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss_lx_machine = {
+    .name = "LX",
+    .desc = "Sun4m platform, SPARCstation LX",
+    .init = ss_lx_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss4_machine = {
+    .name = "SS-4",
+    .desc = "Sun4m platform, SPARCstation 4",
+    .init = ss4_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine scls_machine = {
+    .name = "SPARCClassic",
+    .desc = "Sun4m platform, SPARCClassic",
+    .init = scls_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine sbook_machine = {
+    .name = "SPARCbook",
+    .desc = "Sun4m platform, SPARCbook",
+    .init = sbook_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static const struct sun4d_hwdef sun4d_hwdefs[] = {
+    /* SS-1000 */
+    {
+        .iounit_bases   = {
+            0xfe0200000ULL,
+            0xfe1200000ULL,
+            0xfe2200000ULL,
+            0xfe3200000ULL,
+            -1,
+        },
+        .tcx_base     = 0x820000000ULL,
+        .slavio_base  = 0xf00000000ULL,
+        .ms_kb_base   = 0xf00240000ULL,
+        .serial_base  = 0xf00200000ULL,
+        .nvram_base   = 0xf00280000ULL,
+        .counter_base = 0xf00300000ULL,
+        .espdma_base  = 0x800081000ULL,
+        .esp_base     = 0x800080000ULL,
+        .ledma_base   = 0x800040000ULL,
+        .le_base      = 0x800060000ULL,
+        .sbi_base     = 0xf02800000ULL,
+        .nvram_machine_id = 0x80,
+        .machine_id = ss1000_id,
+        .iounit_version = 0x03000000,
+        .max_mem = 0xf00000000ULL,
+        .default_cpu_model = "TI SuperSparc II",
+    },
+    /* SS-2000 */
+    {
+        .iounit_bases   = {
+            0xfe0200000ULL,
+            0xfe1200000ULL,
+            0xfe2200000ULL,
+            0xfe3200000ULL,
+            0xfe4200000ULL,
+        },
+        .tcx_base     = 0x820000000ULL,
+        .slavio_base  = 0xf00000000ULL,
+        .ms_kb_base   = 0xf00240000ULL,
+        .serial_base  = 0xf00200000ULL,
+        .nvram_base   = 0xf00280000ULL,
+        .counter_base = 0xf00300000ULL,
+        .espdma_base  = 0x800081000ULL,
+        .esp_base     = 0x800080000ULL,
+        .ledma_base   = 0x800040000ULL,
+        .le_base      = 0x800060000ULL,
+        .sbi_base     = 0xf02800000ULL,
+        .nvram_machine_id = 0x80,
+        .machine_id = ss2000_id,
+        .iounit_version = 0x03000000,
+        .max_mem = 0xf00000000ULL,
+        .default_cpu_model = "TI SuperSparc II",
+    },
+};
+
+static DeviceState *sbi_init(hwaddr addr, qemu_irq **parent_irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    unsigned int i;
+
+    dev = qdev_create(NULL, "sbi");
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+
+    for (i = 0; i < MAX_CPUS; i++) {
+        sysbus_connect_irq(s, i, *parent_irq[i]);
+    }
+
+    sysbus_mmio_map(s, 0, addr);
+
+    return dev;
+}
+
+static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, 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)
+{
+    unsigned int i;
+    void *iounits[MAX_IOUNITS], *espdma, *ledma, *nvram;
+    qemu_irq *cpu_irqs[MAX_CPUS], sbi_irq[32], sbi_cpu_irq[MAX_CPUS],
+        espdma_irq, ledma_irq;
+    qemu_irq esp_reset, dma_enable;
+    unsigned long kernel_size;
+    void *fw_cfg;
+    DeviceState *dev;
+
+    /* init CPUs */
+    if (!cpu_model)
+        cpu_model = hwdef->default_cpu_model;
+
+    for(i = 0; i < smp_cpus; i++) {
+        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
+    }
+
+    for (i = smp_cpus; i < MAX_CPUS; i++)
+        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
+
+    /* set up devices */
+    ram_init(0, RAM_size, hwdef->max_mem);
+
+    prom_init(hwdef->slavio_base, bios_name);
+
+    dev = sbi_init(hwdef->sbi_base, cpu_irqs);
+
+    for (i = 0; i < 32; i++) {
+        sbi_irq[i] = qdev_get_gpio_in(dev, i);
+    }
+    for (i = 0; i < MAX_CPUS; i++) {
+        sbi_cpu_irq[i] = qdev_get_gpio_in(dev, 32 + i);
+    }
+
+    for (i = 0; i < MAX_IOUNITS; i++)
+        if (hwdef->iounit_bases[i] != (hwaddr)-1)
+            iounits[i] = iommu_init(hwdef->iounit_bases[i],
+                                    hwdef->iounit_version,
+                                    sbi_irq[0]);
+
+    espdma = sparc32_dma_init(hwdef->espdma_base, sbi_irq[3],
+                              iounits[0], &espdma_irq, 0);
+
+    /* should be lebuffer instead */
+    ledma = sparc32_dma_init(hwdef->ledma_base, sbi_irq[4],
+                             iounits[0], &ledma_irq, 0);
+
+    if (graphic_depth != 8 && graphic_depth != 24) {
+        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
+        exit (1);
+    }
+    tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
+             graphic_depth);
+
+    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
+
+    nvram = m48t59_init(sbi_irq[0], hwdef->nvram_base, 0, 0x2000, 8);
+
+    slavio_timer_init_all(hwdef->counter_base, sbi_irq[10], sbi_cpu_irq, smp_cpus);
+
+    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, sbi_irq[12],
+                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
+    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
+       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
+    escc_init(hwdef->serial_base, sbi_irq[12], sbi_irq[12],
+              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
+
+    if (drive_get_max_bus(IF_SCSI) > 0) {
+        fprintf(stderr, "qemu: too many SCSI bus\n");
+        exit(1);
+    }
+
+    esp_init(hwdef->esp_base, 2,
+             espdma_memory_read, espdma_memory_write,
+             espdma, espdma_irq, &esp_reset, &dma_enable);
+
+    qdev_connect_gpio_out(espdma, 0, esp_reset);
+    qdev_connect_gpio_out(espdma, 1, dma_enable);
+
+    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
+                                    RAM_size);
+
+    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
+               boot_device, RAM_size, kernel_size, graphic_width,
+               graphic_height, graphic_depth, hwdef->nvram_machine_id,
+               "Sun4d");
+
+    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+    if (kernel_cmdline) {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
+        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
+        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+    } else {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
+    }
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
+    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+}
+
+/* SPARCserver 1000 hardware initialisation */
+static void ss1000_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4d_hw_init(&sun4d_hwdefs[0], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCcenter 2000 hardware initialisation */
+static void ss2000_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4d_hw_init(&sun4d_hwdefs[1], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+static QEMUMachine ss1000_machine = {
+    .name = "SS-1000",
+    .desc = "Sun4d platform, SPARCserver 1000",
+    .init = ss1000_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 8,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss2000_machine = {
+    .name = "SS-2000",
+    .desc = "Sun4d platform, SPARCcenter 2000",
+    .init = ss2000_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 20,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static const struct sun4c_hwdef sun4c_hwdefs[] = {
+    /* SS-2 */
+    {
+        .iommu_base   = 0xf8000000,
+        .tcx_base     = 0xfe000000,
+        .slavio_base  = 0xf6000000,
+        .intctl_base  = 0xf5000000,
+        .counter_base = 0xf3000000,
+        .ms_kb_base   = 0xf0000000,
+        .serial_base  = 0xf1000000,
+        .nvram_base   = 0xf2000000,
+        .fd_base      = 0xf7200000,
+        .dma_base     = 0xf8400000,
+        .esp_base     = 0xf8800000,
+        .le_base      = 0xf8c00000,
+        .aux1_base    = 0xf7400003,
+        .nvram_machine_id = 0x55,
+        .machine_id = ss2_id,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "Cypress CY7C601",
+    },
+};
+
+static DeviceState *sun4c_intctl_init(hwaddr addr,
+                                      qemu_irq *parent_irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    unsigned int i;
+
+    dev = qdev_create(NULL, "sun4c_intctl");
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+
+    for (i = 0; i < MAX_PILS; i++) {
+        sysbus_connect_irq(s, i, parent_irq[i]);
+    }
+    sysbus_mmio_map(s, 0, addr);
+
+    return dev;
+}
+
+static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, 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)
+{
+    void *iommu, *espdma, *ledma, *nvram;
+    qemu_irq *cpu_irqs, slavio_irq[8], espdma_irq, ledma_irq;
+    qemu_irq esp_reset, dma_enable;
+    qemu_irq fdc_tc;
+    unsigned long kernel_size;
+    DriveInfo *fd[MAX_FD];
+    void *fw_cfg;
+    DeviceState *dev;
+    unsigned int i;
+
+    /* init CPU */
+    if (!cpu_model)
+        cpu_model = hwdef->default_cpu_model;
+
+    cpu_devinit(cpu_model, 0, hwdef->slavio_base, &cpu_irqs);
+
+    /* set up devices */
+    ram_init(0, RAM_size, hwdef->max_mem);
+
+    prom_init(hwdef->slavio_base, bios_name);
+
+    dev = sun4c_intctl_init(hwdef->intctl_base, cpu_irqs);
+
+    for (i = 0; i < 8; i++) {
+        slavio_irq[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
+                       slavio_irq[1]);
+
+    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[2],
+                              iommu, &espdma_irq, 0);
+
+    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
+                             slavio_irq[3], iommu, &ledma_irq, 1);
+
+    if (graphic_depth != 8 && graphic_depth != 24) {
+        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
+        exit (1);
+    }
+    tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
+             graphic_depth);
+
+    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
+
+    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x800, 2);
+
+    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[1],
+                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
+    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
+       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
+    escc_init(hwdef->serial_base, slavio_irq[1],
+              slavio_irq[1], serial_hds[0], serial_hds[1],
+              ESCC_CLOCK, 1);
+
+    if (hwdef->fd_base != (hwaddr)-1) {
+        /* there is zero or one floppy drive */
+        memset(fd, 0, sizeof(fd));
+        fd[0] = drive_get(IF_FLOPPY, 0, 0);
+        sun4m_fdctrl_init(slavio_irq[1], hwdef->fd_base, fd,
+                          &fdc_tc);
+    } else {
+        fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1);
+    }
+
+    slavio_misc_init(0, hwdef->aux1_base, 0, slavio_irq[1], fdc_tc);
+
+    if (drive_get_max_bus(IF_SCSI) > 0) {
+        fprintf(stderr, "qemu: too many SCSI bus\n");
+        exit(1);
+    }
+
+    esp_init(hwdef->esp_base, 2,
+             espdma_memory_read, espdma_memory_write,
+             espdma, espdma_irq, &esp_reset, &dma_enable);
+
+    qdev_connect_gpio_out(espdma, 0, esp_reset);
+    qdev_connect_gpio_out(espdma, 1, dma_enable);
+
+    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
+                                    RAM_size);
+
+    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
+               boot_device, RAM_size, kernel_size, graphic_width,
+               graphic_height, graphic_depth, hwdef->nvram_machine_id,
+               "Sun4c");
+
+    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+    if (kernel_cmdline) {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
+        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
+        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+    } else {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
+    }
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
+    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+}
+
+/* SPARCstation 2 hardware initialisation */
+static void ss2_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4c_hw_init(&sun4c_hwdefs[0], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+static QEMUMachine ss2_machine = {
+    .name = "SS-2",
+    .desc = "Sun4c platform, SPARCstation 2",
+    .init = ss2_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void sun4m_register_types(void)
+{
+    type_register_static(&idreg_info);
+    type_register_static(&afx_info);
+    type_register_static(&prom_info);
+    type_register_static(&ram_info);
+}
+
+static void ss2_machine_init(void)
+{
+    qemu_register_machine(&ss5_machine);
+    qemu_register_machine(&ss10_machine);
+    qemu_register_machine(&ss600mp_machine);
+    qemu_register_machine(&ss20_machine);
+    qemu_register_machine(&voyager_machine);
+    qemu_register_machine(&ss_lx_machine);
+    qemu_register_machine(&ss4_machine);
+    qemu_register_machine(&scls_machine);
+    qemu_register_machine(&sbook_machine);
+    qemu_register_machine(&ss1000_machine);
+    qemu_register_machine(&ss2000_machine);
+    qemu_register_machine(&ss2_machine);
+}
+
+type_init(sun4m_register_types)
+machine_init(ss2_machine_init);
index 6d0df51749c7e9505ceebffd78583d5d20faa7fd..18e368ec98cb26a09de8493f1b747b84bb9feb75 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "sparc32_dma.h"
-#include "sun4m.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sparc32_dma.h"
+#include "hw/sun4m.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /*
index 8c65fc4215484f31f52a4afeeacd160b9eb8675b..4df0d90ec24cdacc3a294751839bd39c7909dbe6 100644 (file)
@@ -1,4 +1,6 @@
-obj-y = sun4u.o apb_pci.o
+obj-y = apb_pci.o
 obj-y += mc146818rtc.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += sun4u.o
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
new file mode 100644 (file)
index 0000000..51ffa1c
--- /dev/null
@@ -0,0 +1,1014 @@
+/*
+ * QEMU Sun4u/Sun4v System Emulator
+ *
+ * Copyright (c) 2005 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/apb_pci.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/nvram.h"
+#include "hw/fdc.h"
+#include "net/net.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/firmware_abi.h"
+#include "hw/fw_cfg.h"
+#include "hw/sysbus.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+//#define DEBUG_IRQ
+//#define DEBUG_EBUS
+//#define DEBUG_TIMER
+
+#ifdef DEBUG_IRQ
+#define CPUIRQ_DPRINTF(fmt, ...)                                \
+    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define CPUIRQ_DPRINTF(fmt, ...)
+#endif
+
+#ifdef DEBUG_EBUS
+#define EBUS_DPRINTF(fmt, ...)                                  \
+    do { printf("EBUS: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define EBUS_DPRINTF(fmt, ...)
+#endif
+
+#ifdef DEBUG_TIMER
+#define TIMER_DPRINTF(fmt, ...)                                  \
+    do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define TIMER_DPRINTF(fmt, ...)
+#endif
+
+#define KERNEL_LOAD_ADDR     0x00404000
+#define CMDLINE_ADDR         0x003ff000
+#define PROM_SIZE_MAX        (4 * 1024 * 1024)
+#define PROM_VADDR           0x000ffd00000ULL
+#define APB_SPECIAL_BASE     0x1fe00000000ULL
+#define APB_MEM_BASE         0x1ff00000000ULL
+#define APB_PCI_IO_BASE      (APB_SPECIAL_BASE + 0x02000000ULL)
+#define PROM_FILENAME        "openbios-sparc64"
+#define NVRAM_SIZE           0x2000
+#define MAX_IDE_BUS          2
+#define BIOS_CFG_IOPORT      0x510
+#define FW_CFG_SPARC64_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
+#define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
+#define FW_CFG_SPARC64_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
+
+#define IVEC_MAX             0x30
+
+#define TICK_MAX             0x7fffffffffffffffULL
+
+struct hwdef {
+    const char * const default_cpu_model;
+    uint16_t machine_id;
+    uint64_t prom_addr;
+    uint64_t console_serial_base;
+};
+
+typedef struct EbusState {
+    PCIDevice pci_dev;
+    MemoryRegion bar0;
+    MemoryRegion bar1;
+} EbusState;
+
+int DMA_get_channel_mode (int nchan)
+{
+    return 0;
+}
+int DMA_read_memory (int nchan, void *buf, int pos, int size)
+{
+    return 0;
+}
+int DMA_write_memory (int nchan, void *buf, int pos, int size)
+{
+    return 0;
+}
+void DMA_hold_DREQ (int nchan) {}
+void DMA_release_DREQ (int nchan) {}
+void DMA_schedule(int nchan) {}
+
+void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
+{
+}
+
+void DMA_register_channel (int nchan,
+                           DMA_transfer_handler transfer_handler,
+                           void *opaque)
+{
+}
+
+static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+{
+    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
+    return 0;
+}
+
+static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
+                                  const char *arch, ram_addr_t RAM_size,
+                                  const char *boot_devices,
+                                  uint32_t kernel_image, uint32_t kernel_size,
+                                  const char *cmdline,
+                                  uint32_t initrd_image, uint32_t initrd_size,
+                                  uint32_t NVRAM_image,
+                                  int width, int height, int depth,
+                                  const uint8_t *macaddr)
+{
+    unsigned int i;
+    uint32_t start, end;
+    uint8_t image[0x1ff0];
+    struct OpenBIOS_nvpart_v1 *part_header;
+
+    memset(image, '\0', sizeof(image));
+
+    start = 0;
+
+    // OpenBIOS nvram variables
+    // Variable partition
+    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
+    part_header->signature = OPENBIOS_PART_SYSTEM;
+    pstrcpy(part_header->name, sizeof(part_header->name), "system");
+
+    end = start + sizeof(struct OpenBIOS_nvpart_v1);
+    for (i = 0; i < nb_prom_envs; i++)
+        end = OpenBIOS_set_var(image, end, prom_envs[i]);
+
+    // End marker
+    image[end++] = '\0';
+
+    end = start + ((end - start + 15) & ~15);
+    OpenBIOS_finish_partition(part_header, end - start);
+
+    // free partition
+    start = end;
+    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
+    part_header->signature = OPENBIOS_PART_FREE;
+    pstrcpy(part_header->name, sizeof(part_header->name), "free");
+
+    end = 0x1fd0;
+    OpenBIOS_finish_partition(part_header, end - start);
+
+    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr, 0x80);
+
+    for (i = 0; i < sizeof(image); i++)
+        m48t59_write(nvram, i, image[i]);
+
+    return 0;
+}
+
+static uint64_t sun4u_load_kernel(const char *kernel_filename,
+                                  const char *initrd_filename,
+                                  ram_addr_t RAM_size, uint64_t *initrd_size,
+                                  uint64_t *initrd_addr, uint64_t *kernel_addr,
+                                  uint64_t *kernel_entry)
+{
+    int linux_boot;
+    unsigned int i;
+    long kernel_size;
+    uint8_t *ptr;
+    uint64_t kernel_top;
+
+    linux_boot = (kernel_filename != NULL);
+
+    kernel_size = 0;
+    if (linux_boot) {
+        int bswap_needed;
+
+#ifdef BSWAP_NEEDED
+        bswap_needed = 1;
+#else
+        bswap_needed = 0;
+#endif
+        kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
+                               kernel_addr, &kernel_top, 1, ELF_MACHINE, 0);
+        if (kernel_size < 0) {
+            *kernel_addr = KERNEL_LOAD_ADDR;
+            *kernel_entry = KERNEL_LOAD_ADDR;
+            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
+                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
+                                    TARGET_PAGE_SIZE);
+        }
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename,
+                                              KERNEL_LOAD_ADDR,
+                                              RAM_size - KERNEL_LOAD_ADDR);
+        }
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+        /* load initrd above kernel */
+        *initrd_size = 0;
+        if (initrd_filename) {
+            *initrd_addr = TARGET_PAGE_ALIGN(kernel_top);
+
+            *initrd_size = load_image_targphys(initrd_filename,
+                                               *initrd_addr,
+                                               RAM_size - *initrd_addr);
+            if ((int)*initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+        }
+        if (*initrd_size > 0) {
+            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
+                ptr = rom_ptr(*kernel_addr + i);
+                if (ldl_p(ptr + 8) == 0x48647253) { /* HdrS */
+                    stl_p(ptr + 24, *initrd_addr + *kernel_addr);
+                    stl_p(ptr + 28, *initrd_size);
+                    break;
+                }
+            }
+        }
+    }
+    return kernel_size;
+}
+
+void cpu_check_irqs(CPUSPARCState *env)
+{
+    uint32_t pil = env->pil_in |
+                  (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
+
+    /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */
+    if (env->ivec_status & 0x20) {
+        return;
+    }
+    /* check if TM or SM in SOFTINT are set
+       setting these also causes interrupt 14 */
+    if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
+        pil |= 1 << 14;
+    }
+
+    /* The bit corresponding to psrpil is (1<< psrpil), the next bit
+       is (2 << psrpil). */
+    if (pil < (2 << env->psrpil)){
+        if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+            CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
+                           env->interrupt_index);
+            env->interrupt_index = 0;
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        }
+        return;
+    }
+
+    if (cpu_interrupts_enabled(env)) {
+
+        unsigned int i;
+
+        for (i = 15; i > env->psrpil; i--) {
+            if (pil & (1 << i)) {
+                int old_interrupt = env->interrupt_index;
+                int new_interrupt = TT_EXTINT | i;
+
+                if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
+                  && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
+                    CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
+                                   "current %x >= pending %x\n",
+                                   env->tl, cpu_tsptr(env)->tt, new_interrupt);
+                } else if (old_interrupt != new_interrupt) {
+                    env->interrupt_index = new_interrupt;
+                    CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
+                                   old_interrupt, new_interrupt);
+                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                }
+                break;
+            }
+        }
+    } else if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
+                       "current interrupt %x\n",
+                       pil, env->pil_in, env->softint, env->interrupt_index);
+        env->interrupt_index = 0;
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void cpu_kick_irq(SPARCCPU *cpu)
+{
+    CPUSPARCState *env = &cpu->env;
+
+    env->halted = 0;
+    cpu_check_irqs(env);
+    qemu_cpu_kick(CPU(cpu));
+}
+
+static void cpu_set_ivec_irq(void *opaque, int irq, int level)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    if (level) {
+        if (!(env->ivec_status & 0x20)) {
+            CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
+            env->halted = 0;
+            env->interrupt_index = TT_IVEC;
+            env->ivec_status |= 0x20;
+            env->ivec_data[0] = (0x1f << 6) | irq;
+            env->ivec_data[1] = 0;
+            env->ivec_data[2] = 0;
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        }
+    } else {
+        if (env->ivec_status & 0x20) {
+            CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
+            env->ivec_status &= ~0x20;
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        }
+    }
+}
+
+typedef struct ResetData {
+    SPARCCPU *cpu;
+    uint64_t prom_addr;
+} ResetData;
+
+void cpu_put_timer(QEMUFile *f, CPUTimer *s)
+{
+    qemu_put_be32s(f, &s->frequency);
+    qemu_put_be32s(f, &s->disabled);
+    qemu_put_be64s(f, &s->disabled_mask);
+    qemu_put_sbe64s(f, &s->clock_offset);
+
+    qemu_put_timer(f, s->qtimer);
+}
+
+void cpu_get_timer(QEMUFile *f, CPUTimer *s)
+{
+    qemu_get_be32s(f, &s->frequency);
+    qemu_get_be32s(f, &s->disabled);
+    qemu_get_be64s(f, &s->disabled_mask);
+    qemu_get_sbe64s(f, &s->clock_offset);
+
+    qemu_get_timer(f, s->qtimer);
+}
+
+static CPUTimer *cpu_timer_create(const char *name, SPARCCPU *cpu,
+                                  QEMUBHFunc *cb, uint32_t frequency,
+                                  uint64_t disabled_mask)
+{
+    CPUTimer *timer = g_malloc0(sizeof (CPUTimer));
+
+    timer->name = name;
+    timer->frequency = frequency;
+    timer->disabled_mask = disabled_mask;
+
+    timer->disabled = 1;
+    timer->clock_offset = qemu_get_clock_ns(vm_clock);
+
+    timer->qtimer = qemu_new_timer_ns(vm_clock, cb, cpu);
+
+    return timer;
+}
+
+static void cpu_timer_reset(CPUTimer *timer)
+{
+    timer->disabled = 1;
+    timer->clock_offset = qemu_get_clock_ns(vm_clock);
+
+    qemu_del_timer(timer->qtimer);
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetData *s = (ResetData *)opaque;
+    CPUSPARCState *env = &s->cpu->env;
+    static unsigned int nr_resets;
+
+    cpu_reset(CPU(s->cpu));
+
+    cpu_timer_reset(env->tick);
+    cpu_timer_reset(env->stick);
+    cpu_timer_reset(env->hstick);
+
+    env->gregs[1] = 0; // Memory start
+    env->gregs[2] = ram_size; // Memory size
+    env->gregs[3] = 0; // Machine description XXX
+    if (nr_resets++ == 0) {
+        /* Power on reset */
+        env->pc = s->prom_addr + 0x20ULL;
+    } else {
+        env->pc = s->prom_addr + 0x40ULL;
+    }
+    env->npc = env->pc + 4;
+}
+
+static void tick_irq(void *opaque)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    CPUTimer* timer = env->tick;
+
+    if (timer->disabled) {
+        CPUIRQ_DPRINTF("tick_irq: softint disabled\n");
+        return;
+    } else {
+        CPUIRQ_DPRINTF("tick: fire\n");
+    }
+
+    env->softint |= SOFTINT_TIMER;
+    cpu_kick_irq(cpu);
+}
+
+static void stick_irq(void *opaque)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    CPUTimer* timer = env->stick;
+
+    if (timer->disabled) {
+        CPUIRQ_DPRINTF("stick_irq: softint disabled\n");
+        return;
+    } else {
+        CPUIRQ_DPRINTF("stick: fire\n");
+    }
+
+    env->softint |= SOFTINT_STIMER;
+    cpu_kick_irq(cpu);
+}
+
+static void hstick_irq(void *opaque)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    CPUTimer* timer = env->hstick;
+
+    if (timer->disabled) {
+        CPUIRQ_DPRINTF("hstick_irq: softint disabled\n");
+        return;
+    } else {
+        CPUIRQ_DPRINTF("hstick: fire\n");
+    }
+
+    env->softint |= SOFTINT_STIMER;
+    cpu_kick_irq(cpu);
+}
+
+static int64_t cpu_to_timer_ticks(int64_t cpu_ticks, uint32_t frequency)
+{
+    return muldiv64(cpu_ticks, get_ticks_per_sec(), frequency);
+}
+
+static uint64_t timer_to_cpu_ticks(int64_t timer_ticks, uint32_t frequency)
+{
+    return muldiv64(timer_ticks, frequency, get_ticks_per_sec());
+}
+
+void cpu_tick_set_count(CPUTimer *timer, uint64_t count)
+{
+    uint64_t real_count = count & ~timer->disabled_mask;
+    uint64_t disabled_bit = count & timer->disabled_mask;
+
+    int64_t vm_clock_offset = qemu_get_clock_ns(vm_clock) -
+                    cpu_to_timer_ticks(real_count, timer->frequency);
+
+    TIMER_DPRINTF("%s set_count count=0x%016lx (%s) p=%p\n",
+                  timer->name, real_count,
+                  timer->disabled?"disabled":"enabled", timer);
+
+    timer->disabled = disabled_bit ? 1 : 0;
+    timer->clock_offset = vm_clock_offset;
+}
+
+uint64_t cpu_tick_get_count(CPUTimer *timer)
+{
+    uint64_t real_count = timer_to_cpu_ticks(
+                    qemu_get_clock_ns(vm_clock) - timer->clock_offset,
+                    timer->frequency);
+
+    TIMER_DPRINTF("%s get_count count=0x%016lx (%s) p=%p\n",
+           timer->name, real_count,
+           timer->disabled?"disabled":"enabled", timer);
+
+    if (timer->disabled)
+        real_count |= timer->disabled_mask;
+
+    return real_count;
+}
+
+void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
+{
+    int64_t now = qemu_get_clock_ns(vm_clock);
+
+    uint64_t real_limit = limit & ~timer->disabled_mask;
+    timer->disabled = (limit & timer->disabled_mask) ? 1 : 0;
+
+    int64_t expires = cpu_to_timer_ticks(real_limit, timer->frequency) +
+                    timer->clock_offset;
+
+    if (expires < now) {
+        expires = now + 1;
+    }
+
+    TIMER_DPRINTF("%s set_limit limit=0x%016lx (%s) p=%p "
+                  "called with limit=0x%016lx at 0x%016lx (delta=0x%016lx)\n",
+                  timer->name, real_limit,
+                  timer->disabled?"disabled":"enabled",
+                  timer, limit,
+                  timer_to_cpu_ticks(now - timer->clock_offset,
+                                     timer->frequency),
+                  timer_to_cpu_ticks(expires - now, timer->frequency));
+
+    if (!real_limit) {
+        TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n",
+                timer->name);
+        qemu_del_timer(timer->qtimer);
+    } else if (timer->disabled) {
+        qemu_del_timer(timer->qtimer);
+    } else {
+        qemu_mod_timer(timer->qtimer, expires);
+    }
+}
+
+static void isa_irq_handler(void *opaque, int n, int level)
+{
+    static const int isa_irq_to_ivec[16] = {
+        [1] = 0x29, /* keyboard */
+        [4] = 0x2b, /* serial */
+        [6] = 0x27, /* floppy */
+        [7] = 0x22, /* parallel */
+        [12] = 0x2a, /* mouse */
+    };
+    qemu_irq *irqs = opaque;
+    int ivec;
+
+    assert(n < 16);
+    ivec = isa_irq_to_ivec[n];
+    EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec);
+    if (ivec) {
+        qemu_set_irq(irqs[ivec], level);
+    }
+}
+
+/* EBUS (Eight bit bus) bridge */
+static ISABus *
+pci_ebus_init(PCIBus *bus, int devfn, qemu_irq *irqs)
+{
+    qemu_irq *isa_irq;
+    PCIDevice *pci_dev;
+    ISABus *isa_bus;
+
+    pci_dev = pci_create_simple(bus, devfn, "ebus");
+    isa_bus = DO_UPCAST(ISABus, qbus,
+                        qdev_get_child_bus(&pci_dev->qdev, "isa.0"));
+    isa_irq = qemu_allocate_irqs(isa_irq_handler, irqs, 16);
+    isa_bus_irqs(isa_bus, isa_irq);
+    return isa_bus;
+}
+
+static int
+pci_ebus_init1(PCIDevice *pci_dev)
+{
+    EbusState *s = DO_UPCAST(EbusState, pci_dev, pci_dev);
+
+    isa_bus_new(&pci_dev->qdev, pci_address_space_io(pci_dev));
+
+    pci_dev->config[0x04] = 0x06; // command = bus master, pci mem
+    pci_dev->config[0x05] = 0x00;
+    pci_dev->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
+    pci_dev->config[0x07] = 0x03; // status = medium devsel
+    pci_dev->config[0x09] = 0x00; // programming i/f
+    pci_dev->config[0x0D] = 0x0a; // latency_timer
+
+    isa_mmio_setup(&s->bar0, 0x1000000);
+    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
+    isa_mmio_setup(&s->bar1, 0x800000);
+    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1);
+    return 0;
+}
+
+static void ebus_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_ebus_init1;
+    k->vendor_id = PCI_VENDOR_ID_SUN;
+    k->device_id = PCI_DEVICE_ID_SUN_EBUS;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_BRIDGE_OTHER;
+}
+
+static const TypeInfo ebus_info = {
+    .name          = "ebus",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(EbusState),
+    .class_init    = ebus_class_init,
+};
+
+typedef struct PROMState {
+    SysBusDevice busdev;
+    MemoryRegion prom;
+} PROMState;
+
+static uint64_t translate_prom_address(void *opaque, uint64_t addr)
+{
+    hwaddr *base_addr = (hwaddr *)opaque;
+    return addr + *base_addr - PROM_VADDR;
+}
+
+/* Boot PROM (OpenBIOS) */
+static void prom_init(hwaddr addr, const char *bios_name)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    char *filename;
+    int ret;
+
+    dev = qdev_create(NULL, "openprom");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+
+    /* load boot prom */
+    if (bios_name == NULL) {
+        bios_name = PROM_FILENAME;
+    }
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (filename) {
+        ret = load_elf(filename, translate_prom_address, &addr,
+                       NULL, NULL, NULL, 1, ELF_MACHINE, 0);
+        if (ret < 0 || ret > PROM_SIZE_MAX) {
+            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
+        }
+        g_free(filename);
+    } else {
+        ret = -1;
+    }
+    if (ret < 0 || ret > PROM_SIZE_MAX) {
+        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
+        exit(1);
+    }
+}
+
+static int prom_init1(SysBusDevice *dev)
+{
+    PROMState *s = FROM_SYSBUS(PROMState, dev);
+
+    memory_region_init_ram(&s->prom, "sun4u.prom", PROM_SIZE_MAX);
+    vmstate_register_ram_global(&s->prom);
+    memory_region_set_readonly(&s->prom, true);
+    sysbus_init_mmio(dev, &s->prom);
+    return 0;
+}
+
+static Property prom_properties[] = {
+    {/* end of property list */},
+};
+
+static void prom_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = prom_init1;
+    dc->props = prom_properties;
+}
+
+static const TypeInfo prom_info = {
+    .name          = "openprom",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PROMState),
+    .class_init    = prom_class_init,
+};
+
+
+typedef struct RamDevice
+{
+    SysBusDevice busdev;
+    MemoryRegion ram;
+    uint64_t size;
+} RamDevice;
+
+/* System RAM */
+static int ram_init1(SysBusDevice *dev)
+{
+    RamDevice *d = FROM_SYSBUS(RamDevice, dev);
+
+    memory_region_init_ram(&d->ram, "sun4u.ram", d->size);
+    vmstate_register_ram_global(&d->ram);
+    sysbus_init_mmio(dev, &d->ram);
+    return 0;
+}
+
+static void ram_init(hwaddr addr, ram_addr_t RAM_size)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    RamDevice *d;
+
+    /* allocate RAM */
+    dev = qdev_create(NULL, "memory");
+    s = SYS_BUS_DEVICE(dev);
+
+    d = FROM_SYSBUS(RamDevice, s);
+    d->size = RAM_size;
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+}
+
+static Property ram_properties[] = {
+    DEFINE_PROP_UINT64("size", RamDevice, size, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ram_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = ram_init1;
+    dc->props = ram_properties;
+}
+
+static const TypeInfo ram_info = {
+    .name          = "memory",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(RamDevice),
+    .class_init    = ram_class_init,
+};
+
+static SPARCCPU *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
+{
+    SPARCCPU *cpu;
+    CPUSPARCState *env;
+    ResetData *reset_info;
+
+    uint32_t   tick_frequency = 100*1000000;
+    uint32_t  stick_frequency = 100*1000000;
+    uint32_t hstick_frequency = 100*1000000;
+
+    if (cpu_model == NULL) {
+        cpu_model = hwdef->default_cpu_model;
+    }
+    cpu = cpu_sparc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find Sparc CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    env->tick = cpu_timer_create("tick", cpu, tick_irq,
+                                  tick_frequency, TICK_NPT_MASK);
+
+    env->stick = cpu_timer_create("stick", cpu, stick_irq,
+                                   stick_frequency, TICK_INT_DIS);
+
+    env->hstick = cpu_timer_create("hstick", cpu, hstick_irq,
+                                    hstick_frequency, TICK_INT_DIS);
+
+    reset_info = g_malloc0(sizeof(ResetData));
+    reset_info->cpu = cpu;
+    reset_info->prom_addr = hwdef->prom_addr;
+    qemu_register_reset(main_cpu_reset, reset_info);
+
+    return cpu;
+}
+
+static void sun4uv_init(MemoryRegion *address_space_mem,
+                        ram_addr_t RAM_size,
+                        const char *boot_devices,
+                        const char *kernel_filename, const char *kernel_cmdline,
+                        const char *initrd_filename, const char *cpu_model,
+                        const struct hwdef *hwdef)
+{
+    SPARCCPU *cpu;
+    M48t59State *nvram;
+    unsigned int i;
+    uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
+    PCIBus *pci_bus, *pci_bus2, *pci_bus3;
+    ISABus *isa_bus;
+    qemu_irq *ivec_irqs, *pbm_irqs;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    DriveInfo *fd[MAX_FD];
+    void *fw_cfg;
+
+    /* init CPUs */
+    cpu = cpu_devinit(cpu_model, hwdef);
+
+    /* set up devices */
+    ram_init(0, RAM_size);
+
+    prom_init(hwdef->prom_addr, bios_name);
+
+    ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, cpu, IVEC_MAX);
+    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2,
+                           &pci_bus3, &pbm_irqs);
+    pci_vga_init(pci_bus);
+
+    // XXX Should be pci_bus3
+    isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs);
+
+    i = 0;
+    if (hwdef->console_serial_base) {
+        serial_mm_init(address_space_mem, hwdef->console_serial_base, 0,
+                       NULL, 115200, serial_hds[i], DEVICE_BIG_ENDIAN);
+        i++;
+    }
+    for(; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_isa_init(isa_bus, i, serial_hds[i]);
+        }
+    }
+
+    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
+        if (parallel_hds[i]) {
+            parallel_init(isa_bus, i, parallel_hds[i]);
+        }
+    }
+
+    for(i = 0; i < nb_nics; i++)
+        pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
+
+    ide_drive_get(hd, MAX_IDE_BUS);
+
+    pci_cmd646_ide_init(pci_bus, hd, 1);
+
+    isa_create_simple(isa_bus, "i8042");
+    for(i = 0; i < MAX_FD; i++) {
+        fd[i] = drive_get(IF_FLOPPY, 0, i);
+    }
+    fdctrl_init_isa(isa_bus, fd);
+    nvram = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
+
+    initrd_size = 0;
+    initrd_addr = 0;
+    kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
+                                    ram_size, &initrd_size, &initrd_addr,
+                                    &kernel_addr, &kernel_entry);
+
+    sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
+                           kernel_addr, kernel_size,
+                           kernel_cmdline,
+                           initrd_addr, initrd_size,
+                           /* XXX: need an option to load a NVRAM image */
+                           0,
+                           graphic_width, graphic_height, graphic_depth,
+                           (uint8_t *)&nd_table[0].macaddr);
+
+    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+    if (kernel_cmdline) {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
+                       strlen(kernel_cmdline) + 1);
+        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+    } else {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
+    }
+    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_devices[0]);
+
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_HEIGHT, graphic_height);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_DEPTH, graphic_depth);
+
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+}
+
+enum {
+    sun4u_id = 0,
+    sun4v_id = 64,
+    niagara_id,
+};
+
+static const struct hwdef hwdefs[] = {
+    /* Sun4u generic PC-like machine */
+    {
+        .default_cpu_model = "TI UltraSparc IIi",
+        .machine_id = sun4u_id,
+        .prom_addr = 0x1fff0000000ULL,
+        .console_serial_base = 0,
+    },
+    /* Sun4v generic PC-like machine */
+    {
+        .default_cpu_model = "Sun UltraSparc T1",
+        .machine_id = sun4v_id,
+        .prom_addr = 0x1fff0000000ULL,
+        .console_serial_base = 0,
+    },
+    /* Sun4v generic Niagara machine */
+    {
+        .default_cpu_model = "Sun UltraSparc T1",
+        .machine_id = niagara_id,
+        .prom_addr = 0xfff0000000ULL,
+        .console_serial_base = 0xfff0c2c000ULL,
+    },
+};
+
+/* Sun4u hardware initialisation */
+static void sun4u_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_devices = args->boot_device;
+    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
+                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[0]);
+}
+
+/* Sun4v hardware initialisation */
+static void sun4v_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_devices = args->boot_device;
+    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
+                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]);
+}
+
+/* Niagara hardware initialisation */
+static void niagara_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_devices = args->boot_device;
+    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
+                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]);
+}
+
+static QEMUMachine sun4u_machine = {
+    .name = "sun4u",
+    .desc = "Sun4u platform",
+    .init = sun4u_init,
+    .max_cpus = 1, // XXX for now
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine sun4v_machine = {
+    .name = "sun4v",
+    .desc = "Sun4v platform",
+    .init = sun4v_init,
+    .max_cpus = 1, // XXX for now
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine niagara_machine = {
+    .name = "Niagara",
+    .desc = "Sun4v platform, Niagara",
+    .init = niagara_init,
+    .max_cpus = 1, // XXX for now
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void sun4u_register_types(void)
+{
+    type_register_static(&ebus_info);
+    type_register_static(&prom_info);
+    type_register_static(&ram_info);
+}
+
+static void sun4u_machine_init(void)
+{
+    qemu_register_machine(&sun4u_machine);
+    qemu_register_machine(&sun4v_machine);
+    qemu_register_machine(&niagara_machine);
+}
+
+type_init(sun4u_register_types)
+machine_init(sun4u_machine_init);
diff --git a/hw/spitz.c b/hw/spitz.c
deleted file mode 100644 (file)
index 5bc49fc..0000000
+++ /dev/null
@@ -1,1138 +0,0 @@
-/*
- * PXA270-based Clamshell PDA platforms.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog@zabor.org>
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "hw.h"
-#include "pxa.h"
-#include "arm-misc.h"
-#include "sysemu/sysemu.h"
-#include "pcmcia.h"
-#include "i2c.h"
-#include "ssi.h"
-#include "flash.h"
-#include "qemu/timer.h"
-#include "devices.h"
-#include "sharpsl.h"
-#include "ui/console.h"
-#include "block/block.h"
-#include "audio/audio.h"
-#include "boards.h"
-#include "sysemu/blockdev.h"
-#include "sysbus.h"
-#include "exec/address-spaces.h"
-
-#undef REG_FMT
-#define REG_FMT                        "0x%02lx"
-
-/* Spitz Flash */
-#define FLASH_BASE             0x0c000000
-#define FLASH_ECCLPLB          0x00    /* Line parity 7 - 0 bit */
-#define FLASH_ECCLPUB          0x04    /* Line parity 15 - 8 bit */
-#define FLASH_ECCCP            0x08    /* Column parity 5 - 0 bit */
-#define FLASH_ECCCNTR          0x0c    /* ECC byte counter */
-#define FLASH_ECCCLRR          0x10    /* Clear ECC */
-#define FLASH_FLASHIO          0x14    /* Flash I/O */
-#define FLASH_FLASHCTL         0x18    /* Flash Control */
-
-#define FLASHCTL_CE0           (1 << 0)
-#define FLASHCTL_CLE           (1 << 1)
-#define FLASHCTL_ALE           (1 << 2)
-#define FLASHCTL_WP            (1 << 3)
-#define FLASHCTL_CE1           (1 << 4)
-#define FLASHCTL_RYBY          (1 << 5)
-#define FLASHCTL_NCE           (FLASHCTL_CE0 | FLASHCTL_CE1)
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    DeviceState *nand;
-    uint8_t ctl;
-    uint8_t manf_id;
-    uint8_t chip_id;
-    ECCState ecc;
-} SLNANDState;
-
-static uint64_t sl_read(void *opaque, hwaddr addr, unsigned size)
-{
-    SLNANDState *s = (SLNANDState *) opaque;
-    int ryby;
-
-    switch (addr) {
-#define BSHR(byte, from, to)   ((s->ecc.lp[byte] >> (from - to)) & (1 << to))
-    case FLASH_ECCLPLB:
-        return BSHR(0, 4, 0) | BSHR(0, 5, 2) | BSHR(0, 6, 4) | BSHR(0, 7, 6) |
-                BSHR(1, 4, 1) | BSHR(1, 5, 3) | BSHR(1, 6, 5) | BSHR(1, 7, 7);
-
-#define BSHL(byte, from, to)   ((s->ecc.lp[byte] << (to - from)) & (1 << to))
-    case FLASH_ECCLPUB:
-        return BSHL(0, 0, 0) | BSHL(0, 1, 2) | BSHL(0, 2, 4) | BSHL(0, 3, 6) |
-                BSHL(1, 0, 1) | BSHL(1, 1, 3) | BSHL(1, 2, 5) | BSHL(1, 3, 7);
-
-    case FLASH_ECCCP:
-        return s->ecc.cp;
-
-    case FLASH_ECCCNTR:
-        return s->ecc.count & 0xff;
-
-    case FLASH_FLASHCTL:
-        nand_getpins(s->nand, &ryby);
-        if (ryby)
-            return s->ctl | FLASHCTL_RYBY;
-        else
-            return s->ctl;
-
-    case FLASH_FLASHIO:
-        if (size == 4) {
-            return ecc_digest(&s->ecc, nand_getio(s->nand)) |
-                (ecc_digest(&s->ecc, nand_getio(s->nand)) << 16);
-        }
-        return ecc_digest(&s->ecc, nand_getio(s->nand));
-
-    default:
-        zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
-    }
-    return 0;
-}
-
-static void sl_write(void *opaque, hwaddr addr,
-                     uint64_t value, unsigned size)
-{
-    SLNANDState *s = (SLNANDState *) opaque;
-
-    switch (addr) {
-    case FLASH_ECCCLRR:
-        /* Value is ignored.  */
-        ecc_reset(&s->ecc);
-        break;
-
-    case FLASH_FLASHCTL:
-        s->ctl = value & 0xff & ~FLASHCTL_RYBY;
-        nand_setpins(s->nand,
-                        s->ctl & FLASHCTL_CLE,
-                        s->ctl & FLASHCTL_ALE,
-                        s->ctl & FLASHCTL_NCE,
-                        s->ctl & FLASHCTL_WP,
-                        0);
-        break;
-
-    case FLASH_FLASHIO:
-        nand_setio(s->nand, ecc_digest(&s->ecc, value & 0xff));
-        break;
-
-    default:
-        zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
-    }
-}
-
-enum {
-    FLASH_128M,
-    FLASH_1024M,
-};
-
-static const MemoryRegionOps sl_ops = {
-    .read = sl_read,
-    .write = sl_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void sl_flash_register(PXA2xxState *cpu, int size)
-{
-    DeviceState *dev;
-
-    dev = qdev_create(NULL, "sl-nand");
-
-    qdev_prop_set_uint8(dev, "manf_id", NAND_MFR_SAMSUNG);
-    if (size == FLASH_128M)
-        qdev_prop_set_uint8(dev, "chip_id", 0x73);
-    else if (size == FLASH_1024M)
-        qdev_prop_set_uint8(dev, "chip_id", 0xf1);
-
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, FLASH_BASE);
-}
-
-static int sl_nand_init(SysBusDevice *dev) {
-    SLNANDState *s;
-    DriveInfo *nand;
-
-    s = FROM_SYSBUS(SLNANDState, dev);
-
-    s->ctl = 0;
-    nand = drive_get(IF_MTD, 0, 0);
-    s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
-
-    memory_region_init_io(&s->iomem, &sl_ops, s, "sl", 0x40);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    return 0;
-}
-
-/* Spitz Keyboard */
-
-#define SPITZ_KEY_STROBE_NUM   11
-#define SPITZ_KEY_SENSE_NUM    7
-
-static const int spitz_gpio_key_sense[SPITZ_KEY_SENSE_NUM] = {
-    12, 17, 91, 34, 36, 38, 39
-};
-
-static const int spitz_gpio_key_strobe[SPITZ_KEY_STROBE_NUM] = {
-    88, 23, 24, 25, 26, 27, 52, 103, 107, 108, 114
-};
-
-/* Eighth additional row maps the special keys */
-static int spitz_keymap[SPITZ_KEY_SENSE_NUM + 1][SPITZ_KEY_STROBE_NUM] = {
-    { 0x1d, 0x02, 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0e, 0x3f, 0x40 },
-    {  -1 , 0x03, 0x05, 0x13, 0x15, 0x09, 0x17, 0x18, 0x19, 0x41, 0x42 },
-    { 0x0f, 0x10, 0x12, 0x14, 0x22, 0x16, 0x24, 0x25,  -1 ,  -1 ,  -1  },
-    { 0x3c, 0x11, 0x1f, 0x21, 0x2f, 0x23, 0x32, 0x26,  -1 , 0x36,  -1  },
-    { 0x3b, 0x1e, 0x20, 0x2e, 0x30, 0x31, 0x34,  -1 , 0x1c, 0x2a,  -1  },
-    { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33,  -1 , 0x48,  -1 ,  -1 , 0x38 },
-    { 0x37, 0x3d,  -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d,  -1 ,  -1  },
-    { 0x52, 0x43, 0x01, 0x47, 0x49,  -1 ,  -1 ,  -1 ,  -1 ,  -1 ,  -1  },
-};
-
-#define SPITZ_GPIO_AK_INT      13      /* Remote control */
-#define SPITZ_GPIO_SYNC                16      /* Sync button */
-#define SPITZ_GPIO_ON_KEY      95      /* Power button */
-#define SPITZ_GPIO_SWA         97      /* Lid */
-#define SPITZ_GPIO_SWB         96      /* Tablet mode */
-
-/* The special buttons are mapped to unused keys */
-static const int spitz_gpiomap[5] = {
-    SPITZ_GPIO_AK_INT, SPITZ_GPIO_SYNC, SPITZ_GPIO_ON_KEY,
-    SPITZ_GPIO_SWA, SPITZ_GPIO_SWB,
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    qemu_irq sense[SPITZ_KEY_SENSE_NUM];
-    qemu_irq gpiomap[5];
-    int keymap[0x80];
-    uint16_t keyrow[SPITZ_KEY_SENSE_NUM];
-    uint16_t strobe_state;
-    uint16_t sense_state;
-
-    uint16_t pre_map[0x100];
-    uint16_t modifiers;
-    uint16_t imodifiers;
-    uint8_t fifo[16];
-    int fifopos, fifolen;
-    QEMUTimer *kbdtimer;
-} SpitzKeyboardState;
-
-static void spitz_keyboard_sense_update(SpitzKeyboardState *s)
-{
-    int i;
-    uint16_t strobe, sense = 0;
-    for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++) {
-        strobe = s->keyrow[i] & s->strobe_state;
-        if (strobe) {
-            sense |= 1 << i;
-            if (!(s->sense_state & (1 << i)))
-                qemu_irq_raise(s->sense[i]);
-        } else if (s->sense_state & (1 << i))
-            qemu_irq_lower(s->sense[i]);
-    }
-
-    s->sense_state = sense;
-}
-
-static void spitz_keyboard_strobe(void *opaque, int line, int level)
-{
-    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
-
-    if (level)
-        s->strobe_state |= 1 << line;
-    else
-        s->strobe_state &= ~(1 << line);
-    spitz_keyboard_sense_update(s);
-}
-
-static void spitz_keyboard_keydown(SpitzKeyboardState *s, int keycode)
-{
-    int spitz_keycode = s->keymap[keycode & 0x7f];
-    if (spitz_keycode == -1)
-        return;
-
-    /* Handle the additional keys */
-    if ((spitz_keycode >> 4) == SPITZ_KEY_SENSE_NUM) {
-        qemu_set_irq(s->gpiomap[spitz_keycode & 0xf], (keycode < 0x80));
-        return;
-    }
-
-    if (keycode & 0x80)
-        s->keyrow[spitz_keycode >> 4] &= ~(1 << (spitz_keycode & 0xf));
-    else
-        s->keyrow[spitz_keycode >> 4] |= 1 << (spitz_keycode & 0xf);
-
-    spitz_keyboard_sense_update(s);
-}
-
-#define SHIFT  (1 << 7)
-#define CTRL   (1 << 8)
-#define FN     (1 << 9)
-
-#define QUEUE_KEY(c)   s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
-
-static void spitz_keyboard_handler(void *opaque, int keycode)
-{
-    SpitzKeyboardState *s = opaque;
-    uint16_t code;
-    int mapcode;
-    switch (keycode) {
-    case 0x2a: /* Left Shift */
-        s->modifiers |= 1;
-        break;
-    case 0xaa:
-        s->modifiers &= ~1;
-        break;
-    case 0x36: /* Right Shift */
-        s->modifiers |= 2;
-        break;
-    case 0xb6:
-        s->modifiers &= ~2;
-        break;
-    case 0x1d: /* Control */
-        s->modifiers |= 4;
-        break;
-    case 0x9d:
-        s->modifiers &= ~4;
-        break;
-    case 0x38: /* Alt */
-        s->modifiers |= 8;
-        break;
-    case 0xb8:
-        s->modifiers &= ~8;
-        break;
-    }
-
-    code = s->pre_map[mapcode = ((s->modifiers & 3) ?
-            (keycode | SHIFT) :
-            (keycode & ~SHIFT))];
-
-    if (code != mapcode) {
-#if 0
-        if ((code & SHIFT) && !(s->modifiers & 1))
-            QUEUE_KEY(0x2a | (keycode & 0x80));
-        if ((code & CTRL ) && !(s->modifiers & 4))
-            QUEUE_KEY(0x1d | (keycode & 0x80));
-        if ((code & FN   ) && !(s->modifiers & 8))
-            QUEUE_KEY(0x38 | (keycode & 0x80));
-        if ((code & FN   ) && (s->modifiers & 1))
-            QUEUE_KEY(0x2a | (~keycode & 0x80));
-        if ((code & FN   ) && (s->modifiers & 2))
-            QUEUE_KEY(0x36 | (~keycode & 0x80));
-#else
-        if (keycode & 0x80) {
-            if ((s->imodifiers & 1   ) && !(s->modifiers & 1))
-                QUEUE_KEY(0x2a | 0x80);
-            if ((s->imodifiers & 4   ) && !(s->modifiers & 4))
-                QUEUE_KEY(0x1d | 0x80);
-            if ((s->imodifiers & 8   ) && !(s->modifiers & 8))
-                QUEUE_KEY(0x38 | 0x80);
-            if ((s->imodifiers & 0x10) && (s->modifiers & 1))
-                QUEUE_KEY(0x2a);
-            if ((s->imodifiers & 0x20) && (s->modifiers & 2))
-                QUEUE_KEY(0x36);
-            s->imodifiers = 0;
-        } else {
-            if ((code & SHIFT) && !((s->modifiers | s->imodifiers) & 1)) {
-                QUEUE_KEY(0x2a);
-                s->imodifiers |= 1;
-            }
-            if ((code & CTRL ) && !((s->modifiers | s->imodifiers) & 4)) {
-                QUEUE_KEY(0x1d);
-                s->imodifiers |= 4;
-            }
-            if ((code & FN   ) && !((s->modifiers | s->imodifiers) & 8)) {
-                QUEUE_KEY(0x38);
-                s->imodifiers |= 8;
-            }
-            if ((code & FN   ) && (s->modifiers & 1) &&
-                            !(s->imodifiers & 0x10)) {
-                QUEUE_KEY(0x2a | 0x80);
-                s->imodifiers |= 0x10;
-            }
-            if ((code & FN   ) && (s->modifiers & 2) &&
-                            !(s->imodifiers & 0x20)) {
-                QUEUE_KEY(0x36 | 0x80);
-                s->imodifiers |= 0x20;
-            }
-        }
-#endif
-    }
-
-    QUEUE_KEY((code & 0x7f) | (keycode & 0x80));
-}
-
-static void spitz_keyboard_tick(void *opaque)
-{
-    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
-
-    if (s->fifolen) {
-        spitz_keyboard_keydown(s, s->fifo[s->fifopos ++]);
-        s->fifolen --;
-        if (s->fifopos >= 16)
-            s->fifopos = 0;
-    }
-
-    qemu_mod_timer(s->kbdtimer, qemu_get_clock_ns(vm_clock) +
-                   get_ticks_per_sec() / 32);
-}
-
-static void spitz_keyboard_pre_map(SpitzKeyboardState *s)
-{
-    int i;
-    for (i = 0; i < 0x100; i ++)
-        s->pre_map[i] = i;
-    s->pre_map[0x02 | SHIFT    ] = 0x02 | SHIFT;       /* exclam */
-    s->pre_map[0x28 | SHIFT    ] = 0x03 | SHIFT;       /* quotedbl */
-    s->pre_map[0x04 | SHIFT    ] = 0x04 | SHIFT;       /* numbersign */
-    s->pre_map[0x05 | SHIFT    ] = 0x05 | SHIFT;       /* dollar */
-    s->pre_map[0x06 | SHIFT    ] = 0x06 | SHIFT;       /* percent */
-    s->pre_map[0x08 | SHIFT    ] = 0x07 | SHIFT;       /* ampersand */
-    s->pre_map[0x28            ] = 0x08 | SHIFT;       /* apostrophe */
-    s->pre_map[0x0a | SHIFT    ] = 0x09 | SHIFT;       /* parenleft */
-    s->pre_map[0x0b | SHIFT    ] = 0x0a | SHIFT;       /* parenright */
-    s->pre_map[0x29 | SHIFT    ] = 0x0b | SHIFT;       /* asciitilde */
-    s->pre_map[0x03 | SHIFT    ] = 0x0c | SHIFT;       /* at */
-    s->pre_map[0xd3            ] = 0x0e | FN;          /* Delete */
-    s->pre_map[0x3a            ] = 0x0f | FN;          /* Caps_Lock */
-    s->pre_map[0x07 | SHIFT    ] = 0x11 | FN;          /* asciicircum */
-    s->pre_map[0x0d            ] = 0x12 | FN;          /* equal */
-    s->pre_map[0x0d | SHIFT    ] = 0x13 | FN;          /* plus */
-    s->pre_map[0x1a            ] = 0x14 | FN;          /* bracketleft */
-    s->pre_map[0x1b            ] = 0x15 | FN;          /* bracketright */
-    s->pre_map[0x1a | SHIFT    ] = 0x16 | FN;          /* braceleft */
-    s->pre_map[0x1b | SHIFT    ] = 0x17 | FN;          /* braceright */
-    s->pre_map[0x27            ] = 0x22 | FN;          /* semicolon */
-    s->pre_map[0x27 | SHIFT    ] = 0x23 | FN;          /* colon */
-    s->pre_map[0x09 | SHIFT    ] = 0x24 | FN;          /* asterisk */
-    s->pre_map[0x2b            ] = 0x25 | FN;          /* backslash */
-    s->pre_map[0x2b | SHIFT    ] = 0x26 | FN;          /* bar */
-    s->pre_map[0x0c | SHIFT    ] = 0x30 | FN;          /* underscore */
-    s->pre_map[0x33 | SHIFT    ] = 0x33 | FN;          /* less */
-    s->pre_map[0x35            ] = 0x33 | SHIFT;       /* slash */
-    s->pre_map[0x34 | SHIFT    ] = 0x34 | FN;          /* greater */
-    s->pre_map[0x35 | SHIFT    ] = 0x34 | SHIFT;       /* question */
-    s->pre_map[0x49            ] = 0x48 | FN;          /* Page_Up */
-    s->pre_map[0x51            ] = 0x50 | FN;          /* Page_Down */
-
-    s->modifiers = 0;
-    s->imodifiers = 0;
-    s->fifopos = 0;
-    s->fifolen = 0;
-}
-
-#undef SHIFT
-#undef CTRL
-#undef FN
-
-static int spitz_keyboard_post_load(void *opaque, int version_id)
-{
-    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
-
-    /* Release all pressed keys */
-    memset(s->keyrow, 0, sizeof(s->keyrow));
-    spitz_keyboard_sense_update(s);
-    s->modifiers = 0;
-    s->imodifiers = 0;
-    s->fifopos = 0;
-    s->fifolen = 0;
-
-    return 0;
-}
-
-static void spitz_keyboard_register(PXA2xxState *cpu)
-{
-    int i;
-    DeviceState *dev;
-    SpitzKeyboardState *s;
-
-    dev = sysbus_create_simple("spitz-keyboard", -1, NULL);
-    s = FROM_SYSBUS(SpitzKeyboardState, SYS_BUS_DEVICE(dev));
-
-    for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++)
-        qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(cpu->gpio, spitz_gpio_key_sense[i]));
-
-    for (i = 0; i < 5; i ++)
-        s->gpiomap[i] = qdev_get_gpio_in(cpu->gpio, spitz_gpiomap[i]);
-
-    if (!graphic_rotate)
-        s->gpiomap[4] = qemu_irq_invert(s->gpiomap[4]);
-
-    for (i = 0; i < 5; i++)
-        qemu_set_irq(s->gpiomap[i], 0);
-
-    for (i = 0; i < SPITZ_KEY_STROBE_NUM; i ++)
-        qdev_connect_gpio_out(cpu->gpio, spitz_gpio_key_strobe[i],
-                qdev_get_gpio_in(dev, i));
-
-    qemu_mod_timer(s->kbdtimer, qemu_get_clock_ns(vm_clock));
-
-    qemu_add_kbd_event_handler(spitz_keyboard_handler, s);
-}
-
-static int spitz_keyboard_init(SysBusDevice *dev)
-{
-    SpitzKeyboardState *s;
-    int i, j;
-
-    s = FROM_SYSBUS(SpitzKeyboardState, dev);
-
-    for (i = 0; i < 0x80; i ++)
-        s->keymap[i] = -1;
-    for (i = 0; i < SPITZ_KEY_SENSE_NUM + 1; i ++)
-        for (j = 0; j < SPITZ_KEY_STROBE_NUM; j ++)
-            if (spitz_keymap[i][j] != -1)
-                s->keymap[spitz_keymap[i][j]] = (i << 4) | j;
-
-    spitz_keyboard_pre_map(s);
-
-    s->kbdtimer = qemu_new_timer_ns(vm_clock, spitz_keyboard_tick, s);
-    qdev_init_gpio_in(&dev->qdev, spitz_keyboard_strobe, SPITZ_KEY_STROBE_NUM);
-    qdev_init_gpio_out(&dev->qdev, s->sense, SPITZ_KEY_SENSE_NUM);
-
-    return 0;
-}
-
-/* LCD backlight controller */
-
-#define LCDTG_RESCTL   0x00
-#define LCDTG_PHACTRL  0x01
-#define LCDTG_DUTYCTRL 0x02
-#define LCDTG_POWERREG0        0x03
-#define LCDTG_POWERREG1        0x04
-#define LCDTG_GPOR3    0x05
-#define LCDTG_PICTRL   0x06
-#define LCDTG_POLCTRL  0x07
-
-typedef struct {
-    SSISlave ssidev;
-    uint32_t bl_intensity;
-    uint32_t bl_power;
-} SpitzLCDTG;
-
-static void spitz_bl_update(SpitzLCDTG *s)
-{
-    if (s->bl_power && s->bl_intensity)
-        zaurus_printf("LCD Backlight now at %i/63\n", s->bl_intensity);
-    else
-        zaurus_printf("LCD Backlight now off\n");
-}
-
-/* FIXME: Implement GPIO properly and remove this hack.  */
-static SpitzLCDTG *spitz_lcdtg;
-
-static inline void spitz_bl_bit5(void *opaque, int line, int level)
-{
-    SpitzLCDTG *s = spitz_lcdtg;
-    int prev = s->bl_intensity;
-
-    if (level)
-        s->bl_intensity &= ~0x20;
-    else
-        s->bl_intensity |= 0x20;
-
-    if (s->bl_power && prev != s->bl_intensity)
-        spitz_bl_update(s);
-}
-
-static inline void spitz_bl_power(void *opaque, int line, int level)
-{
-    SpitzLCDTG *s = spitz_lcdtg;
-    s->bl_power = !!level;
-    spitz_bl_update(s);
-}
-
-static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value)
-{
-    SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
-    int addr;
-    addr = value >> 5;
-    value &= 0x1f;
-
-    switch (addr) {
-    case LCDTG_RESCTL:
-        if (value)
-            zaurus_printf("LCD in QVGA mode\n");
-        else
-            zaurus_printf("LCD in VGA mode\n");
-        break;
-
-    case LCDTG_DUTYCTRL:
-        s->bl_intensity &= ~0x1f;
-        s->bl_intensity |= value;
-        if (s->bl_power)
-            spitz_bl_update(s);
-        break;
-
-    case LCDTG_POWERREG0:
-        /* Set common voltage to M62332FP */
-        break;
-    }
-    return 0;
-}
-
-static int spitz_lcdtg_init(SSISlave *dev)
-{
-    SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
-
-    spitz_lcdtg = s;
-    s->bl_power = 0;
-    s->bl_intensity = 0x20;
-
-    return 0;
-}
-
-/* SSP devices */
-
-#define CORGI_SSP_PORT         2
-
-#define SPITZ_GPIO_LCDCON_CS   53
-#define SPITZ_GPIO_ADS7846_CS  14
-#define SPITZ_GPIO_MAX1111_CS  20
-#define SPITZ_GPIO_TP_INT      11
-
-static DeviceState *max1111;
-
-/* "Demux" the signal based on current chipselect */
-typedef struct {
-    SSISlave ssidev;
-    SSIBus *bus[3];
-    uint32_t enable[3];
-} CorgiSSPState;
-
-static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
-{
-    CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
-    int i;
-
-    for (i = 0; i < 3; i++) {
-        if (s->enable[i]) {
-            return ssi_transfer(s->bus[i], value);
-        }
-    }
-    return 0;
-}
-
-static void corgi_ssp_gpio_cs(void *opaque, int line, int level)
-{
-    CorgiSSPState *s = (CorgiSSPState *)opaque;
-    assert(line >= 0 && line < 3);
-    s->enable[line] = !level;
-}
-
-#define MAX1111_BATT_VOLT      1
-#define MAX1111_BATT_TEMP      2
-#define MAX1111_ACIN_VOLT      3
-
-#define SPITZ_BATTERY_TEMP     0xe0    /* About 2.9V */
-#define SPITZ_BATTERY_VOLT     0xd0    /* About 4.0V */
-#define SPITZ_CHARGEON_ACIN    0x80    /* About 5.0V */
-
-static void spitz_adc_temp_on(void *opaque, int line, int level)
-{
-    if (!max1111)
-        return;
-
-    if (level)
-        max111x_set_input(max1111, MAX1111_BATT_TEMP, SPITZ_BATTERY_TEMP);
-    else
-        max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
-}
-
-static int corgi_ssp_init(SSISlave *dev)
-{
-    CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
-
-    qdev_init_gpio_in(&dev->qdev, corgi_ssp_gpio_cs, 3);
-    s->bus[0] = ssi_create_bus(&dev->qdev, "ssi0");
-    s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
-    s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2");
-
-    return 0;
-}
-
-static void spitz_ssp_attach(PXA2xxState *cpu)
-{
-    DeviceState *mux;
-    DeviceState *dev;
-    void *bus;
-
-    mux = ssi_create_slave(cpu->ssp[CORGI_SSP_PORT - 1], "corgi-ssp");
-
-    bus = qdev_get_child_bus(mux, "ssi0");
-    ssi_create_slave(bus, "spitz-lcdtg");
-
-    bus = qdev_get_child_bus(mux, "ssi1");
-    dev = ssi_create_slave(bus, "ads7846");
-    qdev_connect_gpio_out(dev, 0,
-                          qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_TP_INT));
-
-    bus = qdev_get_child_bus(mux, "ssi2");
-    max1111 = ssi_create_slave(bus, "max1111");
-    max111x_set_input(max1111, MAX1111_BATT_VOLT, SPITZ_BATTERY_VOLT);
-    max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
-    max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
-
-    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_LCDCON_CS,
-                        qdev_get_gpio_in(mux, 0));
-    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ADS7846_CS,
-                        qdev_get_gpio_in(mux, 1));
-    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_MAX1111_CS,
-                        qdev_get_gpio_in(mux, 2));
-}
-
-/* CF Microdrive */
-
-static void spitz_microdrive_attach(PXA2xxState *cpu, int slot)
-{
-    PCMCIACardState *md;
-    DriveInfo *dinfo;
-
-    dinfo = drive_get(IF_IDE, 0, 0);
-    if (!dinfo || dinfo->media_cd)
-        return;
-    md = dscm1xxxx_init(dinfo);
-    pxa2xx_pcmcia_attach(cpu->pcmcia[slot], md);
-}
-
-/* Wm8750 and Max7310 on I2C */
-
-#define AKITA_MAX_ADDR 0x18
-#define SPITZ_WM_ADDRL 0x1b
-#define SPITZ_WM_ADDRH 0x1a
-
-#define SPITZ_GPIO_WM  5
-
-static void spitz_wm8750_addr(void *opaque, int line, int level)
-{
-    I2CSlave *wm = (I2CSlave *) opaque;
-    if (level)
-        i2c_set_slave_address(wm, SPITZ_WM_ADDRH);
-    else
-        i2c_set_slave_address(wm, SPITZ_WM_ADDRL);
-}
-
-static void spitz_i2c_setup(PXA2xxState *cpu)
-{
-    /* Attach the CPU on one end of our I2C bus.  */
-    i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
-
-    DeviceState *wm;
-
-    /* Attach a WM8750 to the bus */
-    wm = i2c_create_slave(bus, "wm8750", 0);
-
-    spitz_wm8750_addr(wm, 0, 0);
-    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_WM,
-                    qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
-    /* .. and to the sound interface.  */
-    cpu->i2s->opaque = wm;
-    cpu->i2s->codec_out = wm8750_dac_dat;
-    cpu->i2s->codec_in = wm8750_adc_dat;
-    wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
-}
-
-static void spitz_akita_i2c_setup(PXA2xxState *cpu)
-{
-    /* Attach a Max7310 to Akita I2C bus.  */
-    i2c_create_slave(pxa2xx_i2c_bus(cpu->i2c[0]), "max7310",
-                     AKITA_MAX_ADDR);
-}
-
-/* Other peripherals */
-
-static void spitz_out_switch(void *opaque, int line, int level)
-{
-    switch (line) {
-    case 0:
-        zaurus_printf("Charging %s.\n", level ? "off" : "on");
-        break;
-    case 1:
-        zaurus_printf("Discharging %s.\n", level ? "on" : "off");
-        break;
-    case 2:
-        zaurus_printf("Green LED %s.\n", level ? "on" : "off");
-        break;
-    case 3:
-        zaurus_printf("Orange LED %s.\n", level ? "on" : "off");
-        break;
-    case 4:
-        spitz_bl_bit5(opaque, line, level);
-        break;
-    case 5:
-        spitz_bl_power(opaque, line, level);
-        break;
-    case 6:
-        spitz_adc_temp_on(opaque, line, level);
-        break;
-    }
-}
-
-#define SPITZ_SCP_LED_GREEN            1
-#define SPITZ_SCP_JK_B                 2
-#define SPITZ_SCP_CHRG_ON              3
-#define SPITZ_SCP_MUTE_L               4
-#define SPITZ_SCP_MUTE_R               5
-#define SPITZ_SCP_CF_POWER             6
-#define SPITZ_SCP_LED_ORANGE           7
-#define SPITZ_SCP_JK_A                 8
-#define SPITZ_SCP_ADC_TEMP_ON          9
-#define SPITZ_SCP2_IR_ON               1
-#define SPITZ_SCP2_AKIN_PULLUP         2
-#define SPITZ_SCP2_BACKLIGHT_CONT      7
-#define SPITZ_SCP2_BACKLIGHT_ON                8
-#define SPITZ_SCP2_MIC_BIAS            9
-
-static void spitz_scoop_gpio_setup(PXA2xxState *cpu,
-                DeviceState *scp0, DeviceState *scp1)
-{
-    qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, cpu, 8);
-
-    qdev_connect_gpio_out(scp0, SPITZ_SCP_CHRG_ON, outsignals[0]);
-    qdev_connect_gpio_out(scp0, SPITZ_SCP_JK_B, outsignals[1]);
-    qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_GREEN, outsignals[2]);
-    qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]);
-
-    if (scp1) {
-        qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]);
-        qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]);
-    }
-
-    qdev_connect_gpio_out(scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
-}
-
-#define SPITZ_GPIO_HSYNC               22
-#define SPITZ_GPIO_SD_DETECT           9
-#define SPITZ_GPIO_SD_WP               81
-#define SPITZ_GPIO_ON_RESET            89
-#define SPITZ_GPIO_BAT_COVER           90
-#define SPITZ_GPIO_CF1_IRQ             105
-#define SPITZ_GPIO_CF1_CD              94
-#define SPITZ_GPIO_CF2_IRQ             106
-#define SPITZ_GPIO_CF2_CD              93
-
-static int spitz_hsync;
-
-static void spitz_lcd_hsync_handler(void *opaque, int line, int level)
-{
-    PXA2xxState *cpu = (PXA2xxState *) opaque;
-    qemu_set_irq(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_HSYNC), spitz_hsync);
-    spitz_hsync ^= 1;
-}
-
-static void spitz_gpio_setup(PXA2xxState *cpu, int slots)
-{
-    qemu_irq lcd_hsync;
-    /*
-     * Bad hack: We toggle the LCD hsync GPIO on every GPIO status
-     * read to satisfy broken guests that poll-wait for hsync.
-     * Simulating a real hsync event would be less practical and
-     * wouldn't guarantee that a guest ever exits the loop.
-     */
-    spitz_hsync = 0;
-    lcd_hsync = qemu_allocate_irqs(spitz_lcd_hsync_handler, cpu, 1)[0];
-    pxa2xx_gpio_read_notifier(cpu->gpio, lcd_hsync);
-    pxa2xx_lcd_vsync_notifier(cpu->lcd, lcd_hsync);
-
-    /* MMC/SD host */
-    pxa2xx_mmci_handlers(cpu->mmc,
-                    qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_WP),
-                    qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_DETECT));
-
-    /* Battery lock always closed */
-    qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_BAT_COVER));
-
-    /* Handle reset */
-    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ON_RESET, cpu->reset);
-
-    /* PCMCIA signals: card's IRQ and Card-Detect */
-    if (slots >= 1)
-        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
-                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_IRQ),
-                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_CD));
-    if (slots >= 2)
-        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
-                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_IRQ),
-                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_CD));
-}
-
-/* Board init.  */
-enum spitz_model_e { spitz, akita, borzoi, terrier };
-
-#define SPITZ_RAM      0x04000000
-#define SPITZ_ROM      0x00800000
-
-static struct arm_boot_info spitz_binfo = {
-    .loader_start = PXA2XX_SDRAM_BASE,
-    .ram_size = 0x04000000,
-};
-
-static void spitz_common_init(QEMUMachineInitArgs *args,
-                              enum spitz_model_e model, int arm_id)
-{
-    PXA2xxState *mpu;
-    DeviceState *scp0, *scp1 = NULL;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *rom = g_new(MemoryRegion, 1);
-    const char *cpu_model = args->cpu_model;
-
-    if (!cpu_model)
-        cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
-
-    /* Setup CPU & memory */
-    mpu = pxa270_init(address_space_mem, spitz_binfo.ram_size, cpu_model);
-
-    sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
-
-    memory_region_init_ram(rom, "spitz.rom", SPITZ_ROM);
-    vmstate_register_ram_global(rom);
-    memory_region_set_readonly(rom, true);
-    memory_region_add_subregion(address_space_mem, 0, rom);
-
-    /* Setup peripherals */
-    spitz_keyboard_register(mpu);
-
-    spitz_ssp_attach(mpu);
-
-    scp0 = sysbus_create_simple("scoop", 0x10800000, NULL);
-    if (model != akita) {
-        scp1 = sysbus_create_simple("scoop", 0x08800040, NULL);
-    }
-
-    spitz_scoop_gpio_setup(mpu, scp0, scp1);
-
-    spitz_gpio_setup(mpu, (model == akita) ? 1 : 2);
-
-    spitz_i2c_setup(mpu);
-
-    if (model == akita)
-        spitz_akita_i2c_setup(mpu);
-
-    if (model == terrier)
-        /* A 6.0 GB microdrive is permanently sitting in CF slot 1.  */
-        spitz_microdrive_attach(mpu, 1);
-    else if (model != akita)
-        /* A 4.0 GB microdrive is permanently sitting in CF slot 0.  */
-        spitz_microdrive_attach(mpu, 0);
-
-    spitz_binfo.kernel_filename = args->kernel_filename;
-    spitz_binfo.kernel_cmdline = args->kernel_cmdline;
-    spitz_binfo.initrd_filename = args->initrd_filename;
-    spitz_binfo.board_id = arm_id;
-    arm_load_kernel(mpu->cpu, &spitz_binfo);
-    sl_bootparam_write(SL_PXA_PARAM_BASE);
-}
-
-static void spitz_init(QEMUMachineInitArgs *args)
-{
-    spitz_common_init(args, spitz, 0x2c9);
-}
-
-static void borzoi_init(QEMUMachineInitArgs *args)
-{
-    spitz_common_init(args, borzoi, 0x33f);
-}
-
-static void akita_init(QEMUMachineInitArgs *args)
-{
-    spitz_common_init(args, akita, 0x2e8);
-}
-
-static void terrier_init(QEMUMachineInitArgs *args)
-{
-    spitz_common_init(args, terrier, 0x33f);
-}
-
-static QEMUMachine akitapda_machine = {
-    .name = "akita",
-    .desc = "Akita PDA (PXA270)",
-    .init = akita_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine spitzpda_machine = {
-    .name = "spitz",
-    .desc = "Spitz PDA (PXA270)",
-    .init = spitz_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine borzoipda_machine = {
-    .name = "borzoi",
-    .desc = "Borzoi PDA (PXA270)",
-    .init = borzoi_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine terrierpda_machine = {
-    .name = "terrier",
-    .desc = "Terrier PDA (PXA270)",
-    .init = terrier_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void spitz_machine_init(void)
-{
-    qemu_register_machine(&akitapda_machine);
-    qemu_register_machine(&spitzpda_machine);
-    qemu_register_machine(&borzoipda_machine);
-    qemu_register_machine(&terrierpda_machine);
-}
-
-machine_init(spitz_machine_init);
-
-static bool is_version_0(void *opaque, int version_id)
-{
-    return version_id == 0;
-}
-
-static VMStateDescription vmstate_sl_nand_info = {
-    .name = "sl-nand",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields = (VMStateField []) {
-        VMSTATE_UINT8(ctl, SLNANDState),
-        VMSTATE_STRUCT(ecc, SLNANDState, 0, vmstate_ecc_state, ECCState),
-        VMSTATE_END_OF_LIST(),
-    },
-};
-
-static Property sl_nand_properties[] = {
-    DEFINE_PROP_UINT8("manf_id", SLNANDState, manf_id, NAND_MFR_SAMSUNG),
-    DEFINE_PROP_UINT8("chip_id", SLNANDState, chip_id, 0xf1),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void sl_nand_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = sl_nand_init;
-    dc->vmsd = &vmstate_sl_nand_info;
-    dc->props = sl_nand_properties;
-}
-
-static const TypeInfo sl_nand_info = {
-    .name          = "sl-nand",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SLNANDState),
-    .class_init    = sl_nand_class_init,
-};
-
-static VMStateDescription vmstate_spitz_kbd = {
-    .name = "spitz-keyboard",
-    .version_id = 1,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .post_load = spitz_keyboard_post_load,
-    .fields = (VMStateField []) {
-        VMSTATE_UINT16(sense_state, SpitzKeyboardState),
-        VMSTATE_UINT16(strobe_state, SpitzKeyboardState),
-        VMSTATE_UNUSED_TEST(is_version_0, 5),
-        VMSTATE_END_OF_LIST(),
-    },
-};
-
-static Property spitz_keyboard_properties[] = {
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void spitz_keyboard_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = spitz_keyboard_init;
-    dc->vmsd = &vmstate_spitz_kbd;
-    dc->props = spitz_keyboard_properties;
-}
-
-static const TypeInfo spitz_keyboard_info = {
-    .name          = "spitz-keyboard",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SpitzKeyboardState),
-    .class_init    = spitz_keyboard_class_init,
-};
-
-static const VMStateDescription vmstate_corgi_ssp_regs = {
-    .name = "corgi-ssp",
-    .version_id = 2,
-    .minimum_version_id = 2,
-    .minimum_version_id_old = 2,
-    .fields = (VMStateField []) {
-        VMSTATE_SSI_SLAVE(ssidev, CorgiSSPState),
-        VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3),
-        VMSTATE_END_OF_LIST(),
-    }
-};
-
-static void corgi_ssp_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
-
-    k->init = corgi_ssp_init;
-    k->transfer = corgi_ssp_transfer;
-    dc->vmsd = &vmstate_corgi_ssp_regs;
-}
-
-static const TypeInfo corgi_ssp_info = {
-    .name          = "corgi-ssp",
-    .parent        = TYPE_SSI_SLAVE,
-    .instance_size = sizeof(CorgiSSPState),
-    .class_init    = corgi_ssp_class_init,
-};
-
-static const VMStateDescription vmstate_spitz_lcdtg_regs = {
-    .name = "spitz-lcdtg",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField []) {
-        VMSTATE_SSI_SLAVE(ssidev, SpitzLCDTG),
-        VMSTATE_UINT32(bl_intensity, SpitzLCDTG),
-        VMSTATE_UINT32(bl_power, SpitzLCDTG),
-        VMSTATE_END_OF_LIST(),
-    }
-};
-
-static void spitz_lcdtg_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
-
-    k->init = spitz_lcdtg_init;
-    k->transfer = spitz_lcdtg_transfer;
-    dc->vmsd = &vmstate_spitz_lcdtg_regs;
-}
-
-static const TypeInfo spitz_lcdtg_info = {
-    .name          = "spitz-lcdtg",
-    .parent        = TYPE_SSI_SLAVE,
-    .instance_size = sizeof(SpitzLCDTG),
-    .class_init    = spitz_lcdtg_class_init,
-};
-
-static void spitz_register_types(void)
-{
-    type_register_static(&corgi_ssp_info);
-    type_register_static(&spitz_lcdtg_info);
-    type_register_static(&spitz_keyboard_info);
-    type_register_static(&sl_nand_info);
-}
-
-type_init(spitz_register_types)
index 8777b1681ae69bc6a69d6095e6a5af7722902f7f..db50909734998386eea6ecba8c3aeb07a3c286a0 100644 (file)
@@ -10,7 +10,7 @@
 /* The controller can support a variety of different displays, but we only
    implement one.  Most of the commends relating to brightness and geometry
    setup are ignored. */
-#include "i2c.h"
+#include "hw/i2c.h"
 #include "ui/console.h"
 
 //#define DEBUG_SSD0303 1
index 84c86a52446b83b0126f8db4e0b05b15768230ce..27b415199451496aae82ba61c65ed037c0449982 100644 (file)
@@ -10,7 +10,7 @@
 /* The controller can support a variety of different displays, but we only
    implement one.  Most of the commends relating to brightness and geometry
    setup are ignored. */
-#include "ssi.h"
+#include "hw/ssi.h"
 #include "ui/console.h"
 
 //#define DEBUG_SSD0323 1
index dca8906e7db7635f6ec353cf17d2f2c13027e4d4..4d3c4f6445d370cf513ccc03c2544d2c1d122ba0 100644 (file)
@@ -11,8 +11,8 @@
  */
 
 #include "sysemu/blockdev.h"
-#include "ssi.h"
-#include "sd.h"
+#include "hw/ssi.h"
+#include "hw/sd.h"
 
 //#define DEBUG_SSI_SD 1
 
index 0b18176f7a788b6a5564278eae1e2d057160272c..1264d9da23d1c4adf9037178ddc03befa0e376a4 100644 (file)
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -12,7 +12,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "ssi.h"
+#include "hw/ssi.h"
 
 struct SSIBus {
     BusState qbus;
index a05d60beb4ad6e5a394ff864fd2230bb93da6620..fdae317295af5347a157569bdbcfa16d84d05f01 100644 (file)
--- a/hw/ssi.h
+++ b/hw/ssi.h
@@ -11,7 +11,7 @@
 #ifndef QEMU_SSI_H
 #define QEMU_SSI_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 typedef struct SSISlave SSISlave;
 
diff --git a/hw/stellaris.c b/hw/stellaris.c
deleted file mode 100644 (file)
index 9b8f203..0000000
+++ /dev/null
@@ -1,1401 +0,0 @@
-/*
- * Luminary Micro Stellaris peripherals
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "sysbus.h"
-#include "ssi.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "qemu/timer.h"
-#include "i2c.h"
-#include "net/net.h"
-#include "boards.h"
-#include "exec/address-spaces.h"
-
-#define GPIO_A 0
-#define GPIO_B 1
-#define GPIO_C 2
-#define GPIO_D 3
-#define GPIO_E 4
-#define GPIO_F 5
-#define GPIO_G 6
-
-#define BP_OLED_I2C  0x01
-#define BP_OLED_SSI  0x02
-#define BP_GAMEPAD   0x04
-
-typedef const struct {
-    const char *name;
-    uint32_t did0;
-    uint32_t did1;
-    uint32_t dc0;
-    uint32_t dc1;
-    uint32_t dc2;
-    uint32_t dc3;
-    uint32_t dc4;
-    uint32_t peripherals;
-} stellaris_board_info;
-
-/* General purpose timer module.  */
-
-typedef struct gptm_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t config;
-    uint32_t mode[2];
-    uint32_t control;
-    uint32_t state;
-    uint32_t mask;
-    uint32_t load[2];
-    uint32_t match[2];
-    uint32_t prescale[2];
-    uint32_t match_prescale[2];
-    uint32_t rtc;
-    int64_t tick[2];
-    struct gptm_state *opaque[2];
-    QEMUTimer *timer[2];
-    /* The timers have an alternate output used to trigger the ADC.  */
-    qemu_irq trigger;
-    qemu_irq irq;
-} gptm_state;
-
-static void gptm_update_irq(gptm_state *s)
-{
-    int level;
-    level = (s->state & s->mask) != 0;
-    qemu_set_irq(s->irq, level);
-}
-
-static void gptm_stop(gptm_state *s, int n)
-{
-    qemu_del_timer(s->timer[n]);
-}
-
-static void gptm_reload(gptm_state *s, int n, int reset)
-{
-    int64_t tick;
-    if (reset)
-        tick = qemu_get_clock_ns(vm_clock);
-    else
-        tick = s->tick[n];
-
-    if (s->config == 0) {
-        /* 32-bit CountDown.  */
-        uint32_t count;
-        count = s->load[0] | (s->load[1] << 16);
-        tick += (int64_t)count * system_clock_scale;
-    } else if (s->config == 1) {
-        /* 32-bit RTC.  1Hz tick.  */
-        tick += get_ticks_per_sec();
-    } else if (s->mode[n] == 0xa) {
-        /* PWM mode.  Not implemented.  */
-    } else {
-        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
-    }
-    s->tick[n] = tick;
-    qemu_mod_timer(s->timer[n], tick);
-}
-
-static void gptm_tick(void *opaque)
-{
-    gptm_state **p = (gptm_state **)opaque;
-    gptm_state *s;
-    int n;
-
-    s = *p;
-    n = p - s->opaque;
-    if (s->config == 0) {
-        s->state |= 1;
-        if ((s->control & 0x20)) {
-            /* Output trigger.  */
-           qemu_irq_pulse(s->trigger);
-        }
-        if (s->mode[0] & 1) {
-            /* One-shot.  */
-            s->control &= ~1;
-        } else {
-            /* Periodic.  */
-            gptm_reload(s, 0, 0);
-        }
-    } else if (s->config == 1) {
-        /* RTC.  */
-        uint32_t match;
-        s->rtc++;
-        match = s->match[0] | (s->match[1] << 16);
-        if (s->rtc > match)
-            s->rtc = 0;
-        if (s->rtc == 0) {
-            s->state |= 8;
-        }
-        gptm_reload(s, 0, 0);
-    } else if (s->mode[n] == 0xa) {
-        /* PWM mode.  Not implemented.  */
-    } else {
-        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
-    }
-    gptm_update_irq(s);
-}
-
-static uint64_t gptm_read(void *opaque, hwaddr offset,
-                          unsigned size)
-{
-    gptm_state *s = (gptm_state *)opaque;
-
-    switch (offset) {
-    case 0x00: /* CFG */
-        return s->config;
-    case 0x04: /* TAMR */
-        return s->mode[0];
-    case 0x08: /* TBMR */
-        return s->mode[1];
-    case 0x0c: /* CTL */
-        return s->control;
-    case 0x18: /* IMR */
-        return s->mask;
-    case 0x1c: /* RIS */
-        return s->state;
-    case 0x20: /* MIS */
-        return s->state & s->mask;
-    case 0x24: /* CR */
-        return 0;
-    case 0x28: /* TAILR */
-        return s->load[0] | ((s->config < 4) ? (s->load[1] << 16) : 0);
-    case 0x2c: /* TBILR */
-        return s->load[1];
-    case 0x30: /* TAMARCHR */
-        return s->match[0] | ((s->config < 4) ? (s->match[1] << 16) : 0);
-    case 0x34: /* TBMATCHR */
-        return s->match[1];
-    case 0x38: /* TAPR */
-        return s->prescale[0];
-    case 0x3c: /* TBPR */
-        return s->prescale[1];
-    case 0x40: /* TAPMR */
-        return s->match_prescale[0];
-    case 0x44: /* TBPMR */
-        return s->match_prescale[1];
-    case 0x48: /* TAR */
-        if (s->control == 1)
-            return s->rtc;
-    case 0x4c: /* TBR */
-        hw_error("TODO: Timer value read\n");
-    default:
-        hw_error("gptm_read: Bad offset 0x%x\n", (int)offset);
-        return 0;
-    }
-}
-
-static void gptm_write(void *opaque, hwaddr offset,
-                       uint64_t value, unsigned size)
-{
-    gptm_state *s = (gptm_state *)opaque;
-    uint32_t oldval;
-
-    /* The timers should be disabled before changing the configuration.
-       We take advantage of this and defer everything until the timer
-       is enabled.  */
-    switch (offset) {
-    case 0x00: /* CFG */
-        s->config = value;
-        break;
-    case 0x04: /* TAMR */
-        s->mode[0] = value;
-        break;
-    case 0x08: /* TBMR */
-        s->mode[1] = value;
-        break;
-    case 0x0c: /* CTL */
-        oldval = s->control;
-        s->control = value;
-        /* TODO: Implement pause.  */
-        if ((oldval ^ value) & 1) {
-            if (value & 1) {
-                gptm_reload(s, 0, 1);
-            } else {
-                gptm_stop(s, 0);
-            }
-        }
-        if (((oldval ^ value) & 0x100) && s->config >= 4) {
-            if (value & 0x100) {
-                gptm_reload(s, 1, 1);
-            } else {
-                gptm_stop(s, 1);
-            }
-        }
-        break;
-    case 0x18: /* IMR */
-        s->mask = value & 0x77;
-        gptm_update_irq(s);
-        break;
-    case 0x24: /* CR */
-        s->state &= ~value;
-        break;
-    case 0x28: /* TAILR */
-        s->load[0] = value & 0xffff;
-        if (s->config < 4) {
-            s->load[1] = value >> 16;
-        }
-        break;
-    case 0x2c: /* TBILR */
-        s->load[1] = value & 0xffff;
-        break;
-    case 0x30: /* TAMARCHR */
-        s->match[0] = value & 0xffff;
-        if (s->config < 4) {
-            s->match[1] = value >> 16;
-        }
-        break;
-    case 0x34: /* TBMATCHR */
-        s->match[1] = value >> 16;
-        break;
-    case 0x38: /* TAPR */
-        s->prescale[0] = value;
-        break;
-    case 0x3c: /* TBPR */
-        s->prescale[1] = value;
-        break;
-    case 0x40: /* TAPMR */
-        s->match_prescale[0] = value;
-        break;
-    case 0x44: /* TBPMR */
-        s->match_prescale[0] = value;
-        break;
-    default:
-        hw_error("gptm_write: Bad offset 0x%x\n", (int)offset);
-    }
-    gptm_update_irq(s);
-}
-
-static const MemoryRegionOps gptm_ops = {
-    .read = gptm_read,
-    .write = gptm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_stellaris_gptm = {
-    .name = "stellaris_gptm",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32(config, gptm_state),
-        VMSTATE_UINT32_ARRAY(mode, gptm_state, 2),
-        VMSTATE_UINT32(control, gptm_state),
-        VMSTATE_UINT32(state, gptm_state),
-        VMSTATE_UINT32(mask, gptm_state),
-        VMSTATE_UNUSED(8),
-        VMSTATE_UINT32_ARRAY(load, gptm_state, 2),
-        VMSTATE_UINT32_ARRAY(match, gptm_state, 2),
-        VMSTATE_UINT32_ARRAY(prescale, gptm_state, 2),
-        VMSTATE_UINT32_ARRAY(match_prescale, gptm_state, 2),
-        VMSTATE_UINT32(rtc, gptm_state),
-        VMSTATE_INT64_ARRAY(tick, gptm_state, 2),
-        VMSTATE_TIMER_ARRAY(timer, gptm_state, 2),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int stellaris_gptm_init(SysBusDevice *dev)
-{
-    gptm_state *s = FROM_SYSBUS(gptm_state, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    qdev_init_gpio_out(&dev->qdev, &s->trigger, 1);
-
-    memory_region_init_io(&s->iomem, &gptm_ops, s,
-                          "gptm", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    s->opaque[0] = s->opaque[1] = s;
-    s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]);
-    s->timer[1] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[1]);
-    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_gptm, s);
-    return 0;
-}
-
-
-/* System controller.  */
-
-typedef struct {
-    MemoryRegion iomem;
-    uint32_t pborctl;
-    uint32_t ldopctl;
-    uint32_t int_status;
-    uint32_t int_mask;
-    uint32_t resc;
-    uint32_t rcc;
-    uint32_t rcc2;
-    uint32_t rcgc[3];
-    uint32_t scgc[3];
-    uint32_t dcgc[3];
-    uint32_t clkvclr;
-    uint32_t ldoarst;
-    uint32_t user0;
-    uint32_t user1;
-    qemu_irq irq;
-    stellaris_board_info *board;
-} ssys_state;
-
-static void ssys_update(ssys_state *s)
-{
-  qemu_set_irq(s->irq, (s->int_status & s->int_mask) != 0);
-}
-
-static uint32_t pllcfg_sandstorm[16] = {
-    0x31c0, /* 1 Mhz */
-    0x1ae0, /* 1.8432 Mhz */
-    0x18c0, /* 2 Mhz */
-    0xd573, /* 2.4576 Mhz */
-    0x37a6, /* 3.57954 Mhz */
-    0x1ae2, /* 3.6864 Mhz */
-    0x0c40, /* 4 Mhz */
-    0x98bc, /* 4.906 Mhz */
-    0x935b, /* 4.9152 Mhz */
-    0x09c0, /* 5 Mhz */
-    0x4dee, /* 5.12 Mhz */
-    0x0c41, /* 6 Mhz */
-    0x75db, /* 6.144 Mhz */
-    0x1ae6, /* 7.3728 Mhz */
-    0x0600, /* 8 Mhz */
-    0x585b /* 8.192 Mhz */
-};
-
-static uint32_t pllcfg_fury[16] = {
-    0x3200, /* 1 Mhz */
-    0x1b20, /* 1.8432 Mhz */
-    0x1900, /* 2 Mhz */
-    0xf42b, /* 2.4576 Mhz */
-    0x37e3, /* 3.57954 Mhz */
-    0x1b21, /* 3.6864 Mhz */
-    0x0c80, /* 4 Mhz */
-    0x98ee, /* 4.906 Mhz */
-    0xd5b4, /* 4.9152 Mhz */
-    0x0a00, /* 5 Mhz */
-    0x4e27, /* 5.12 Mhz */
-    0x1902, /* 6 Mhz */
-    0xec1c, /* 6.144 Mhz */
-    0x1b23, /* 7.3728 Mhz */
-    0x0640, /* 8 Mhz */
-    0xb11c /* 8.192 Mhz */
-};
-
-#define DID0_VER_MASK        0x70000000
-#define DID0_VER_0           0x00000000
-#define DID0_VER_1           0x10000000
-
-#define DID0_CLASS_MASK      0x00FF0000
-#define DID0_CLASS_SANDSTORM 0x00000000
-#define DID0_CLASS_FURY      0x00010000
-
-static int ssys_board_class(const ssys_state *s)
-{
-    uint32_t did0 = s->board->did0;
-    switch (did0 & DID0_VER_MASK) {
-    case DID0_VER_0:
-        return DID0_CLASS_SANDSTORM;
-    case DID0_VER_1:
-        switch (did0 & DID0_CLASS_MASK) {
-        case DID0_CLASS_SANDSTORM:
-        case DID0_CLASS_FURY:
-            return did0 & DID0_CLASS_MASK;
-        }
-        /* for unknown classes, fall through */
-    default:
-        hw_error("ssys_board_class: Unknown class 0x%08x\n", did0);
-    }
-}
-
-static uint64_t ssys_read(void *opaque, hwaddr offset,
-                          unsigned size)
-{
-    ssys_state *s = (ssys_state *)opaque;
-
-    switch (offset) {
-    case 0x000: /* DID0 */
-        return s->board->did0;
-    case 0x004: /* DID1 */
-        return s->board->did1;
-    case 0x008: /* DC0 */
-        return s->board->dc0;
-    case 0x010: /* DC1 */
-        return s->board->dc1;
-    case 0x014: /* DC2 */
-        return s->board->dc2;
-    case 0x018: /* DC3 */
-        return s->board->dc3;
-    case 0x01c: /* DC4 */
-        return s->board->dc4;
-    case 0x030: /* PBORCTL */
-        return s->pborctl;
-    case 0x034: /* LDOPCTL */
-        return s->ldopctl;
-    case 0x040: /* SRCR0 */
-        return 0;
-    case 0x044: /* SRCR1 */
-        return 0;
-    case 0x048: /* SRCR2 */
-        return 0;
-    case 0x050: /* RIS */
-        return s->int_status;
-    case 0x054: /* IMC */
-        return s->int_mask;
-    case 0x058: /* MISC */
-        return s->int_status & s->int_mask;
-    case 0x05c: /* RESC */
-        return s->resc;
-    case 0x060: /* RCC */
-        return s->rcc;
-    case 0x064: /* PLLCFG */
-        {
-            int xtal;
-            xtal = (s->rcc >> 6) & 0xf;
-            switch (ssys_board_class(s)) {
-            case DID0_CLASS_FURY:
-                return pllcfg_fury[xtal];
-            case DID0_CLASS_SANDSTORM:
-                return pllcfg_sandstorm[xtal];
-            default:
-                hw_error("ssys_read: Unhandled class for PLLCFG read.\n");
-                return 0;
-            }
-        }
-    case 0x070: /* RCC2 */
-        return s->rcc2;
-    case 0x100: /* RCGC0 */
-        return s->rcgc[0];
-    case 0x104: /* RCGC1 */
-        return s->rcgc[1];
-    case 0x108: /* RCGC2 */
-        return s->rcgc[2];
-    case 0x110: /* SCGC0 */
-        return s->scgc[0];
-    case 0x114: /* SCGC1 */
-        return s->scgc[1];
-    case 0x118: /* SCGC2 */
-        return s->scgc[2];
-    case 0x120: /* DCGC0 */
-        return s->dcgc[0];
-    case 0x124: /* DCGC1 */
-        return s->dcgc[1];
-    case 0x128: /* DCGC2 */
-        return s->dcgc[2];
-    case 0x150: /* CLKVCLR */
-        return s->clkvclr;
-    case 0x160: /* LDOARST */
-        return s->ldoarst;
-    case 0x1e0: /* USER0 */
-        return s->user0;
-    case 0x1e4: /* USER1 */
-        return s->user1;
-    default:
-        hw_error("ssys_read: Bad offset 0x%x\n", (int)offset);
-        return 0;
-    }
-}
-
-static bool ssys_use_rcc2(ssys_state *s)
-{
-    return (s->rcc2 >> 31) & 0x1;
-}
-
-/*
- * Caculate the sys. clock period in ms.
- */
-static void ssys_calculate_system_clock(ssys_state *s)
-{
-    if (ssys_use_rcc2(s)) {
-        system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
-    } else {
-        system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
-    }
-}
-
-static void ssys_write(void *opaque, hwaddr offset,
-                       uint64_t value, unsigned size)
-{
-    ssys_state *s = (ssys_state *)opaque;
-
-    switch (offset) {
-    case 0x030: /* PBORCTL */
-        s->pborctl = value & 0xffff;
-        break;
-    case 0x034: /* LDOPCTL */
-        s->ldopctl = value & 0x1f;
-        break;
-    case 0x040: /* SRCR0 */
-    case 0x044: /* SRCR1 */
-    case 0x048: /* SRCR2 */
-        fprintf(stderr, "Peripheral reset not implemented\n");
-        break;
-    case 0x054: /* IMC */
-        s->int_mask = value & 0x7f;
-        break;
-    case 0x058: /* MISC */
-        s->int_status &= ~value;
-        break;
-    case 0x05c: /* RESC */
-        s->resc = value & 0x3f;
-        break;
-    case 0x060: /* RCC */
-        if ((s->rcc & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
-            /* PLL enable.  */
-            s->int_status |= (1 << 6);
-        }
-        s->rcc = value;
-        ssys_calculate_system_clock(s);
-        break;
-    case 0x070: /* RCC2 */
-        if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
-            break;
-        }
-
-        if ((s->rcc2 & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
-            /* PLL enable.  */
-            s->int_status |= (1 << 6);
-        }
-        s->rcc2 = value;
-        ssys_calculate_system_clock(s);
-        break;
-    case 0x100: /* RCGC0 */
-        s->rcgc[0] = value;
-        break;
-    case 0x104: /* RCGC1 */
-        s->rcgc[1] = value;
-        break;
-    case 0x108: /* RCGC2 */
-        s->rcgc[2] = value;
-        break;
-    case 0x110: /* SCGC0 */
-        s->scgc[0] = value;
-        break;
-    case 0x114: /* SCGC1 */
-        s->scgc[1] = value;
-        break;
-    case 0x118: /* SCGC2 */
-        s->scgc[2] = value;
-        break;
-    case 0x120: /* DCGC0 */
-        s->dcgc[0] = value;
-        break;
-    case 0x124: /* DCGC1 */
-        s->dcgc[1] = value;
-        break;
-    case 0x128: /* DCGC2 */
-        s->dcgc[2] = value;
-        break;
-    case 0x150: /* CLKVCLR */
-        s->clkvclr = value;
-        break;
-    case 0x160: /* LDOARST */
-        s->ldoarst = value;
-        break;
-    default:
-        hw_error("ssys_write: Bad offset 0x%x\n", (int)offset);
-    }
-    ssys_update(s);
-}
-
-static const MemoryRegionOps ssys_ops = {
-    .read = ssys_read,
-    .write = ssys_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ssys_reset(void *opaque)
-{
-    ssys_state *s = (ssys_state *)opaque;
-
-    s->pborctl = 0x7ffd;
-    s->rcc = 0x078e3ac0;
-
-    if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
-        s->rcc2 = 0;
-    } else {
-        s->rcc2 = 0x07802810;
-    }
-    s->rcgc[0] = 1;
-    s->scgc[0] = 1;
-    s->dcgc[0] = 1;
-    ssys_calculate_system_clock(s);
-}
-
-static int stellaris_sys_post_load(void *opaque, int version_id)
-{
-    ssys_state *s = opaque;
-
-    ssys_calculate_system_clock(s);
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_stellaris_sys = {
-    .name = "stellaris_sys",
-    .version_id = 2,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .post_load = stellaris_sys_post_load,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32(pborctl, ssys_state),
-        VMSTATE_UINT32(ldopctl, ssys_state),
-        VMSTATE_UINT32(int_mask, ssys_state),
-        VMSTATE_UINT32(int_status, ssys_state),
-        VMSTATE_UINT32(resc, ssys_state),
-        VMSTATE_UINT32(rcc, ssys_state),
-        VMSTATE_UINT32_V(rcc2, ssys_state, 2),
-        VMSTATE_UINT32_ARRAY(rcgc, ssys_state, 3),
-        VMSTATE_UINT32_ARRAY(scgc, ssys_state, 3),
-        VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
-        VMSTATE_UINT32(clkvclr, ssys_state),
-        VMSTATE_UINT32(ldoarst, ssys_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int stellaris_sys_init(uint32_t base, qemu_irq irq,
-                              stellaris_board_info * board,
-                              uint8_t *macaddr)
-{
-    ssys_state *s;
-
-    s = (ssys_state *)g_malloc0(sizeof(ssys_state));
-    s->irq = irq;
-    s->board = board;
-    /* Most devices come preprogrammed with a MAC address in the user data. */
-    s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
-    s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
-
-    memory_region_init_io(&s->iomem, &ssys_ops, s, "ssys", 0x00001000);
-    memory_region_add_subregion(get_system_memory(), base, &s->iomem);
-    ssys_reset(s);
-    vmstate_register(NULL, -1, &vmstate_stellaris_sys, s);
-    return 0;
-}
-
-
-/* I2C controller.  */
-
-typedef struct {
-    SysBusDevice busdev;
-    i2c_bus *bus;
-    qemu_irq irq;
-    MemoryRegion iomem;
-    uint32_t msa;
-    uint32_t mcs;
-    uint32_t mdr;
-    uint32_t mtpr;
-    uint32_t mimr;
-    uint32_t mris;
-    uint32_t mcr;
-} stellaris_i2c_state;
-
-#define STELLARIS_I2C_MCS_BUSY    0x01
-#define STELLARIS_I2C_MCS_ERROR   0x02
-#define STELLARIS_I2C_MCS_ADRACK  0x04
-#define STELLARIS_I2C_MCS_DATACK  0x08
-#define STELLARIS_I2C_MCS_ARBLST  0x10
-#define STELLARIS_I2C_MCS_IDLE    0x20
-#define STELLARIS_I2C_MCS_BUSBSY  0x40
-
-static uint64_t stellaris_i2c_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
-
-    switch (offset) {
-    case 0x00: /* MSA */
-        return s->msa;
-    case 0x04: /* MCS */
-        /* We don't emulate timing, so the controller is never busy.  */
-        return s->mcs | STELLARIS_I2C_MCS_IDLE;
-    case 0x08: /* MDR */
-        return s->mdr;
-    case 0x0c: /* MTPR */
-        return s->mtpr;
-    case 0x10: /* MIMR */
-        return s->mimr;
-    case 0x14: /* MRIS */
-        return s->mris;
-    case 0x18: /* MMIS */
-        return s->mris & s->mimr;
-    case 0x20: /* MCR */
-        return s->mcr;
-    default:
-        hw_error("strllaris_i2c_read: Bad offset 0x%x\n", (int)offset);
-        return 0;
-    }
-}
-
-static void stellaris_i2c_update(stellaris_i2c_state *s)
-{
-    int level;
-
-    level = (s->mris & s->mimr) != 0;
-    qemu_set_irq(s->irq, level);
-}
-
-static void stellaris_i2c_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
-
-    switch (offset) {
-    case 0x00: /* MSA */
-        s->msa = value & 0xff;
-        break;
-    case 0x04: /* MCS */
-        if ((s->mcr & 0x10) == 0) {
-            /* Disabled.  Do nothing.  */
-            break;
-        }
-        /* Grab the bus if this is starting a transfer.  */
-        if ((value & 2) && (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
-            if (i2c_start_transfer(s->bus, s->msa >> 1, s->msa & 1)) {
-                s->mcs |= STELLARIS_I2C_MCS_ARBLST;
-            } else {
-                s->mcs &= ~STELLARIS_I2C_MCS_ARBLST;
-                s->mcs |= STELLARIS_I2C_MCS_BUSBSY;
-            }
-        }
-        /* If we don't have the bus then indicate an error.  */
-        if (!i2c_bus_busy(s->bus)
-                || (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
-            s->mcs |= STELLARIS_I2C_MCS_ERROR;
-            break;
-        }
-        s->mcs &= ~STELLARIS_I2C_MCS_ERROR;
-        if (value & 1) {
-            /* Transfer a byte.  */
-            /* TODO: Handle errors.  */
-            if (s->msa & 1) {
-                /* Recv */
-                s->mdr = i2c_recv(s->bus) & 0xff;
-            } else {
-                /* Send */
-                i2c_send(s->bus, s->mdr);
-            }
-            /* Raise an interrupt.  */
-            s->mris |= 1;
-        }
-        if (value & 4) {
-            /* Finish transfer.  */
-            i2c_end_transfer(s->bus);
-            s->mcs &= ~STELLARIS_I2C_MCS_BUSBSY;
-        }
-        break;
-    case 0x08: /* MDR */
-        s->mdr = value & 0xff;
-        break;
-    case 0x0c: /* MTPR */
-        s->mtpr = value & 0xff;
-        break;
-    case 0x10: /* MIMR */
-        s->mimr = 1;
-        break;
-    case 0x1c: /* MICR */
-        s->mris &= ~value;
-        break;
-    case 0x20: /* MCR */
-        if (value & 1)
-            hw_error(
-                      "stellaris_i2c_write: Loopback not implemented\n");
-        if (value & 0x20)
-            hw_error(
-                      "stellaris_i2c_write: Slave mode not implemented\n");
-        s->mcr = value & 0x31;
-        break;
-    default:
-        hw_error("stellaris_i2c_write: Bad offset 0x%x\n",
-                  (int)offset);
-    }
-    stellaris_i2c_update(s);
-}
-
-static void stellaris_i2c_reset(stellaris_i2c_state *s)
-{
-    if (s->mcs & STELLARIS_I2C_MCS_BUSBSY)
-        i2c_end_transfer(s->bus);
-
-    s->msa = 0;
-    s->mcs = 0;
-    s->mdr = 0;
-    s->mtpr = 1;
-    s->mimr = 0;
-    s->mris = 0;
-    s->mcr = 0;
-    stellaris_i2c_update(s);
-}
-
-static const MemoryRegionOps stellaris_i2c_ops = {
-    .read = stellaris_i2c_read,
-    .write = stellaris_i2c_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_stellaris_i2c = {
-    .name = "stellaris_i2c",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32(msa, stellaris_i2c_state),
-        VMSTATE_UINT32(mcs, stellaris_i2c_state),
-        VMSTATE_UINT32(mdr, stellaris_i2c_state),
-        VMSTATE_UINT32(mtpr, stellaris_i2c_state),
-        VMSTATE_UINT32(mimr, stellaris_i2c_state),
-        VMSTATE_UINT32(mris, stellaris_i2c_state),
-        VMSTATE_UINT32(mcr, stellaris_i2c_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int stellaris_i2c_init(SysBusDevice * dev)
-{
-    stellaris_i2c_state *s = FROM_SYSBUS(stellaris_i2c_state, dev);
-    i2c_bus *bus;
-
-    sysbus_init_irq(dev, &s->irq);
-    bus = i2c_init_bus(&dev->qdev, "i2c");
-    s->bus = bus;
-
-    memory_region_init_io(&s->iomem, &stellaris_i2c_ops, s,
-                          "i2c", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    /* ??? For now we only implement the master interface.  */
-    stellaris_i2c_reset(s);
-    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
-    return 0;
-}
-
-/* Analogue to Digital Converter.  This is only partially implemented,
-   enough for applications that use a combined ADC and timer tick.  */
-
-#define STELLARIS_ADC_EM_CONTROLLER 0
-#define STELLARIS_ADC_EM_COMP       1
-#define STELLARIS_ADC_EM_EXTERNAL   4
-#define STELLARIS_ADC_EM_TIMER      5
-#define STELLARIS_ADC_EM_PWM0       6
-#define STELLARIS_ADC_EM_PWM1       7
-#define STELLARIS_ADC_EM_PWM2       8
-
-#define STELLARIS_ADC_FIFO_EMPTY    0x0100
-#define STELLARIS_ADC_FIFO_FULL     0x1000
-
-typedef struct
-{
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t actss;
-    uint32_t ris;
-    uint32_t im;
-    uint32_t emux;
-    uint32_t ostat;
-    uint32_t ustat;
-    uint32_t sspri;
-    uint32_t sac;
-    struct {
-        uint32_t state;
-        uint32_t data[16];
-    } fifo[4];
-    uint32_t ssmux[4];
-    uint32_t ssctl[4];
-    uint32_t noise;
-    qemu_irq irq[4];
-} stellaris_adc_state;
-
-static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
-{
-    int tail;
-
-    tail = s->fifo[n].state & 0xf;
-    if (s->fifo[n].state & STELLARIS_ADC_FIFO_EMPTY) {
-        s->ustat |= 1 << n;
-    } else {
-        s->fifo[n].state = (s->fifo[n].state & ~0xf) | ((tail + 1) & 0xf);
-        s->fifo[n].state &= ~STELLARIS_ADC_FIFO_FULL;
-        if (tail + 1 == ((s->fifo[n].state >> 4) & 0xf))
-            s->fifo[n].state |= STELLARIS_ADC_FIFO_EMPTY;
-    }
-    return s->fifo[n].data[tail];
-}
-
-static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
-                                     uint32_t value)
-{
-    int head;
-
-    /* TODO: Real hardware has limited size FIFOs.  We have a full 16 entry 
-       FIFO fir each sequencer.  */
-    head = (s->fifo[n].state >> 4) & 0xf;
-    if (s->fifo[n].state & STELLARIS_ADC_FIFO_FULL) {
-        s->ostat |= 1 << n;
-        return;
-    }
-    s->fifo[n].data[head] = value;
-    head = (head + 1) & 0xf;
-    s->fifo[n].state &= ~STELLARIS_ADC_FIFO_EMPTY;
-    s->fifo[n].state = (s->fifo[n].state & ~0xf0) | (head << 4);
-    if ((s->fifo[n].state & 0xf) == head)
-        s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;
-}
-
-static void stellaris_adc_update(stellaris_adc_state *s)
-{
-    int level;
-    int n;
-
-    for (n = 0; n < 4; n++) {
-        level = (s->ris & s->im & (1 << n)) != 0;
-        qemu_set_irq(s->irq[n], level);
-    }
-}
-
-static void stellaris_adc_trigger(void *opaque, int irq, int level)
-{
-    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
-    int n;
-
-    for (n = 0; n < 4; n++) {
-        if ((s->actss & (1 << n)) == 0) {
-            continue;
-        }
-
-        if (((s->emux >> (n * 4)) & 0xff) != 5) {
-            continue;
-        }
-
-        /* Some applications use the ADC as a random number source, so introduce
-           some variation into the signal.  */
-        s->noise = s->noise * 314159 + 1;
-        /* ??? actual inputs not implemented.  Return an arbitrary value.  */
-        stellaris_adc_fifo_write(s, n, 0x200 + ((s->noise >> 16) & 7));
-        s->ris |= (1 << n);
-        stellaris_adc_update(s);
-    }
-}
-
-static void stellaris_adc_reset(stellaris_adc_state *s)
-{
-    int n;
-
-    for (n = 0; n < 4; n++) {
-        s->ssmux[n] = 0;
-        s->ssctl[n] = 0;
-        s->fifo[n].state = STELLARIS_ADC_FIFO_EMPTY;
-    }
-}
-
-static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
-
-    /* TODO: Implement this.  */
-    if (offset >= 0x40 && offset < 0xc0) {
-        int n;
-        n = (offset - 0x40) >> 5;
-        switch (offset & 0x1f) {
-        case 0x00: /* SSMUX */
-            return s->ssmux[n];
-        case 0x04: /* SSCTL */
-            return s->ssctl[n];
-        case 0x08: /* SSFIFO */
-            return stellaris_adc_fifo_read(s, n);
-        case 0x0c: /* SSFSTAT */
-            return s->fifo[n].state;
-        default:
-            break;
-        }
-    }
-    switch (offset) {
-    case 0x00: /* ACTSS */
-        return s->actss;
-    case 0x04: /* RIS */
-        return s->ris;
-    case 0x08: /* IM */
-        return s->im;
-    case 0x0c: /* ISC */
-        return s->ris & s->im;
-    case 0x10: /* OSTAT */
-        return s->ostat;
-    case 0x14: /* EMUX */
-        return s->emux;
-    case 0x18: /* USTAT */
-        return s->ustat;
-    case 0x20: /* SSPRI */
-        return s->sspri;
-    case 0x30: /* SAC */
-        return s->sac;
-    default:
-        hw_error("strllaris_adc_read: Bad offset 0x%x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void stellaris_adc_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
-
-    /* TODO: Implement this.  */
-    if (offset >= 0x40 && offset < 0xc0) {
-        int n;
-        n = (offset - 0x40) >> 5;
-        switch (offset & 0x1f) {
-        case 0x00: /* SSMUX */
-            s->ssmux[n] = value & 0x33333333;
-            return;
-        case 0x04: /* SSCTL */
-            if (value != 6) {
-                hw_error("ADC: Unimplemented sequence %" PRIx64 "\n",
-                          value);
-            }
-            s->ssctl[n] = value;
-            return;
-        default:
-            break;
-        }
-    }
-    switch (offset) {
-    case 0x00: /* ACTSS */
-        s->actss = value & 0xf;
-        break;
-    case 0x08: /* IM */
-        s->im = value;
-        break;
-    case 0x0c: /* ISC */
-        s->ris &= ~value;
-        break;
-    case 0x10: /* OSTAT */
-        s->ostat &= ~value;
-        break;
-    case 0x14: /* EMUX */
-        s->emux = value;
-        break;
-    case 0x18: /* USTAT */
-        s->ustat &= ~value;
-        break;
-    case 0x20: /* SSPRI */
-        s->sspri = value;
-        break;
-    case 0x28: /* PSSI */
-        hw_error("Not implemented:  ADC sample initiate\n");
-        break;
-    case 0x30: /* SAC */
-        s->sac = value;
-        break;
-    default:
-        hw_error("stellaris_adc_write: Bad offset 0x%x\n", (int)offset);
-    }
-    stellaris_adc_update(s);
-}
-
-static const MemoryRegionOps stellaris_adc_ops = {
-    .read = stellaris_adc_read,
-    .write = stellaris_adc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_stellaris_adc = {
-    .name = "stellaris_adc",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32(actss, stellaris_adc_state),
-        VMSTATE_UINT32(ris, stellaris_adc_state),
-        VMSTATE_UINT32(im, stellaris_adc_state),
-        VMSTATE_UINT32(emux, stellaris_adc_state),
-        VMSTATE_UINT32(ostat, stellaris_adc_state),
-        VMSTATE_UINT32(ustat, stellaris_adc_state),
-        VMSTATE_UINT32(sspri, stellaris_adc_state),
-        VMSTATE_UINT32(sac, stellaris_adc_state),
-        VMSTATE_UINT32(fifo[0].state, stellaris_adc_state),
-        VMSTATE_UINT32_ARRAY(fifo[0].data, stellaris_adc_state, 16),
-        VMSTATE_UINT32(ssmux[0], stellaris_adc_state),
-        VMSTATE_UINT32(ssctl[0], stellaris_adc_state),
-        VMSTATE_UINT32(fifo[1].state, stellaris_adc_state),
-        VMSTATE_UINT32_ARRAY(fifo[1].data, stellaris_adc_state, 16),
-        VMSTATE_UINT32(ssmux[1], stellaris_adc_state),
-        VMSTATE_UINT32(ssctl[1], stellaris_adc_state),
-        VMSTATE_UINT32(fifo[2].state, stellaris_adc_state),
-        VMSTATE_UINT32_ARRAY(fifo[2].data, stellaris_adc_state, 16),
-        VMSTATE_UINT32(ssmux[2], stellaris_adc_state),
-        VMSTATE_UINT32(ssctl[2], stellaris_adc_state),
-        VMSTATE_UINT32(fifo[3].state, stellaris_adc_state),
-        VMSTATE_UINT32_ARRAY(fifo[3].data, stellaris_adc_state, 16),
-        VMSTATE_UINT32(ssmux[3], stellaris_adc_state),
-        VMSTATE_UINT32(ssctl[3], stellaris_adc_state),
-        VMSTATE_UINT32(noise, stellaris_adc_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int stellaris_adc_init(SysBusDevice *dev)
-{
-    stellaris_adc_state *s = FROM_SYSBUS(stellaris_adc_state, dev);
-    int n;
-
-    for (n = 0; n < 4; n++) {
-        sysbus_init_irq(dev, &s->irq[n]);
-    }
-
-    memory_region_init_io(&s->iomem, &stellaris_adc_ops, s,
-                          "adc", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    stellaris_adc_reset(s);
-    qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
-    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
-    return 0;
-}
-
-/* Board init.  */
-static stellaris_board_info stellaris_boards[] = {
-  { "LM3S811EVB",
-    0,
-    0x0032000e,
-    0x001f001f, /* dc0 */
-    0x001132bf,
-    0x01071013,
-    0x3f0f01ff,
-    0x0000001f,
-    BP_OLED_I2C
-  },
-  { "LM3S6965EVB",
-    0x10010002,
-    0x1073402e,
-    0x00ff007f, /* dc0 */
-    0x001133ff,
-    0x030f5317,
-    0x0f0f87ff,
-    0x5000007f,
-    BP_OLED_SSI | BP_GAMEPAD
-  }
-};
-
-static void stellaris_init(const char *kernel_filename, const char *cpu_model,
-                           stellaris_board_info *board)
-{
-    static const int uart_irq[] = {5, 6, 33, 34};
-    static const int timer_irq[] = {19, 21, 23, 35};
-    static const uint32_t gpio_addr[7] =
-      { 0x40004000, 0x40005000, 0x40006000, 0x40007000,
-        0x40024000, 0x40025000, 0x40026000};
-    static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
-
-    MemoryRegion *address_space_mem = get_system_memory();
-    qemu_irq *pic;
-    DeviceState *gpio_dev[7];
-    qemu_irq gpio_in[7][8];
-    qemu_irq gpio_out[7][8];
-    qemu_irq adc;
-    int sram_size;
-    int flash_size;
-    i2c_bus *i2c;
-    DeviceState *dev;
-    int i;
-    int j;
-
-    flash_size = ((board->dc0 & 0xffff) + 1) << 1;
-    sram_size = (board->dc0 >> 18) + 1;
-    pic = armv7m_init(address_space_mem,
-                      flash_size, sram_size, kernel_filename, cpu_model);
-
-    if (board->dc1 & (1 << 16)) {
-        dev = sysbus_create_varargs("stellaris-adc", 0x40038000,
-                                    pic[14], pic[15], pic[16], pic[17], NULL);
-        adc = qdev_get_gpio_in(dev, 0);
-    } else {
-        adc = NULL;
-    }
-    for (i = 0; i < 4; i++) {
-        if (board->dc2 & (0x10000 << i)) {
-            dev = sysbus_create_simple("stellaris-gptm",
-                                       0x40030000 + i * 0x1000,
-                                       pic[timer_irq[i]]);
-            /* TODO: This is incorrect, but we get away with it because
-               the ADC output is only ever pulsed.  */
-            qdev_connect_gpio_out(dev, 0, adc);
-        }
-    }
-
-    stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr.a);
-
-    for (i = 0; i < 7; i++) {
-        if (board->dc4 & (1 << i)) {
-            gpio_dev[i] = sysbus_create_simple("pl061_luminary", gpio_addr[i],
-                                               pic[gpio_irq[i]]);
-            for (j = 0; j < 8; j++) {
-                gpio_in[i][j] = qdev_get_gpio_in(gpio_dev[i], j);
-                gpio_out[i][j] = NULL;
-            }
-        }
-    }
-
-    if (board->dc2 & (1 << 12)) {
-        dev = sysbus_create_simple("stellaris-i2c", 0x40020000, pic[8]);
-        i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
-        if (board->peripherals & BP_OLED_I2C) {
-            i2c_create_slave(i2c, "ssd0303", 0x3d);
-        }
-    }
-
-    for (i = 0; i < 4; i++) {
-        if (board->dc2 & (1 << i)) {
-            sysbus_create_simple("pl011_luminary", 0x4000c000 + i * 0x1000,
-                                 pic[uart_irq[i]]);
-        }
-    }
-    if (board->dc2 & (1 << 4)) {
-        dev = sysbus_create_simple("pl022", 0x40008000, pic[7]);
-        if (board->peripherals & BP_OLED_SSI) {
-            void *bus;
-            DeviceState *sddev;
-            DeviceState *ssddev;
-
-            /* Some boards have both an OLED controller and SD card connected to
-             * the same SSI port, with the SD card chip select connected to a
-             * GPIO pin.  Technically the OLED chip select is connected to the
-             * SSI Fss pin.  We do not bother emulating that as both devices
-             * should never be selected simultaneously, and our OLED controller
-             * ignores stray 0xff commands that occur when deselecting the SD
-             * card.
-             */
-            bus = qdev_get_child_bus(dev, "ssi");
-
-            sddev = ssi_create_slave(bus, "ssi-sd");
-            ssddev = ssi_create_slave(bus, "ssd0323");
-            gpio_out[GPIO_D][0] = qemu_irq_split(qdev_get_gpio_in(sddev, 0),
-                                                 qdev_get_gpio_in(ssddev, 0));
-            gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 1);
-
-            /* Make sure the select pin is high.  */
-            qemu_irq_raise(gpio_out[GPIO_D][0]);
-        }
-    }
-    if (board->dc4 & (1 << 28)) {
-        DeviceState *enet;
-
-        qemu_check_nic_model(&nd_table[0], "stellaris");
-
-        enet = qdev_create(NULL, "stellaris_enet");
-        qdev_set_nic_properties(enet, &nd_table[0]);
-        qdev_init_nofail(enet);
-        sysbus_mmio_map(SYS_BUS_DEVICE(enet), 0, 0x40048000);
-        sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, pic[42]);
-    }
-    if (board->peripherals & BP_GAMEPAD) {
-        qemu_irq gpad_irq[5];
-        static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };
-
-        gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */
-        gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */
-        gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */
-        gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */
-        gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */
-
-        stellaris_gamepad_init(5, gpad_irq, gpad_keycode);
-    }
-    for (i = 0; i < 7; i++) {
-        if (board->dc4 & (1 << i)) {
-            for (j = 0; j < 8; j++) {
-                if (gpio_out[i][j]) {
-                    qdev_connect_gpio_out(gpio_dev[i], j, gpio_out[i][j]);
-                }
-            }
-        }
-    }
-}
-
-/* FIXME: Figure out how to generate these from stellaris_boards.  */
-static void lm3s811evb_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]);
-}
-
-static void lm3s6965evb_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]);
-}
-
-static QEMUMachine lm3s811evb_machine = {
-    .name = "lm3s811evb",
-    .desc = "Stellaris LM3S811EVB",
-    .init = lm3s811evb_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine lm3s6965evb_machine = {
-    .name = "lm3s6965evb",
-    .desc = "Stellaris LM3S6965EVB",
-    .init = lm3s6965evb_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void stellaris_machine_init(void)
-{
-    qemu_register_machine(&lm3s811evb_machine);
-    qemu_register_machine(&lm3s6965evb_machine);
-}
-
-machine_init(stellaris_machine_init);
-
-static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = stellaris_i2c_init;
-}
-
-static const TypeInfo stellaris_i2c_info = {
-    .name          = "stellaris-i2c",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(stellaris_i2c_state),
-    .class_init    = stellaris_i2c_class_init,
-};
-
-static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = stellaris_gptm_init;
-}
-
-static const TypeInfo stellaris_gptm_info = {
-    .name          = "stellaris-gptm",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(gptm_state),
-    .class_init    = stellaris_gptm_class_init,
-};
-
-static void stellaris_adc_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = stellaris_adc_init;
-}
-
-static const TypeInfo stellaris_adc_info = {
-    .name          = "stellaris-adc",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(stellaris_adc_state),
-    .class_init    = stellaris_adc_class_init,
-};
-
-static void stellaris_register_types(void)
-{
-    type_register_static(&stellaris_i2c_info);
-    type_register_static(&stellaris_gptm_info);
-    type_register_static(&stellaris_adc_info);
-}
-
-type_init(stellaris_register_types)
index 6c701fb67b99ae41e9716920c0812263fde4262c..59b84564a0e2a6025d70126631b3a413258db653 100644 (file)
@@ -6,7 +6,7 @@
  *
  * This code is licensed under the GPL.
  */
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
 #include <zlib.h>
 
index 7a95c3fc8854fe98d8dde87dd20fe59bea686831..4e407922a0679e21806231e2d1ccf3491d4c0896 100644 (file)
@@ -6,8 +6,8 @@
  *
  * This code is licensed under the GPL.
  */
-#include "hw.h"
-#include "devices.h"
+#include "hw/hw.h"
+#include "hw/devices.h"
 #include "ui/console.h"
 
 typedef struct {
index d4cf84d4c03183f1fc9d2593910a0e3c9e609f19..a07d6a56d32129f2768f7677293db3a2d53eea29 100644 (file)
@@ -1,4 +1,4 @@
-#include "stream.h"
+#include "hw/stream.h"
 
 void
 stream_push(StreamSlave *sink, uint8_t *buf, size_t len, uint32_t *app)
index ab736e300e4dec41ced37fbb1f09e9d62856602e..49f9577e32ea2b5fce85837ddfca20a81c524ff3 100644 (file)
  *  Contributions after 2012-01-13 are licensed under the terms of the
  *  GNU GPL, version 2 or (at your option) any later version.
  */
-#include "sysbus.h"
-#include "strongarm.h"
+#include "hw/sysbus.h"
+#include "hw/strongarm.h"
 #include "qemu/error-report.h"
-#include "arm-misc.h"
+#include "hw/arm-misc.h"
 #include "char/char.h"
 #include "sysemu/sysemu.h"
-#include "ssi.h"
+#include "hw/ssi.h"
 
 //#define DEBUG
 
index f8f4d023a35c50dd18c1fd05c2181f16b00acad1..9d443d1b10194c1e885d3c814c1d200c3bcc7ecd 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "sun4m.h"
+#include "hw/hw.h"
+#include "hw/sun4m.h"
 #include "monitor/monitor.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 //#define DEBUG_IRQ_COUNT
 //#define DEBUG_IRQ
diff --git a/hw/sun4m.c b/hw/sun4m.c
deleted file mode 100644 (file)
index 9903f44..0000000
+++ /dev/null
@@ -1,1936 +0,0 @@
-/*
- * QEMU Sun4m & Sun4d & Sun4c System Emulator
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "sysbus.h"
-#include "qemu/timer.h"
-#include "sun4m.h"
-#include "nvram.h"
-#include "sparc32_dma.h"
-#include "fdc.h"
-#include "sysemu/sysemu.h"
-#include "net/net.h"
-#include "boards.h"
-#include "firmware_abi.h"
-#include "esp.h"
-#include "pc.h"
-#include "isa.h"
-#include "fw_cfg.h"
-#include "escc.h"
-#include "empty_slot.h"
-#include "qdev-addr.h"
-#include "loader.h"
-#include "elf.h"
-#include "sysemu/blockdev.h"
-#include "trace.h"
-
-/*
- * Sun4m architecture was used in the following machines:
- *
- * SPARCserver 6xxMP/xx
- * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15),
- * SPARCclassic X (4/10)
- * SPARCstation LX/ZX (4/30)
- * SPARCstation Voyager
- * SPARCstation 10/xx, SPARCserver 10/xx
- * SPARCstation 5, SPARCserver 5
- * SPARCstation 20/xx, SPARCserver 20
- * SPARCstation 4
- *
- * Sun4d architecture was used in the following machines:
- *
- * SPARCcenter 2000
- * SPARCserver 1000
- *
- * Sun4c architecture was used in the following machines:
- * SPARCstation 1/1+, SPARCserver 1/1+
- * SPARCstation SLC
- * SPARCstation IPC
- * SPARCstation ELC
- * SPARCstation IPX
- *
- * See for example: http://www.sunhelp.org/faq/sunref1.html
- */
-
-#define KERNEL_LOAD_ADDR     0x00004000
-#define CMDLINE_ADDR         0x007ff000
-#define INITRD_LOAD_ADDR     0x00800000
-#define PROM_SIZE_MAX        (1024 * 1024)
-#define PROM_VADDR           0xffd00000
-#define PROM_FILENAME        "openbios-sparc32"
-#define CFG_ADDR             0xd00000510ULL
-#define FW_CFG_SUN4M_DEPTH   (FW_CFG_ARCH_LOCAL + 0x00)
-
-#define MAX_CPUS 16
-#define MAX_PILS 16
-#define MAX_VSIMMS 4
-
-#define ESCC_CLOCK 4915200
-
-struct sun4m_hwdef {
-    hwaddr iommu_base, iommu_pad_base, iommu_pad_len, slavio_base;
-    hwaddr intctl_base, counter_base, nvram_base, ms_kb_base;
-    hwaddr serial_base, fd_base;
-    hwaddr afx_base, idreg_base, dma_base, esp_base, le_base;
-    hwaddr tcx_base, cs_base, apc_base, aux1_base, aux2_base;
-    hwaddr bpp_base, dbri_base, sx_base;
-    struct {
-        hwaddr reg_base, vram_base;
-    } vsimm[MAX_VSIMMS];
-    hwaddr ecc_base;
-    uint64_t max_mem;
-    const char * const default_cpu_model;
-    uint32_t ecc_version;
-    uint32_t iommu_version;
-    uint16_t machine_id;
-    uint8_t nvram_machine_id;
-};
-
-#define MAX_IOUNITS 5
-
-struct sun4d_hwdef {
-    hwaddr iounit_bases[MAX_IOUNITS], slavio_base;
-    hwaddr counter_base, nvram_base, ms_kb_base;
-    hwaddr serial_base;
-    hwaddr espdma_base, esp_base;
-    hwaddr ledma_base, le_base;
-    hwaddr tcx_base;
-    hwaddr sbi_base;
-    uint64_t max_mem;
-    const char * const default_cpu_model;
-    uint32_t iounit_version;
-    uint16_t machine_id;
-    uint8_t nvram_machine_id;
-};
-
-struct sun4c_hwdef {
-    hwaddr iommu_base, slavio_base;
-    hwaddr intctl_base, counter_base, nvram_base, ms_kb_base;
-    hwaddr serial_base, fd_base;
-    hwaddr idreg_base, dma_base, esp_base, le_base;
-    hwaddr tcx_base, aux1_base;
-    uint64_t max_mem;
-    const char * const default_cpu_model;
-    uint32_t iommu_version;
-    uint16_t machine_id;
-    uint8_t nvram_machine_id;
-};
-
-int DMA_get_channel_mode (int nchan)
-{
-    return 0;
-}
-int DMA_read_memory (int nchan, void *buf, int pos, int size)
-{
-    return 0;
-}
-int DMA_write_memory (int nchan, void *buf, int pos, int size)
-{
-    return 0;
-}
-void DMA_hold_DREQ (int nchan) {}
-void DMA_release_DREQ (int nchan) {}
-void DMA_schedule(int nchan) {}
-
-void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
-{
-}
-
-void DMA_register_channel (int nchan,
-                           DMA_transfer_handler transfer_handler,
-                           void *opaque)
-{
-}
-
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
-{
-    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    return 0;
-}
-
-static void nvram_init(M48t59State *nvram, uint8_t *macaddr,
-                       const char *cmdline, const char *boot_devices,
-                       ram_addr_t RAM_size, uint32_t kernel_size,
-                       int width, int height, int depth,
-                       int nvram_machine_id, const char *arch)
-{
-    unsigned int i;
-    uint32_t start, end;
-    uint8_t image[0x1ff0];
-    struct OpenBIOS_nvpart_v1 *part_header;
-
-    memset(image, '\0', sizeof(image));
-
-    start = 0;
-
-    // OpenBIOS nvram variables
-    // Variable partition
-    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
-    part_header->signature = OPENBIOS_PART_SYSTEM;
-    pstrcpy(part_header->name, sizeof(part_header->name), "system");
-
-    end = start + sizeof(struct OpenBIOS_nvpart_v1);
-    for (i = 0; i < nb_prom_envs; i++)
-        end = OpenBIOS_set_var(image, end, prom_envs[i]);
-
-    // End marker
-    image[end++] = '\0';
-
-    end = start + ((end - start + 15) & ~15);
-    OpenBIOS_finish_partition(part_header, end - start);
-
-    // free partition
-    start = end;
-    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
-    part_header->signature = OPENBIOS_PART_FREE;
-    pstrcpy(part_header->name, sizeof(part_header->name), "free");
-
-    end = 0x1fd0;
-    OpenBIOS_finish_partition(part_header, end - start);
-
-    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr,
-                    nvram_machine_id);
-
-    for (i = 0; i < sizeof(image); i++)
-        m48t59_write(nvram, i, image[i]);
-}
-
-static DeviceState *slavio_intctl;
-
-void sun4m_pic_info(Monitor *mon, const QDict *qdict)
-{
-    if (slavio_intctl)
-        slavio_pic_info(mon, slavio_intctl);
-}
-
-void sun4m_irq_info(Monitor *mon, const QDict *qdict)
-{
-    if (slavio_intctl)
-        slavio_irq_info(mon, slavio_intctl);
-}
-
-void cpu_check_irqs(CPUSPARCState *env)
-{
-    if (env->pil_in && (env->interrupt_index == 0 ||
-                        (env->interrupt_index & ~15) == TT_EXTINT)) {
-        unsigned int i;
-
-        for (i = 15; i > 0; i--) {
-            if (env->pil_in & (1 << i)) {
-                int old_interrupt = env->interrupt_index;
-
-                env->interrupt_index = TT_EXTINT | i;
-                if (old_interrupt != env->interrupt_index) {
-                    trace_sun4m_cpu_interrupt(i);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
-                }
-                break;
-            }
-        }
-    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
-        trace_sun4m_cpu_reset_interrupt(env->interrupt_index & 15);
-        env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-static void cpu_kick_irq(SPARCCPU *cpu)
-{
-    CPUSPARCState *env = &cpu->env;
-
-    env->halted = 0;
-    cpu_check_irqs(env);
-    qemu_cpu_kick(CPU(cpu));
-}
-
-static void cpu_set_irq(void *opaque, int irq, int level)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    if (level) {
-        trace_sun4m_cpu_set_irq_raise(irq);
-        env->pil_in |= 1 << irq;
-        cpu_kick_irq(cpu);
-    } else {
-        trace_sun4m_cpu_set_irq_lower(irq);
-        env->pil_in &= ~(1 << irq);
-        cpu_check_irqs(env);
-    }
-}
-
-static void dummy_cpu_set_irq(void *opaque, int irq, int level)
-{
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-    env->halted = 0;
-}
-
-static void secondary_cpu_reset(void *opaque)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-    env->halted = 1;
-}
-
-static void cpu_halt_signal(void *opaque, int irq, int level)
-{
-    if (level && cpu_single_env)
-        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return addr - 0xf0000000ULL;
-}
-
-static unsigned long sun4m_load_kernel(const char *kernel_filename,
-                                       const char *initrd_filename,
-                                       ram_addr_t RAM_size)
-{
-    int linux_boot;
-    unsigned int i;
-    long initrd_size, kernel_size;
-    uint8_t *ptr;
-
-    linux_boot = (kernel_filename != NULL);
-
-    kernel_size = 0;
-    if (linux_boot) {
-        int bswap_needed;
-
-#ifdef BSWAP_NEEDED
-        bswap_needed = 1;
-#else
-        bswap_needed = 0;
-#endif
-        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
-                               NULL, NULL, NULL, 1, ELF_MACHINE, 0);
-        if (kernel_size < 0)
-            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
-                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
-                                    TARGET_PAGE_SIZE);
-        if (kernel_size < 0)
-            kernel_size = load_image_targphys(kernel_filename,
-                                              KERNEL_LOAD_ADDR,
-                                              RAM_size - KERNEL_LOAD_ADDR);
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-
-        /* load initrd */
-        initrd_size = 0;
-        if (initrd_filename) {
-            initrd_size = load_image_targphys(initrd_filename,
-                                              INITRD_LOAD_ADDR,
-                                              RAM_size - INITRD_LOAD_ADDR);
-            if (initrd_size < 0) {
-                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                        initrd_filename);
-                exit(1);
-            }
-        }
-        if (initrd_size > 0) {
-            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
-                ptr = rom_ptr(KERNEL_LOAD_ADDR + i);
-                if (ldl_p(ptr) == 0x48647253) { // HdrS
-                    stl_p(ptr + 16, INITRD_LOAD_ADDR);
-                    stl_p(ptr + 20, initrd_size);
-                    break;
-                }
-            }
-        }
-    }
-    return kernel_size;
-}
-
-static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "iommu");
-    qdev_prop_set_uint32(dev, "version", version);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, irq);
-    sysbus_mmio_map(s, 0, addr);
-
-    return s;
-}
-
-static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq,
-                              void *iommu, qemu_irq *dev_irq, int is_ledma)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "sparc32_dma");
-    qdev_prop_set_ptr(dev, "iommu_opaque", iommu);
-    qdev_prop_set_uint32(dev, "is_ledma", is_ledma);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, parent_irq);
-    *dev_irq = qdev_get_gpio_in(dev, 0);
-    sysbus_mmio_map(s, 0, daddr);
-
-    return s;
-}
-
-static void lance_init(NICInfo *nd, hwaddr leaddr,
-                       void *dma_opaque, qemu_irq irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    qemu_irq reset;
-
-    qemu_check_nic_model(&nd_table[0], "lance");
-
-    dev = qdev_create(NULL, "lance");
-    qdev_set_nic_properties(dev, nd);
-    qdev_prop_set_ptr(dev, "dma", dma_opaque);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(s, 0, leaddr);
-    sysbus_connect_irq(s, 0, irq);
-    reset = qdev_get_gpio_in(dev, 0);
-    qdev_connect_gpio_out(dma_opaque, 0, reset);
-}
-
-static DeviceState *slavio_intctl_init(hwaddr addr,
-                                       hwaddr addrg,
-                                       qemu_irq **parent_irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    unsigned int i, j;
-
-    dev = qdev_create(NULL, "slavio_intctl");
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-
-    for (i = 0; i < MAX_CPUS; i++) {
-        for (j = 0; j < MAX_PILS; j++) {
-            sysbus_connect_irq(s, i * MAX_PILS + j, parent_irq[i][j]);
-        }
-    }
-    sysbus_mmio_map(s, 0, addrg);
-    for (i = 0; i < MAX_CPUS; i++) {
-        sysbus_mmio_map(s, i + 1, addr + i * TARGET_PAGE_SIZE);
-    }
-
-    return dev;
-}
-
-#define SYS_TIMER_OFFSET      0x10000ULL
-#define CPU_TIMER_OFFSET(cpu) (0x1000ULL * cpu)
-
-static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq,
-                                  qemu_irq *cpu_irqs, unsigned int num_cpus)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    unsigned int i;
-
-    dev = qdev_create(NULL, "slavio_timer");
-    qdev_prop_set_uint32(dev, "num_cpus", num_cpus);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, master_irq);
-    sysbus_mmio_map(s, 0, addr + SYS_TIMER_OFFSET);
-
-    for (i = 0; i < MAX_CPUS; i++) {
-        sysbus_mmio_map(s, i + 1, addr + (hwaddr)CPU_TIMER_OFFSET(i));
-        sysbus_connect_irq(s, i + 1, cpu_irqs[i]);
-    }
-}
-
-static qemu_irq  slavio_system_powerdown;
-
-static void slavio_powerdown_req(Notifier *n, void *opaque)
-{
-    qemu_irq_raise(slavio_system_powerdown);
-}
-
-static Notifier slavio_system_powerdown_notifier = {
-    .notify = slavio_powerdown_req
-};
-
-#define MISC_LEDS 0x01600000
-#define MISC_CFG  0x01800000
-#define MISC_DIAG 0x01a00000
-#define MISC_MDM  0x01b00000
-#define MISC_SYS  0x01f00000
-
-static void slavio_misc_init(hwaddr base,
-                             hwaddr aux1_base,
-                             hwaddr aux2_base, qemu_irq irq,
-                             qemu_irq fdc_tc)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "slavio_misc");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    if (base) {
-        /* 8 bit registers */
-        /* Slavio control */
-        sysbus_mmio_map(s, 0, base + MISC_CFG);
-        /* Diagnostics */
-        sysbus_mmio_map(s, 1, base + MISC_DIAG);
-        /* Modem control */
-        sysbus_mmio_map(s, 2, base + MISC_MDM);
-        /* 16 bit registers */
-        /* ss600mp diag LEDs */
-        sysbus_mmio_map(s, 3, base + MISC_LEDS);
-        /* 32 bit registers */
-        /* System control */
-        sysbus_mmio_map(s, 4, base + MISC_SYS);
-    }
-    if (aux1_base) {
-        /* AUX 1 (Misc System Functions) */
-        sysbus_mmio_map(s, 5, aux1_base);
-    }
-    if (aux2_base) {
-        /* AUX 2 (Software Powerdown Control) */
-        sysbus_mmio_map(s, 6, aux2_base);
-    }
-    sysbus_connect_irq(s, 0, irq);
-    sysbus_connect_irq(s, 1, fdc_tc);
-    slavio_system_powerdown = qdev_get_gpio_in(dev, 0);
-    qemu_register_powerdown_notifier(&slavio_system_powerdown_notifier);
-}
-
-static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "eccmemctl");
-    qdev_prop_set_uint32(dev, "version", version);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, irq);
-    sysbus_mmio_map(s, 0, base);
-    if (version == 0) { // SS-600MP only
-        sysbus_mmio_map(s, 1, base + 0x1000);
-    }
-}
-
-static void apc_init(hwaddr power_base, qemu_irq cpu_halt)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "apc");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    /* Power management (APC) XXX: not a Slavio device */
-    sysbus_mmio_map(s, 0, power_base);
-    sysbus_connect_irq(s, 0, cpu_halt);
-}
-
-static void tcx_init(hwaddr addr, int vram_size, int width,
-                     int height, int depth)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "SUNW,tcx");
-    qdev_prop_set_taddr(dev, "addr", addr);
-    qdev_prop_set_uint32(dev, "vram_size", vram_size);
-    qdev_prop_set_uint16(dev, "width", width);
-    qdev_prop_set_uint16(dev, "height", height);
-    qdev_prop_set_uint16(dev, "depth", depth);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    /* 8-bit plane */
-    sysbus_mmio_map(s, 0, addr + 0x00800000ULL);
-    /* DAC */
-    sysbus_mmio_map(s, 1, addr + 0x00200000ULL);
-    /* TEC (dummy) */
-    sysbus_mmio_map(s, 2, addr + 0x00700000ULL);
-    /* THC 24 bit: NetBSD writes here even with 8-bit display: dummy */
-    sysbus_mmio_map(s, 3, addr + 0x00301000ULL);
-    if (depth == 24) {
-        /* 24-bit plane */
-        sysbus_mmio_map(s, 4, addr + 0x02000000ULL);
-        /* Control plane */
-        sysbus_mmio_map(s, 5, addr + 0x0a000000ULL);
-    } else {
-        /* THC 8 bit (dummy) */
-        sysbus_mmio_map(s, 4, addr + 0x00300000ULL);
-    }
-}
-
-/* NCR89C100/MACIO Internal ID register */
-static const uint8_t idreg_data[] = { 0xfe, 0x81, 0x01, 0x03 };
-
-static void idreg_init(hwaddr addr)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "macio_idreg");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-    cpu_physical_memory_write_rom(addr, idreg_data, sizeof(idreg_data));
-}
-
-typedef struct IDRegState {
-    SysBusDevice busdev;
-    MemoryRegion mem;
-} IDRegState;
-
-static int idreg_init1(SysBusDevice *dev)
-{
-    IDRegState *s = FROM_SYSBUS(IDRegState, dev);
-
-    memory_region_init_ram(&s->mem, "sun4m.idreg", sizeof(idreg_data));
-    vmstate_register_ram_global(&s->mem);
-    memory_region_set_readonly(&s->mem, true);
-    sysbus_init_mmio(dev, &s->mem);
-    return 0;
-}
-
-static void idreg_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = idreg_init1;
-}
-
-static const TypeInfo idreg_info = {
-    .name          = "macio_idreg",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(IDRegState),
-    .class_init    = idreg_class_init,
-};
-
-typedef struct AFXState {
-    SysBusDevice busdev;
-    MemoryRegion mem;
-} AFXState;
-
-/* SS-5 TCX AFX register */
-static void afx_init(hwaddr addr)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "tcx_afx");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-}
-
-static int afx_init1(SysBusDevice *dev)
-{
-    AFXState *s = FROM_SYSBUS(AFXState, dev);
-
-    memory_region_init_ram(&s->mem, "sun4m.afx", 4);
-    vmstate_register_ram_global(&s->mem);
-    sysbus_init_mmio(dev, &s->mem);
-    return 0;
-}
-
-static void afx_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = afx_init1;
-}
-
-static const TypeInfo afx_info = {
-    .name          = "tcx_afx",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(AFXState),
-    .class_init    = afx_class_init,
-};
-
-typedef struct PROMState {
-    SysBusDevice busdev;
-    MemoryRegion prom;
-} PROMState;
-
-/* Boot PROM (OpenBIOS) */
-static uint64_t translate_prom_address(void *opaque, uint64_t addr)
-{
-    hwaddr *base_addr = (hwaddr *)opaque;
-    return addr + *base_addr - PROM_VADDR;
-}
-
-static void prom_init(hwaddr addr, const char *bios_name)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    char *filename;
-    int ret;
-
-    dev = qdev_create(NULL, "openprom");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-
-    /* load boot prom */
-    if (bios_name == NULL) {
-        bios_name = PROM_FILENAME;
-    }
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (filename) {
-        ret = load_elf(filename, translate_prom_address, &addr, NULL,
-                       NULL, NULL, 1, ELF_MACHINE, 0);
-        if (ret < 0 || ret > PROM_SIZE_MAX) {
-            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
-        }
-        g_free(filename);
-    } else {
-        ret = -1;
-    }
-    if (ret < 0 || ret > PROM_SIZE_MAX) {
-        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
-        exit(1);
-    }
-}
-
-static int prom_init1(SysBusDevice *dev)
-{
-    PROMState *s = FROM_SYSBUS(PROMState, dev);
-
-    memory_region_init_ram(&s->prom, "sun4m.prom", PROM_SIZE_MAX);
-    vmstate_register_ram_global(&s->prom);
-    memory_region_set_readonly(&s->prom, true);
-    sysbus_init_mmio(dev, &s->prom);
-    return 0;
-}
-
-static Property prom_properties[] = {
-    {/* end of property list */},
-};
-
-static void prom_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = prom_init1;
-    dc->props = prom_properties;
-}
-
-static const TypeInfo prom_info = {
-    .name          = "openprom",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PROMState),
-    .class_init    = prom_class_init,
-};
-
-typedef struct RamDevice
-{
-    SysBusDevice busdev;
-    MemoryRegion ram;
-    uint64_t size;
-} RamDevice;
-
-/* System RAM */
-static int ram_init1(SysBusDevice *dev)
-{
-    RamDevice *d = FROM_SYSBUS(RamDevice, dev);
-
-    memory_region_init_ram(&d->ram, "sun4m.ram", d->size);
-    vmstate_register_ram_global(&d->ram);
-    sysbus_init_mmio(dev, &d->ram);
-    return 0;
-}
-
-static void ram_init(hwaddr addr, ram_addr_t RAM_size,
-                     uint64_t max_mem)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    RamDevice *d;
-
-    /* allocate RAM */
-    if ((uint64_t)RAM_size > max_mem) {
-        fprintf(stderr,
-                "qemu: Too much memory for this machine: %d, maximum %d\n",
-                (unsigned int)(RAM_size / (1024 * 1024)),
-                (unsigned int)(max_mem / (1024 * 1024)));
-        exit(1);
-    }
-    dev = qdev_create(NULL, "memory");
-    s = SYS_BUS_DEVICE(dev);
-
-    d = FROM_SYSBUS(RamDevice, s);
-    d->size = RAM_size;
-    qdev_init_nofail(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-}
-
-static Property ram_properties[] = {
-    DEFINE_PROP_UINT64("size", RamDevice, size, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void ram_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = ram_init1;
-    dc->props = ram_properties;
-}
-
-static const TypeInfo ram_info = {
-    .name          = "memory",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(RamDevice),
-    .class_init    = ram_class_init,
-};
-
-static void cpu_devinit(const char *cpu_model, unsigned int id,
-                        uint64_t prom_addr, qemu_irq **cpu_irqs)
-{
-    SPARCCPU *cpu;
-    CPUSPARCState *env;
-
-    cpu = cpu_sparc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    cpu_sparc_set_id(env, id);
-    if (id == 0) {
-        qemu_register_reset(main_cpu_reset, cpu);
-    } else {
-        qemu_register_reset(secondary_cpu_reset, cpu);
-        env->halted = 1;
-    }
-    *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
-    env->prom_addr = prom_addr;
-}
-
-static void dummy_fdc_tc(void *opaque, int irq, int level)
-{
-}
-
-static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, 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)
-{
-    unsigned int i;
-    void *iommu, *espdma, *ledma, *nvram;
-    qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
-        espdma_irq, ledma_irq;
-    qemu_irq esp_reset, dma_enable;
-    qemu_irq fdc_tc;
-    qemu_irq *cpu_halt;
-    unsigned long kernel_size;
-    DriveInfo *fd[MAX_FD];
-    void *fw_cfg;
-    unsigned int num_vsimms;
-
-    /* init CPUs */
-    if (!cpu_model)
-        cpu_model = hwdef->default_cpu_model;
-
-    for(i = 0; i < smp_cpus; i++) {
-        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
-    }
-
-    for (i = smp_cpus; i < MAX_CPUS; i++)
-        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
-
-
-    /* set up devices */
-    ram_init(0, RAM_size, hwdef->max_mem);
-    /* models without ECC don't trap when missing ram is accessed */
-    if (!hwdef->ecc_base) {
-        empty_slot_init(RAM_size, hwdef->max_mem - RAM_size);
-    }
-
-    prom_init(hwdef->slavio_base, bios_name);
-
-    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
-                                       hwdef->intctl_base + 0x10000ULL,
-                                       cpu_irqs);
-
-    for (i = 0; i < 32; i++) {
-        slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i);
-    }
-    for (i = 0; i < MAX_CPUS; i++) {
-        slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i);
-    }
-
-    if (hwdef->idreg_base) {
-        idreg_init(hwdef->idreg_base);
-    }
-
-    if (hwdef->afx_base) {
-        afx_init(hwdef->afx_base);
-    }
-
-    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
-                       slavio_irq[30]);
-
-    if (hwdef->iommu_pad_base) {
-        /* On the real hardware (SS-5, LX) the MMU is not padded, but aliased.
-           Software shouldn't use aliased addresses, neither should it crash
-           when does. Using empty_slot instead of aliasing can help with
-           debugging such accesses */
-        empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len);
-    }
-
-    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[18],
-                              iommu, &espdma_irq, 0);
-
-    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
-                             slavio_irq[16], iommu, &ledma_irq, 1);
-
-    if (graphic_depth != 8 && graphic_depth != 24) {
-        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
-        exit (1);
-    }
-    num_vsimms = 0;
-    if (num_vsimms == 0) {
-        tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
-                 graphic_depth);
-    }
-
-    for (i = num_vsimms; i < MAX_VSIMMS; i++) {
-        /* vsimm registers probed by OBP */
-        if (hwdef->vsimm[i].reg_base) {
-            empty_slot_init(hwdef->vsimm[i].reg_base, 0x2000);
-        }
-    }
-
-    if (hwdef->sx_base) {
-        empty_slot_init(hwdef->sx_base, 0x2000);
-    }
-
-    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
-
-    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 8);
-
-    slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus);
-
-    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
-                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
-    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
-       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
-    escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
-              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
-
-    cpu_halt = qemu_allocate_irqs(cpu_halt_signal, NULL, 1);
-    if (hwdef->apc_base) {
-        apc_init(hwdef->apc_base, cpu_halt[0]);
-    }
-
-    if (hwdef->fd_base) {
-        /* there is zero or one floppy drive */
-        memset(fd, 0, sizeof(fd));
-        fd[0] = drive_get(IF_FLOPPY, 0, 0);
-        sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd,
-                          &fdc_tc);
-    } else {
-        fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1);
-    }
-
-    slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base,
-                     slavio_irq[30], fdc_tc);
-
-    if (drive_get_max_bus(IF_SCSI) > 0) {
-        fprintf(stderr, "qemu: too many SCSI bus\n");
-        exit(1);
-    }
-
-    esp_init(hwdef->esp_base, 2,
-             espdma_memory_read, espdma_memory_write,
-             espdma, espdma_irq, &esp_reset, &dma_enable);
-
-    qdev_connect_gpio_out(espdma, 0, esp_reset);
-    qdev_connect_gpio_out(espdma, 1, dma_enable);
-
-    if (hwdef->cs_base) {
-        sysbus_create_simple("SUNW,CS4231", hwdef->cs_base,
-                             slavio_irq[5]);
-    }
-
-    if (hwdef->dbri_base) {
-        /* ISDN chip with attached CS4215 audio codec */
-        /* prom space */
-        empty_slot_init(hwdef->dbri_base+0x1000, 0x30);
-        /* reg space */
-        empty_slot_init(hwdef->dbri_base+0x10000, 0x100);
-    }
-
-    if (hwdef->bpp_base) {
-        /* parallel port */
-        empty_slot_init(hwdef->bpp_base, 0x20);
-    }
-
-    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
-                                    RAM_size);
-
-    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
-               boot_device, RAM_size, kernel_size, graphic_width,
-               graphic_height, graphic_depth, hwdef->nvram_machine_id,
-               "Sun4m");
-
-    if (hwdef->ecc_base)
-        ecc_init(hwdef->ecc_base, slavio_irq[28],
-                 hwdef->ecc_version);
-
-    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-    if (kernel_cmdline) {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
-        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
-        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
-        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
-                       strlen(kernel_cmdline) + 1);
-    } else {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
-        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
-    }
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
-    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
-}
-
-enum {
-    ss2_id = 0,
-    ss5_id = 32,
-    vger_id,
-    lx_id,
-    ss4_id,
-    scls_id,
-    sbook_id,
-    ss10_id = 64,
-    ss20_id,
-    ss600mp_id,
-    ss1000_id = 96,
-    ss2000_id,
-};
-
-static const struct sun4m_hwdef sun4m_hwdefs[] = {
-    /* SS-5 */
-    {
-        .iommu_base   = 0x10000000,
-        .iommu_pad_base = 0x10004000,
-        .iommu_pad_len  = 0x0fffb000,
-        .tcx_base     = 0x50000000,
-        .cs_base      = 0x6c000000,
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .apc_base     = 0x6a000000,
-        .afx_base     = 0x6e000000,
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = ss5_id,
-        .iommu_version = 0x05000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "Fujitsu MB86904",
-    },
-    /* SS-10 */
-    {
-        .iommu_base   = 0xfe0000000ULL,
-        .tcx_base     = 0xe20000000ULL,
-        .slavio_base  = 0xff0000000ULL,
-        .ms_kb_base   = 0xff1000000ULL,
-        .serial_base  = 0xff1100000ULL,
-        .nvram_base   = 0xff1200000ULL,
-        .fd_base      = 0xff1700000ULL,
-        .counter_base = 0xff1300000ULL,
-        .intctl_base  = 0xff1400000ULL,
-        .idreg_base   = 0xef0000000ULL,
-        .dma_base     = 0xef0400000ULL,
-        .esp_base     = 0xef0800000ULL,
-        .le_base      = 0xef0c00000ULL,
-        .apc_base     = 0xefa000000ULL, // XXX should not exist
-        .aux1_base    = 0xff1800000ULL,
-        .aux2_base    = 0xff1a01000ULL,
-        .ecc_base     = 0xf00000000ULL,
-        .ecc_version  = 0x10000000, // version 0, implementation 1
-        .nvram_machine_id = 0x72,
-        .machine_id = ss10_id,
-        .iommu_version = 0x03000000,
-        .max_mem = 0xf00000000ULL,
-        .default_cpu_model = "TI SuperSparc II",
-    },
-    /* SS-600MP */
-    {
-        .iommu_base   = 0xfe0000000ULL,
-        .tcx_base     = 0xe20000000ULL,
-        .slavio_base  = 0xff0000000ULL,
-        .ms_kb_base   = 0xff1000000ULL,
-        .serial_base  = 0xff1100000ULL,
-        .nvram_base   = 0xff1200000ULL,
-        .counter_base = 0xff1300000ULL,
-        .intctl_base  = 0xff1400000ULL,
-        .dma_base     = 0xef0081000ULL,
-        .esp_base     = 0xef0080000ULL,
-        .le_base      = 0xef0060000ULL,
-        .apc_base     = 0xefa000000ULL, // XXX should not exist
-        .aux1_base    = 0xff1800000ULL,
-        .aux2_base    = 0xff1a01000ULL, // XXX should not exist
-        .ecc_base     = 0xf00000000ULL,
-        .ecc_version  = 0x00000000, // version 0, implementation 0
-        .nvram_machine_id = 0x71,
-        .machine_id = ss600mp_id,
-        .iommu_version = 0x01000000,
-        .max_mem = 0xf00000000ULL,
-        .default_cpu_model = "TI SuperSparc II",
-    },
-    /* SS-20 */
-    {
-        .iommu_base   = 0xfe0000000ULL,
-        .tcx_base     = 0xe20000000ULL,
-        .slavio_base  = 0xff0000000ULL,
-        .ms_kb_base   = 0xff1000000ULL,
-        .serial_base  = 0xff1100000ULL,
-        .nvram_base   = 0xff1200000ULL,
-        .fd_base      = 0xff1700000ULL,
-        .counter_base = 0xff1300000ULL,
-        .intctl_base  = 0xff1400000ULL,
-        .idreg_base   = 0xef0000000ULL,
-        .dma_base     = 0xef0400000ULL,
-        .esp_base     = 0xef0800000ULL,
-        .le_base      = 0xef0c00000ULL,
-        .bpp_base     = 0xef4800000ULL,
-        .apc_base     = 0xefa000000ULL, // XXX should not exist
-        .aux1_base    = 0xff1800000ULL,
-        .aux2_base    = 0xff1a01000ULL,
-        .dbri_base    = 0xee0000000ULL,
-        .sx_base      = 0xf80000000ULL,
-        .vsimm        = {
-            {
-                .reg_base  = 0x9c000000ULL,
-                .vram_base = 0xfc000000ULL
-            }, {
-                .reg_base  = 0x90000000ULL,
-                .vram_base = 0xf0000000ULL
-            }, {
-                .reg_base  = 0x94000000ULL
-            }, {
-                .reg_base  = 0x98000000ULL
-            }
-        },
-        .ecc_base     = 0xf00000000ULL,
-        .ecc_version  = 0x20000000, // version 0, implementation 2
-        .nvram_machine_id = 0x72,
-        .machine_id = ss20_id,
-        .iommu_version = 0x13000000,
-        .max_mem = 0xf00000000ULL,
-        .default_cpu_model = "TI SuperSparc II",
-    },
-    /* Voyager */
-    {
-        .iommu_base   = 0x10000000,
-        .tcx_base     = 0x50000000,
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .apc_base     = 0x71300000, // pmc
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = vger_id,
-        .iommu_version = 0x05000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "Fujitsu MB86904",
-    },
-    /* LX */
-    {
-        .iommu_base   = 0x10000000,
-        .iommu_pad_base = 0x10004000,
-        .iommu_pad_len  = 0x0fffb000,
-        .tcx_base     = 0x50000000,
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = lx_id,
-        .iommu_version = 0x04000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "TI MicroSparc I",
-    },
-    /* SS-4 */
-    {
-        .iommu_base   = 0x10000000,
-        .tcx_base     = 0x50000000,
-        .cs_base      = 0x6c000000,
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .apc_base     = 0x6a000000,
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = ss4_id,
-        .iommu_version = 0x05000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "Fujitsu MB86904",
-    },
-    /* SPARCClassic */
-    {
-        .iommu_base   = 0x10000000,
-        .tcx_base     = 0x50000000,
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .apc_base     = 0x6a000000,
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = scls_id,
-        .iommu_version = 0x05000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "TI MicroSparc I",
-    },
-    /* SPARCbook */
-    {
-        .iommu_base   = 0x10000000,
-        .tcx_base     = 0x50000000, // XXX
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .apc_base     = 0x6a000000,
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = sbook_id,
-        .iommu_version = 0x05000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "TI MicroSparc I",
-    },
-};
-
-/* SPARCstation 5 hardware initialisation */
-static void ss5_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[0], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCstation 10 hardware initialisation */
-static void ss10_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[1], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCserver 600MP hardware initialisation */
-static void ss600mp_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[2], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCstation 20 hardware initialisation */
-static void ss20_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[3], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCstation Voyager hardware initialisation */
-static void vger_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[4], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCstation LX hardware initialisation */
-static void ss_lx_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[5], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCstation 4 hardware initialisation */
-static void ss4_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[6], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCClassic hardware initialisation */
-static void scls_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[7], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCbook hardware initialisation */
-static void sbook_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[8], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-static QEMUMachine ss5_machine = {
-    .name = "SS-5",
-    .desc = "Sun4m platform, SPARCstation 5",
-    .init = ss5_init,
-    .block_default_type = IF_SCSI,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss10_machine = {
-    .name = "SS-10",
-    .desc = "Sun4m platform, SPARCstation 10",
-    .init = ss10_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss600mp_machine = {
-    .name = "SS-600MP",
-    .desc = "Sun4m platform, SPARCserver 600MP",
-    .init = ss600mp_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss20_machine = {
-    .name = "SS-20",
-    .desc = "Sun4m platform, SPARCstation 20",
-    .init = ss20_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine voyager_machine = {
-    .name = "Voyager",
-    .desc = "Sun4m platform, SPARCstation Voyager",
-    .init = vger_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss_lx_machine = {
-    .name = "LX",
-    .desc = "Sun4m platform, SPARCstation LX",
-    .init = ss_lx_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss4_machine = {
-    .name = "SS-4",
-    .desc = "Sun4m platform, SPARCstation 4",
-    .init = ss4_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine scls_machine = {
-    .name = "SPARCClassic",
-    .desc = "Sun4m platform, SPARCClassic",
-    .init = scls_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine sbook_machine = {
-    .name = "SPARCbook",
-    .desc = "Sun4m platform, SPARCbook",
-    .init = sbook_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static const struct sun4d_hwdef sun4d_hwdefs[] = {
-    /* SS-1000 */
-    {
-        .iounit_bases   = {
-            0xfe0200000ULL,
-            0xfe1200000ULL,
-            0xfe2200000ULL,
-            0xfe3200000ULL,
-            -1,
-        },
-        .tcx_base     = 0x820000000ULL,
-        .slavio_base  = 0xf00000000ULL,
-        .ms_kb_base   = 0xf00240000ULL,
-        .serial_base  = 0xf00200000ULL,
-        .nvram_base   = 0xf00280000ULL,
-        .counter_base = 0xf00300000ULL,
-        .espdma_base  = 0x800081000ULL,
-        .esp_base     = 0x800080000ULL,
-        .ledma_base   = 0x800040000ULL,
-        .le_base      = 0x800060000ULL,
-        .sbi_base     = 0xf02800000ULL,
-        .nvram_machine_id = 0x80,
-        .machine_id = ss1000_id,
-        .iounit_version = 0x03000000,
-        .max_mem = 0xf00000000ULL,
-        .default_cpu_model = "TI SuperSparc II",
-    },
-    /* SS-2000 */
-    {
-        .iounit_bases   = {
-            0xfe0200000ULL,
-            0xfe1200000ULL,
-            0xfe2200000ULL,
-            0xfe3200000ULL,
-            0xfe4200000ULL,
-        },
-        .tcx_base     = 0x820000000ULL,
-        .slavio_base  = 0xf00000000ULL,
-        .ms_kb_base   = 0xf00240000ULL,
-        .serial_base  = 0xf00200000ULL,
-        .nvram_base   = 0xf00280000ULL,
-        .counter_base = 0xf00300000ULL,
-        .espdma_base  = 0x800081000ULL,
-        .esp_base     = 0x800080000ULL,
-        .ledma_base   = 0x800040000ULL,
-        .le_base      = 0x800060000ULL,
-        .sbi_base     = 0xf02800000ULL,
-        .nvram_machine_id = 0x80,
-        .machine_id = ss2000_id,
-        .iounit_version = 0x03000000,
-        .max_mem = 0xf00000000ULL,
-        .default_cpu_model = "TI SuperSparc II",
-    },
-};
-
-static DeviceState *sbi_init(hwaddr addr, qemu_irq **parent_irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    unsigned int i;
-
-    dev = qdev_create(NULL, "sbi");
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-
-    for (i = 0; i < MAX_CPUS; i++) {
-        sysbus_connect_irq(s, i, *parent_irq[i]);
-    }
-
-    sysbus_mmio_map(s, 0, addr);
-
-    return dev;
-}
-
-static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, 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)
-{
-    unsigned int i;
-    void *iounits[MAX_IOUNITS], *espdma, *ledma, *nvram;
-    qemu_irq *cpu_irqs[MAX_CPUS], sbi_irq[32], sbi_cpu_irq[MAX_CPUS],
-        espdma_irq, ledma_irq;
-    qemu_irq esp_reset, dma_enable;
-    unsigned long kernel_size;
-    void *fw_cfg;
-    DeviceState *dev;
-
-    /* init CPUs */
-    if (!cpu_model)
-        cpu_model = hwdef->default_cpu_model;
-
-    for(i = 0; i < smp_cpus; i++) {
-        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
-    }
-
-    for (i = smp_cpus; i < MAX_CPUS; i++)
-        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
-
-    /* set up devices */
-    ram_init(0, RAM_size, hwdef->max_mem);
-
-    prom_init(hwdef->slavio_base, bios_name);
-
-    dev = sbi_init(hwdef->sbi_base, cpu_irqs);
-
-    for (i = 0; i < 32; i++) {
-        sbi_irq[i] = qdev_get_gpio_in(dev, i);
-    }
-    for (i = 0; i < MAX_CPUS; i++) {
-        sbi_cpu_irq[i] = qdev_get_gpio_in(dev, 32 + i);
-    }
-
-    for (i = 0; i < MAX_IOUNITS; i++)
-        if (hwdef->iounit_bases[i] != (hwaddr)-1)
-            iounits[i] = iommu_init(hwdef->iounit_bases[i],
-                                    hwdef->iounit_version,
-                                    sbi_irq[0]);
-
-    espdma = sparc32_dma_init(hwdef->espdma_base, sbi_irq[3],
-                              iounits[0], &espdma_irq, 0);
-
-    /* should be lebuffer instead */
-    ledma = sparc32_dma_init(hwdef->ledma_base, sbi_irq[4],
-                             iounits[0], &ledma_irq, 0);
-
-    if (graphic_depth != 8 && graphic_depth != 24) {
-        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
-        exit (1);
-    }
-    tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
-             graphic_depth);
-
-    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
-
-    nvram = m48t59_init(sbi_irq[0], hwdef->nvram_base, 0, 0x2000, 8);
-
-    slavio_timer_init_all(hwdef->counter_base, sbi_irq[10], sbi_cpu_irq, smp_cpus);
-
-    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, sbi_irq[12],
-                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
-    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
-       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
-    escc_init(hwdef->serial_base, sbi_irq[12], sbi_irq[12],
-              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
-
-    if (drive_get_max_bus(IF_SCSI) > 0) {
-        fprintf(stderr, "qemu: too many SCSI bus\n");
-        exit(1);
-    }
-
-    esp_init(hwdef->esp_base, 2,
-             espdma_memory_read, espdma_memory_write,
-             espdma, espdma_irq, &esp_reset, &dma_enable);
-
-    qdev_connect_gpio_out(espdma, 0, esp_reset);
-    qdev_connect_gpio_out(espdma, 1, dma_enable);
-
-    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
-                                    RAM_size);
-
-    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
-               boot_device, RAM_size, kernel_size, graphic_width,
-               graphic_height, graphic_depth, hwdef->nvram_machine_id,
-               "Sun4d");
-
-    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-    if (kernel_cmdline) {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
-        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
-        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
-    } else {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
-    }
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
-    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
-}
-
-/* SPARCserver 1000 hardware initialisation */
-static void ss1000_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4d_hw_init(&sun4d_hwdefs[0], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCcenter 2000 hardware initialisation */
-static void ss2000_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4d_hw_init(&sun4d_hwdefs[1], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-static QEMUMachine ss1000_machine = {
-    .name = "SS-1000",
-    .desc = "Sun4d platform, SPARCserver 1000",
-    .init = ss1000_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 8,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss2000_machine = {
-    .name = "SS-2000",
-    .desc = "Sun4d platform, SPARCcenter 2000",
-    .init = ss2000_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 20,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static const struct sun4c_hwdef sun4c_hwdefs[] = {
-    /* SS-2 */
-    {
-        .iommu_base   = 0xf8000000,
-        .tcx_base     = 0xfe000000,
-        .slavio_base  = 0xf6000000,
-        .intctl_base  = 0xf5000000,
-        .counter_base = 0xf3000000,
-        .ms_kb_base   = 0xf0000000,
-        .serial_base  = 0xf1000000,
-        .nvram_base   = 0xf2000000,
-        .fd_base      = 0xf7200000,
-        .dma_base     = 0xf8400000,
-        .esp_base     = 0xf8800000,
-        .le_base      = 0xf8c00000,
-        .aux1_base    = 0xf7400003,
-        .nvram_machine_id = 0x55,
-        .machine_id = ss2_id,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "Cypress CY7C601",
-    },
-};
-
-static DeviceState *sun4c_intctl_init(hwaddr addr,
-                                      qemu_irq *parent_irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    unsigned int i;
-
-    dev = qdev_create(NULL, "sun4c_intctl");
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-
-    for (i = 0; i < MAX_PILS; i++) {
-        sysbus_connect_irq(s, i, parent_irq[i]);
-    }
-    sysbus_mmio_map(s, 0, addr);
-
-    return dev;
-}
-
-static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, 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)
-{
-    void *iommu, *espdma, *ledma, *nvram;
-    qemu_irq *cpu_irqs, slavio_irq[8], espdma_irq, ledma_irq;
-    qemu_irq esp_reset, dma_enable;
-    qemu_irq fdc_tc;
-    unsigned long kernel_size;
-    DriveInfo *fd[MAX_FD];
-    void *fw_cfg;
-    DeviceState *dev;
-    unsigned int i;
-
-    /* init CPU */
-    if (!cpu_model)
-        cpu_model = hwdef->default_cpu_model;
-
-    cpu_devinit(cpu_model, 0, hwdef->slavio_base, &cpu_irqs);
-
-    /* set up devices */
-    ram_init(0, RAM_size, hwdef->max_mem);
-
-    prom_init(hwdef->slavio_base, bios_name);
-
-    dev = sun4c_intctl_init(hwdef->intctl_base, cpu_irqs);
-
-    for (i = 0; i < 8; i++) {
-        slavio_irq[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
-                       slavio_irq[1]);
-
-    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[2],
-                              iommu, &espdma_irq, 0);
-
-    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
-                             slavio_irq[3], iommu, &ledma_irq, 1);
-
-    if (graphic_depth != 8 && graphic_depth != 24) {
-        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
-        exit (1);
-    }
-    tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
-             graphic_depth);
-
-    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
-
-    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x800, 2);
-
-    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[1],
-                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
-    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
-       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
-    escc_init(hwdef->serial_base, slavio_irq[1],
-              slavio_irq[1], serial_hds[0], serial_hds[1],
-              ESCC_CLOCK, 1);
-
-    if (hwdef->fd_base != (hwaddr)-1) {
-        /* there is zero or one floppy drive */
-        memset(fd, 0, sizeof(fd));
-        fd[0] = drive_get(IF_FLOPPY, 0, 0);
-        sun4m_fdctrl_init(slavio_irq[1], hwdef->fd_base, fd,
-                          &fdc_tc);
-    } else {
-        fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1);
-    }
-
-    slavio_misc_init(0, hwdef->aux1_base, 0, slavio_irq[1], fdc_tc);
-
-    if (drive_get_max_bus(IF_SCSI) > 0) {
-        fprintf(stderr, "qemu: too many SCSI bus\n");
-        exit(1);
-    }
-
-    esp_init(hwdef->esp_base, 2,
-             espdma_memory_read, espdma_memory_write,
-             espdma, espdma_irq, &esp_reset, &dma_enable);
-
-    qdev_connect_gpio_out(espdma, 0, esp_reset);
-    qdev_connect_gpio_out(espdma, 1, dma_enable);
-
-    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
-                                    RAM_size);
-
-    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
-               boot_device, RAM_size, kernel_size, graphic_width,
-               graphic_height, graphic_depth, hwdef->nvram_machine_id,
-               "Sun4c");
-
-    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-    if (kernel_cmdline) {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
-        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
-        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
-    } else {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
-    }
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
-    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
-}
-
-/* SPARCstation 2 hardware initialisation */
-static void ss2_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4c_hw_init(&sun4c_hwdefs[0], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-static QEMUMachine ss2_machine = {
-    .name = "SS-2",
-    .desc = "Sun4c platform, SPARCstation 2",
-    .init = ss2_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void sun4m_register_types(void)
-{
-    type_register_static(&idreg_info);
-    type_register_static(&afx_info);
-    type_register_static(&prom_info);
-    type_register_static(&ram_info);
-}
-
-static void ss2_machine_init(void)
-{
-    qemu_register_machine(&ss5_machine);
-    qemu_register_machine(&ss10_machine);
-    qemu_register_machine(&ss600mp_machine);
-    qemu_register_machine(&ss20_machine);
-    qemu_register_machine(&voyager_machine);
-    qemu_register_machine(&ss_lx_machine);
-    qemu_register_machine(&ss4_machine);
-    qemu_register_machine(&scls_machine);
-    qemu_register_machine(&sbook_machine);
-    qemu_register_machine(&ss1000_machine);
-    qemu_register_machine(&ss2000_machine);
-    qemu_register_machine(&ss2_machine);
-}
-
-type_init(sun4m_register_types)
-machine_init(ss2_machine_init);
index 0361eeed41c4f768b26f324f508d09b41dedc3ef..0d2cfb807b179a79d5b75abc748414ce0edbca29 100644 (file)
@@ -31,6 +31,6 @@ void sun4m_pic_info(Monitor *mon, const QDict *qdict);
 void sun4m_irq_info(Monitor *mon, const QDict *qdict);
 
 /* sparc32_dma.c */
-#include "sparc32_dma.h"
+#include "hw/sparc32_dma.h"
 
 #endif
index 8f9635f3430369b570cefd73eabfa0863b97817c..33e77b02a3decce5a1e39c01cee3c6d655b256bb 100644 (file)
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "sun4m.h"
-#include "sysbus.h"
+#include "hw/sun4m.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /*
diff --git a/hw/sun4u.c b/hw/sun4u.c
deleted file mode 100644 (file)
index 9fbda29..0000000
+++ /dev/null
@@ -1,1014 +0,0 @@
-/*
- * QEMU Sun4u/Sun4v System Emulator
- *
- * Copyright (c) 2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "pci/pci.h"
-#include "apb_pci.h"
-#include "pc.h"
-#include "serial.h"
-#include "nvram.h"
-#include "fdc.h"
-#include "net/net.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "firmware_abi.h"
-#include "fw_cfg.h"
-#include "sysbus.h"
-#include "ide.h"
-#include "loader.h"
-#include "elf.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-//#define DEBUG_IRQ
-//#define DEBUG_EBUS
-//#define DEBUG_TIMER
-
-#ifdef DEBUG_IRQ
-#define CPUIRQ_DPRINTF(fmt, ...)                                \
-    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define CPUIRQ_DPRINTF(fmt, ...)
-#endif
-
-#ifdef DEBUG_EBUS
-#define EBUS_DPRINTF(fmt, ...)                                  \
-    do { printf("EBUS: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define EBUS_DPRINTF(fmt, ...)
-#endif
-
-#ifdef DEBUG_TIMER
-#define TIMER_DPRINTF(fmt, ...)                                  \
-    do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define TIMER_DPRINTF(fmt, ...)
-#endif
-
-#define KERNEL_LOAD_ADDR     0x00404000
-#define CMDLINE_ADDR         0x003ff000
-#define PROM_SIZE_MAX        (4 * 1024 * 1024)
-#define PROM_VADDR           0x000ffd00000ULL
-#define APB_SPECIAL_BASE     0x1fe00000000ULL
-#define APB_MEM_BASE         0x1ff00000000ULL
-#define APB_PCI_IO_BASE      (APB_SPECIAL_BASE + 0x02000000ULL)
-#define PROM_FILENAME        "openbios-sparc64"
-#define NVRAM_SIZE           0x2000
-#define MAX_IDE_BUS          2
-#define BIOS_CFG_IOPORT      0x510
-#define FW_CFG_SPARC64_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
-#define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
-#define FW_CFG_SPARC64_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
-
-#define IVEC_MAX             0x30
-
-#define TICK_MAX             0x7fffffffffffffffULL
-
-struct hwdef {
-    const char * const default_cpu_model;
-    uint16_t machine_id;
-    uint64_t prom_addr;
-    uint64_t console_serial_base;
-};
-
-typedef struct EbusState {
-    PCIDevice pci_dev;
-    MemoryRegion bar0;
-    MemoryRegion bar1;
-} EbusState;
-
-int DMA_get_channel_mode (int nchan)
-{
-    return 0;
-}
-int DMA_read_memory (int nchan, void *buf, int pos, int size)
-{
-    return 0;
-}
-int DMA_write_memory (int nchan, void *buf, int pos, int size)
-{
-    return 0;
-}
-void DMA_hold_DREQ (int nchan) {}
-void DMA_release_DREQ (int nchan) {}
-void DMA_schedule(int nchan) {}
-
-void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
-{
-}
-
-void DMA_register_channel (int nchan,
-                           DMA_transfer_handler transfer_handler,
-                           void *opaque)
-{
-}
-
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
-{
-    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    return 0;
-}
-
-static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
-                                  const char *arch, ram_addr_t RAM_size,
-                                  const char *boot_devices,
-                                  uint32_t kernel_image, uint32_t kernel_size,
-                                  const char *cmdline,
-                                  uint32_t initrd_image, uint32_t initrd_size,
-                                  uint32_t NVRAM_image,
-                                  int width, int height, int depth,
-                                  const uint8_t *macaddr)
-{
-    unsigned int i;
-    uint32_t start, end;
-    uint8_t image[0x1ff0];
-    struct OpenBIOS_nvpart_v1 *part_header;
-
-    memset(image, '\0', sizeof(image));
-
-    start = 0;
-
-    // OpenBIOS nvram variables
-    // Variable partition
-    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
-    part_header->signature = OPENBIOS_PART_SYSTEM;
-    pstrcpy(part_header->name, sizeof(part_header->name), "system");
-
-    end = start + sizeof(struct OpenBIOS_nvpart_v1);
-    for (i = 0; i < nb_prom_envs; i++)
-        end = OpenBIOS_set_var(image, end, prom_envs[i]);
-
-    // End marker
-    image[end++] = '\0';
-
-    end = start + ((end - start + 15) & ~15);
-    OpenBIOS_finish_partition(part_header, end - start);
-
-    // free partition
-    start = end;
-    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
-    part_header->signature = OPENBIOS_PART_FREE;
-    pstrcpy(part_header->name, sizeof(part_header->name), "free");
-
-    end = 0x1fd0;
-    OpenBIOS_finish_partition(part_header, end - start);
-
-    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr, 0x80);
-
-    for (i = 0; i < sizeof(image); i++)
-        m48t59_write(nvram, i, image[i]);
-
-    return 0;
-}
-
-static uint64_t sun4u_load_kernel(const char *kernel_filename,
-                                  const char *initrd_filename,
-                                  ram_addr_t RAM_size, uint64_t *initrd_size,
-                                  uint64_t *initrd_addr, uint64_t *kernel_addr,
-                                  uint64_t *kernel_entry)
-{
-    int linux_boot;
-    unsigned int i;
-    long kernel_size;
-    uint8_t *ptr;
-    uint64_t kernel_top;
-
-    linux_boot = (kernel_filename != NULL);
-
-    kernel_size = 0;
-    if (linux_boot) {
-        int bswap_needed;
-
-#ifdef BSWAP_NEEDED
-        bswap_needed = 1;
-#else
-        bswap_needed = 0;
-#endif
-        kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
-                               kernel_addr, &kernel_top, 1, ELF_MACHINE, 0);
-        if (kernel_size < 0) {
-            *kernel_addr = KERNEL_LOAD_ADDR;
-            *kernel_entry = KERNEL_LOAD_ADDR;
-            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
-                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
-                                    TARGET_PAGE_SIZE);
-        }
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename,
-                                              KERNEL_LOAD_ADDR,
-                                              RAM_size - KERNEL_LOAD_ADDR);
-        }
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-        /* load initrd above kernel */
-        *initrd_size = 0;
-        if (initrd_filename) {
-            *initrd_addr = TARGET_PAGE_ALIGN(kernel_top);
-
-            *initrd_size = load_image_targphys(initrd_filename,
-                                               *initrd_addr,
-                                               RAM_size - *initrd_addr);
-            if ((int)*initrd_size < 0) {
-                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                        initrd_filename);
-                exit(1);
-            }
-        }
-        if (*initrd_size > 0) {
-            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
-                ptr = rom_ptr(*kernel_addr + i);
-                if (ldl_p(ptr + 8) == 0x48647253) { /* HdrS */
-                    stl_p(ptr + 24, *initrd_addr + *kernel_addr);
-                    stl_p(ptr + 28, *initrd_size);
-                    break;
-                }
-            }
-        }
-    }
-    return kernel_size;
-}
-
-void cpu_check_irqs(CPUSPARCState *env)
-{
-    uint32_t pil = env->pil_in |
-                  (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
-
-    /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */
-    if (env->ivec_status & 0x20) {
-        return;
-    }
-    /* check if TM or SM in SOFTINT are set
-       setting these also causes interrupt 14 */
-    if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
-        pil |= 1 << 14;
-    }
-
-    /* The bit corresponding to psrpil is (1<< psrpil), the next bit
-       is (2 << psrpil). */
-    if (pil < (2 << env->psrpil)){
-        if (env->interrupt_request & CPU_INTERRUPT_HARD) {
-            CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
-                           env->interrupt_index);
-            env->interrupt_index = 0;
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-        }
-        return;
-    }
-
-    if (cpu_interrupts_enabled(env)) {
-
-        unsigned int i;
-
-        for (i = 15; i > env->psrpil; i--) {
-            if (pil & (1 << i)) {
-                int old_interrupt = env->interrupt_index;
-                int new_interrupt = TT_EXTINT | i;
-
-                if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
-                  && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
-                    CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
-                                   "current %x >= pending %x\n",
-                                   env->tl, cpu_tsptr(env)->tt, new_interrupt);
-                } else if (old_interrupt != new_interrupt) {
-                    env->interrupt_index = new_interrupt;
-                    CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
-                                   old_interrupt, new_interrupt);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
-                }
-                break;
-            }
-        }
-    } else if (env->interrupt_request & CPU_INTERRUPT_HARD) {
-        CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
-                       "current interrupt %x\n",
-                       pil, env->pil_in, env->softint, env->interrupt_index);
-        env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-static void cpu_kick_irq(SPARCCPU *cpu)
-{
-    CPUSPARCState *env = &cpu->env;
-
-    env->halted = 0;
-    cpu_check_irqs(env);
-    qemu_cpu_kick(CPU(cpu));
-}
-
-static void cpu_set_ivec_irq(void *opaque, int irq, int level)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    if (level) {
-        if (!(env->ivec_status & 0x20)) {
-            CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
-            env->halted = 0;
-            env->interrupt_index = TT_IVEC;
-            env->ivec_status |= 0x20;
-            env->ivec_data[0] = (0x1f << 6) | irq;
-            env->ivec_data[1] = 0;
-            env->ivec_data[2] = 0;
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
-        }
-    } else {
-        if (env->ivec_status & 0x20) {
-            CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
-            env->ivec_status &= ~0x20;
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-        }
-    }
-}
-
-typedef struct ResetData {
-    SPARCCPU *cpu;
-    uint64_t prom_addr;
-} ResetData;
-
-void cpu_put_timer(QEMUFile *f, CPUTimer *s)
-{
-    qemu_put_be32s(f, &s->frequency);
-    qemu_put_be32s(f, &s->disabled);
-    qemu_put_be64s(f, &s->disabled_mask);
-    qemu_put_sbe64s(f, &s->clock_offset);
-
-    qemu_put_timer(f, s->qtimer);
-}
-
-void cpu_get_timer(QEMUFile *f, CPUTimer *s)
-{
-    qemu_get_be32s(f, &s->frequency);
-    qemu_get_be32s(f, &s->disabled);
-    qemu_get_be64s(f, &s->disabled_mask);
-    qemu_get_sbe64s(f, &s->clock_offset);
-
-    qemu_get_timer(f, s->qtimer);
-}
-
-static CPUTimer *cpu_timer_create(const char *name, SPARCCPU *cpu,
-                                  QEMUBHFunc *cb, uint32_t frequency,
-                                  uint64_t disabled_mask)
-{
-    CPUTimer *timer = g_malloc0(sizeof (CPUTimer));
-
-    timer->name = name;
-    timer->frequency = frequency;
-    timer->disabled_mask = disabled_mask;
-
-    timer->disabled = 1;
-    timer->clock_offset = qemu_get_clock_ns(vm_clock);
-
-    timer->qtimer = qemu_new_timer_ns(vm_clock, cb, cpu);
-
-    return timer;
-}
-
-static void cpu_timer_reset(CPUTimer *timer)
-{
-    timer->disabled = 1;
-    timer->clock_offset = qemu_get_clock_ns(vm_clock);
-
-    qemu_del_timer(timer->qtimer);
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetData *s = (ResetData *)opaque;
-    CPUSPARCState *env = &s->cpu->env;
-    static unsigned int nr_resets;
-
-    cpu_reset(CPU(s->cpu));
-
-    cpu_timer_reset(env->tick);
-    cpu_timer_reset(env->stick);
-    cpu_timer_reset(env->hstick);
-
-    env->gregs[1] = 0; // Memory start
-    env->gregs[2] = ram_size; // Memory size
-    env->gregs[3] = 0; // Machine description XXX
-    if (nr_resets++ == 0) {
-        /* Power on reset */
-        env->pc = s->prom_addr + 0x20ULL;
-    } else {
-        env->pc = s->prom_addr + 0x40ULL;
-    }
-    env->npc = env->pc + 4;
-}
-
-static void tick_irq(void *opaque)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    CPUTimer* timer = env->tick;
-
-    if (timer->disabled) {
-        CPUIRQ_DPRINTF("tick_irq: softint disabled\n");
-        return;
-    } else {
-        CPUIRQ_DPRINTF("tick: fire\n");
-    }
-
-    env->softint |= SOFTINT_TIMER;
-    cpu_kick_irq(cpu);
-}
-
-static void stick_irq(void *opaque)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    CPUTimer* timer = env->stick;
-
-    if (timer->disabled) {
-        CPUIRQ_DPRINTF("stick_irq: softint disabled\n");
-        return;
-    } else {
-        CPUIRQ_DPRINTF("stick: fire\n");
-    }
-
-    env->softint |= SOFTINT_STIMER;
-    cpu_kick_irq(cpu);
-}
-
-static void hstick_irq(void *opaque)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    CPUTimer* timer = env->hstick;
-
-    if (timer->disabled) {
-        CPUIRQ_DPRINTF("hstick_irq: softint disabled\n");
-        return;
-    } else {
-        CPUIRQ_DPRINTF("hstick: fire\n");
-    }
-
-    env->softint |= SOFTINT_STIMER;
-    cpu_kick_irq(cpu);
-}
-
-static int64_t cpu_to_timer_ticks(int64_t cpu_ticks, uint32_t frequency)
-{
-    return muldiv64(cpu_ticks, get_ticks_per_sec(), frequency);
-}
-
-static uint64_t timer_to_cpu_ticks(int64_t timer_ticks, uint32_t frequency)
-{
-    return muldiv64(timer_ticks, frequency, get_ticks_per_sec());
-}
-
-void cpu_tick_set_count(CPUTimer *timer, uint64_t count)
-{
-    uint64_t real_count = count & ~timer->disabled_mask;
-    uint64_t disabled_bit = count & timer->disabled_mask;
-
-    int64_t vm_clock_offset = qemu_get_clock_ns(vm_clock) -
-                    cpu_to_timer_ticks(real_count, timer->frequency);
-
-    TIMER_DPRINTF("%s set_count count=0x%016lx (%s) p=%p\n",
-                  timer->name, real_count,
-                  timer->disabled?"disabled":"enabled", timer);
-
-    timer->disabled = disabled_bit ? 1 : 0;
-    timer->clock_offset = vm_clock_offset;
-}
-
-uint64_t cpu_tick_get_count(CPUTimer *timer)
-{
-    uint64_t real_count = timer_to_cpu_ticks(
-                    qemu_get_clock_ns(vm_clock) - timer->clock_offset,
-                    timer->frequency);
-
-    TIMER_DPRINTF("%s get_count count=0x%016lx (%s) p=%p\n",
-           timer->name, real_count,
-           timer->disabled?"disabled":"enabled", timer);
-
-    if (timer->disabled)
-        real_count |= timer->disabled_mask;
-
-    return real_count;
-}
-
-void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
-{
-    int64_t now = qemu_get_clock_ns(vm_clock);
-
-    uint64_t real_limit = limit & ~timer->disabled_mask;
-    timer->disabled = (limit & timer->disabled_mask) ? 1 : 0;
-
-    int64_t expires = cpu_to_timer_ticks(real_limit, timer->frequency) +
-                    timer->clock_offset;
-
-    if (expires < now) {
-        expires = now + 1;
-    }
-
-    TIMER_DPRINTF("%s set_limit limit=0x%016lx (%s) p=%p "
-                  "called with limit=0x%016lx at 0x%016lx (delta=0x%016lx)\n",
-                  timer->name, real_limit,
-                  timer->disabled?"disabled":"enabled",
-                  timer, limit,
-                  timer_to_cpu_ticks(now - timer->clock_offset,
-                                     timer->frequency),
-                  timer_to_cpu_ticks(expires - now, timer->frequency));
-
-    if (!real_limit) {
-        TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n",
-                timer->name);
-        qemu_del_timer(timer->qtimer);
-    } else if (timer->disabled) {
-        qemu_del_timer(timer->qtimer);
-    } else {
-        qemu_mod_timer(timer->qtimer, expires);
-    }
-}
-
-static void isa_irq_handler(void *opaque, int n, int level)
-{
-    static const int isa_irq_to_ivec[16] = {
-        [1] = 0x29, /* keyboard */
-        [4] = 0x2b, /* serial */
-        [6] = 0x27, /* floppy */
-        [7] = 0x22, /* parallel */
-        [12] = 0x2a, /* mouse */
-    };
-    qemu_irq *irqs = opaque;
-    int ivec;
-
-    assert(n < 16);
-    ivec = isa_irq_to_ivec[n];
-    EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec);
-    if (ivec) {
-        qemu_set_irq(irqs[ivec], level);
-    }
-}
-
-/* EBUS (Eight bit bus) bridge */
-static ISABus *
-pci_ebus_init(PCIBus *bus, int devfn, qemu_irq *irqs)
-{
-    qemu_irq *isa_irq;
-    PCIDevice *pci_dev;
-    ISABus *isa_bus;
-
-    pci_dev = pci_create_simple(bus, devfn, "ebus");
-    isa_bus = DO_UPCAST(ISABus, qbus,
-                        qdev_get_child_bus(&pci_dev->qdev, "isa.0"));
-    isa_irq = qemu_allocate_irqs(isa_irq_handler, irqs, 16);
-    isa_bus_irqs(isa_bus, isa_irq);
-    return isa_bus;
-}
-
-static int
-pci_ebus_init1(PCIDevice *pci_dev)
-{
-    EbusState *s = DO_UPCAST(EbusState, pci_dev, pci_dev);
-
-    isa_bus_new(&pci_dev->qdev, pci_address_space_io(pci_dev));
-
-    pci_dev->config[0x04] = 0x06; // command = bus master, pci mem
-    pci_dev->config[0x05] = 0x00;
-    pci_dev->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
-    pci_dev->config[0x07] = 0x03; // status = medium devsel
-    pci_dev->config[0x09] = 0x00; // programming i/f
-    pci_dev->config[0x0D] = 0x0a; // latency_timer
-
-    isa_mmio_setup(&s->bar0, 0x1000000);
-    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
-    isa_mmio_setup(&s->bar1, 0x800000);
-    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1);
-    return 0;
-}
-
-static void ebus_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = pci_ebus_init1;
-    k->vendor_id = PCI_VENDOR_ID_SUN;
-    k->device_id = PCI_DEVICE_ID_SUN_EBUS;
-    k->revision = 0x01;
-    k->class_id = PCI_CLASS_BRIDGE_OTHER;
-}
-
-static const TypeInfo ebus_info = {
-    .name          = "ebus",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(EbusState),
-    .class_init    = ebus_class_init,
-};
-
-typedef struct PROMState {
-    SysBusDevice busdev;
-    MemoryRegion prom;
-} PROMState;
-
-static uint64_t translate_prom_address(void *opaque, uint64_t addr)
-{
-    hwaddr *base_addr = (hwaddr *)opaque;
-    return addr + *base_addr - PROM_VADDR;
-}
-
-/* Boot PROM (OpenBIOS) */
-static void prom_init(hwaddr addr, const char *bios_name)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    char *filename;
-    int ret;
-
-    dev = qdev_create(NULL, "openprom");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-
-    /* load boot prom */
-    if (bios_name == NULL) {
-        bios_name = PROM_FILENAME;
-    }
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (filename) {
-        ret = load_elf(filename, translate_prom_address, &addr,
-                       NULL, NULL, NULL, 1, ELF_MACHINE, 0);
-        if (ret < 0 || ret > PROM_SIZE_MAX) {
-            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
-        }
-        g_free(filename);
-    } else {
-        ret = -1;
-    }
-    if (ret < 0 || ret > PROM_SIZE_MAX) {
-        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
-        exit(1);
-    }
-}
-
-static int prom_init1(SysBusDevice *dev)
-{
-    PROMState *s = FROM_SYSBUS(PROMState, dev);
-
-    memory_region_init_ram(&s->prom, "sun4u.prom", PROM_SIZE_MAX);
-    vmstate_register_ram_global(&s->prom);
-    memory_region_set_readonly(&s->prom, true);
-    sysbus_init_mmio(dev, &s->prom);
-    return 0;
-}
-
-static Property prom_properties[] = {
-    {/* end of property list */},
-};
-
-static void prom_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = prom_init1;
-    dc->props = prom_properties;
-}
-
-static const TypeInfo prom_info = {
-    .name          = "openprom",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PROMState),
-    .class_init    = prom_class_init,
-};
-
-
-typedef struct RamDevice
-{
-    SysBusDevice busdev;
-    MemoryRegion ram;
-    uint64_t size;
-} RamDevice;
-
-/* System RAM */
-static int ram_init1(SysBusDevice *dev)
-{
-    RamDevice *d = FROM_SYSBUS(RamDevice, dev);
-
-    memory_region_init_ram(&d->ram, "sun4u.ram", d->size);
-    vmstate_register_ram_global(&d->ram);
-    sysbus_init_mmio(dev, &d->ram);
-    return 0;
-}
-
-static void ram_init(hwaddr addr, ram_addr_t RAM_size)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    RamDevice *d;
-
-    /* allocate RAM */
-    dev = qdev_create(NULL, "memory");
-    s = SYS_BUS_DEVICE(dev);
-
-    d = FROM_SYSBUS(RamDevice, s);
-    d->size = RAM_size;
-    qdev_init_nofail(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-}
-
-static Property ram_properties[] = {
-    DEFINE_PROP_UINT64("size", RamDevice, size, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void ram_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = ram_init1;
-    dc->props = ram_properties;
-}
-
-static const TypeInfo ram_info = {
-    .name          = "memory",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(RamDevice),
-    .class_init    = ram_class_init,
-};
-
-static SPARCCPU *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
-{
-    SPARCCPU *cpu;
-    CPUSPARCState *env;
-    ResetData *reset_info;
-
-    uint32_t   tick_frequency = 100*1000000;
-    uint32_t  stick_frequency = 100*1000000;
-    uint32_t hstick_frequency = 100*1000000;
-
-    if (cpu_model == NULL) {
-        cpu_model = hwdef->default_cpu_model;
-    }
-    cpu = cpu_sparc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find Sparc CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    env->tick = cpu_timer_create("tick", cpu, tick_irq,
-                                  tick_frequency, TICK_NPT_MASK);
-
-    env->stick = cpu_timer_create("stick", cpu, stick_irq,
-                                   stick_frequency, TICK_INT_DIS);
-
-    env->hstick = cpu_timer_create("hstick", cpu, hstick_irq,
-                                    hstick_frequency, TICK_INT_DIS);
-
-    reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->cpu = cpu;
-    reset_info->prom_addr = hwdef->prom_addr;
-    qemu_register_reset(main_cpu_reset, reset_info);
-
-    return cpu;
-}
-
-static void sun4uv_init(MemoryRegion *address_space_mem,
-                        ram_addr_t RAM_size,
-                        const char *boot_devices,
-                        const char *kernel_filename, const char *kernel_cmdline,
-                        const char *initrd_filename, const char *cpu_model,
-                        const struct hwdef *hwdef)
-{
-    SPARCCPU *cpu;
-    M48t59State *nvram;
-    unsigned int i;
-    uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
-    PCIBus *pci_bus, *pci_bus2, *pci_bus3;
-    ISABus *isa_bus;
-    qemu_irq *ivec_irqs, *pbm_irqs;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    DriveInfo *fd[MAX_FD];
-    void *fw_cfg;
-
-    /* init CPUs */
-    cpu = cpu_devinit(cpu_model, hwdef);
-
-    /* set up devices */
-    ram_init(0, RAM_size);
-
-    prom_init(hwdef->prom_addr, bios_name);
-
-    ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, cpu, IVEC_MAX);
-    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2,
-                           &pci_bus3, &pbm_irqs);
-    pci_vga_init(pci_bus);
-
-    // XXX Should be pci_bus3
-    isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs);
-
-    i = 0;
-    if (hwdef->console_serial_base) {
-        serial_mm_init(address_space_mem, hwdef->console_serial_base, 0,
-                       NULL, 115200, serial_hds[i], DEVICE_BIG_ENDIAN);
-        i++;
-    }
-    for(; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_hds[i]) {
-            serial_isa_init(isa_bus, i, serial_hds[i]);
-        }
-    }
-
-    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
-        if (parallel_hds[i]) {
-            parallel_init(isa_bus, i, parallel_hds[i]);
-        }
-    }
-
-    for(i = 0; i < nb_nics; i++)
-        pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
-
-    ide_drive_get(hd, MAX_IDE_BUS);
-
-    pci_cmd646_ide_init(pci_bus, hd, 1);
-
-    isa_create_simple(isa_bus, "i8042");
-    for(i = 0; i < MAX_FD; i++) {
-        fd[i] = drive_get(IF_FLOPPY, 0, i);
-    }
-    fdctrl_init_isa(isa_bus, fd);
-    nvram = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
-
-    initrd_size = 0;
-    initrd_addr = 0;
-    kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
-                                    ram_size, &initrd_size, &initrd_addr,
-                                    &kernel_addr, &kernel_entry);
-
-    sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
-                           kernel_addr, kernel_size,
-                           kernel_cmdline,
-                           initrd_addr, initrd_size,
-                           /* XXX: need an option to load a NVRAM image */
-                           0,
-                           graphic_width, graphic_height, graphic_depth,
-                           (uint8_t *)&nd_table[0].macaddr);
-
-    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-    if (kernel_cmdline) {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
-                       strlen(kernel_cmdline) + 1);
-        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
-    } else {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
-    }
-    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_devices[0]);
-
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_HEIGHT, graphic_height);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_DEPTH, graphic_depth);
-
-    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
-}
-
-enum {
-    sun4u_id = 0,
-    sun4v_id = 64,
-    niagara_id,
-};
-
-static const struct hwdef hwdefs[] = {
-    /* Sun4u generic PC-like machine */
-    {
-        .default_cpu_model = "TI UltraSparc IIi",
-        .machine_id = sun4u_id,
-        .prom_addr = 0x1fff0000000ULL,
-        .console_serial_base = 0,
-    },
-    /* Sun4v generic PC-like machine */
-    {
-        .default_cpu_model = "Sun UltraSparc T1",
-        .machine_id = sun4v_id,
-        .prom_addr = 0x1fff0000000ULL,
-        .console_serial_base = 0,
-    },
-    /* Sun4v generic Niagara machine */
-    {
-        .default_cpu_model = "Sun UltraSparc T1",
-        .machine_id = niagara_id,
-        .prom_addr = 0xfff0000000ULL,
-        .console_serial_base = 0xfff0c2c000ULL,
-    },
-};
-
-/* Sun4u hardware initialisation */
-static void sun4u_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_devices = args->boot_device;
-    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
-                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[0]);
-}
-
-/* Sun4v hardware initialisation */
-static void sun4v_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_devices = args->boot_device;
-    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
-                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]);
-}
-
-/* Niagara hardware initialisation */
-static void niagara_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_devices = args->boot_device;
-    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
-                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]);
-}
-
-static QEMUMachine sun4u_machine = {
-    .name = "sun4u",
-    .desc = "Sun4u platform",
-    .init = sun4u_init,
-    .max_cpus = 1, // XXX for now
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine sun4v_machine = {
-    .name = "sun4v",
-    .desc = "Sun4v platform",
-    .init = sun4v_init,
-    .max_cpus = 1, // XXX for now
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine niagara_machine = {
-    .name = "Niagara",
-    .desc = "Sun4v platform, Niagara",
-    .init = niagara_init,
-    .max_cpus = 1, // XXX for now
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void sun4u_register_types(void)
-{
-    type_register_static(&ebus_info);
-    type_register_static(&prom_info);
-    type_register_static(&ram_info);
-}
-
-static void sun4u_machine_init(void)
-{
-    qemu_register_machine(&sun4u_machine);
-    qemu_register_machine(&sun4v_machine);
-    qemu_register_machine(&niagara_machine);
-}
-
-type_init(sun4u_register_types)
-machine_init(sun4u_machine_init);
index 50c72327997654de494145d3b28a59fe6d4690e1..702fc728f4ca32285af2b2f8b338a95487faed87 100644 (file)
@@ -17,7 +17,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "monitor/monitor.h"
 #include "exec/address-spaces.h"
 
index 2100bd7d0781087903027484b83636d7b9cd23ec..5d90a52af5d766392f71bd3683575dcd578b7597 100644 (file)
@@ -3,7 +3,7 @@
 
 /* Devices attached directly to the main system bus.  */
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "exec/memory.h"
 
 #define QDEV_MAX_MMIO 32
index 4ce80b18f3f6bc7fd618d64434673c52b1a9c825..f76f96d9e7e1aade94f16c647527bac9dacb9db3 100644 (file)
@@ -1,6 +1,6 @@
-#include "hw.h"
-#include "sh.h"
-#include "loader.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "hw/loader.h"
 
 #define CE1  0x0100
 #define CE2  0x0200
index e815f83198f3962a1f89e5afe0c212dad83bce0c..0755463a1dd95c52aa6f3b1cd13f393055d64cbe 100644 (file)
@@ -10,9 +10,9 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "devices.h"
-#include "flash.h"
+#include "hw/hw.h"
+#include "hw/devices.h"
+#include "hw/flash.h"
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
 #include "sysemu/blockdev.h"
@@ -421,15 +421,15 @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
 }
 
 #define BITS 8
-#include "tc6393xb_template.h"
+#include "hw/tc6393xb_template.h"
 #define BITS 15
-#include "tc6393xb_template.h"
+#include "hw/tc6393xb_template.h"
 #define BITS 16
-#include "tc6393xb_template.h"
+#include "hw/tc6393xb_template.h"
 #define BITS 24
-#include "tc6393xb_template.h"
+#include "hw/tc6393xb_template.h"
 #define BITS 32
-#include "tc6393xb_template.h"
+#include "hw/tc6393xb_template.h"
 
 static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
 {
index 0ce2952f7393496ed4921529f075206a1902ab21..896407d8650964540cc1716f8eaf29c00596e198 100644 (file)
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -25,8 +25,8 @@
 #include "qemu-common.h"
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
-#include "sysbus.h"
-#include "qdev-addr.h"
+#include "hw/sysbus.h"
+#include "hw/qdev-addr.h"
 
 #define MAXX 1024
 #define MAXY 768
index 3ad2d2f04c928f276e89efc43edb44ac89db18f0..47e5437e0dc86cfc14468c2c51ba2712947f6893 100644 (file)
@@ -18,9 +18,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "i2c.h"
-#include "tmp105.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
+#include "hw/tmp105.h"
 #include "qapi/visitor.h"
 
 static void tmp105_interrupt_update(TMP105State *s)
index d2189191e2a3ca4d0cc2c417d7d65292bbeea954..9a9632c54b9645b8f34098878b19571351084132 100644 (file)
@@ -14,8 +14,8 @@
 #ifndef QEMU_TMP105_H
 #define QEMU_TMP105_H
 
-#include "i2c.h"
-#include "tmp105_regs.h"
+#include "hw/i2c.h"
+#include "hw/tmp105_regs.h"
 
 #define TYPE_TMP105 "tmp105"
 #define TMP105(obj) OBJECT_CHECK(TMP105State, (obj), TYPE_TMP105)
diff --git a/hw/tosa.c b/hw/tosa.c
deleted file mode 100644 (file)
index efea109..0000000
--- a/hw/tosa.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/* vim:set shiftwidth=4 ts=4 et: */
-/*
- * PXA255 Sharp Zaurus SL-6000 PDA platform
- *
- * Copyright (c) 2008 Dmitry Baryshkov
- *
- * Code based on spitz platform by Andrzej Zaborowski <balrog@zabor.org>
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "hw.h"
-#include "pxa.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "sharpsl.h"
-#include "pcmcia.h"
-#include "block/block.h"
-#include "boards.h"
-#include "i2c.h"
-#include "ssi.h"
-#include "sysemu/blockdev.h"
-#include "sysbus.h"
-#include "exec/address-spaces.h"
-
-#define TOSA_RAM    0x04000000
-#define TOSA_ROM       0x00800000
-
-#define TOSA_GPIO_USB_IN               (5)
-#define TOSA_GPIO_nSD_DETECT   (9)
-#define TOSA_GPIO_ON_RESET             (19)
-#define TOSA_GPIO_CF_IRQ               (21)    /* CF slot0 Ready */
-#define TOSA_GPIO_CF_CD                        (13)
-#define TOSA_GPIO_TC6393XB_INT  (15)
-#define TOSA_GPIO_JC_CF_IRQ            (36)    /* CF slot1 Ready */
-
-#define TOSA_SCOOP_GPIO_BASE   1
-#define TOSA_GPIO_IR_POWERDWN  (TOSA_SCOOP_GPIO_BASE + 2)
-#define TOSA_GPIO_SD_WP                        (TOSA_SCOOP_GPIO_BASE + 3)
-#define TOSA_GPIO_PWR_ON               (TOSA_SCOOP_GPIO_BASE + 4)
-
-#define TOSA_SCOOP_JC_GPIO_BASE                1
-#define TOSA_GPIO_BT_LED               (TOSA_SCOOP_JC_GPIO_BASE + 0)
-#define TOSA_GPIO_NOTE_LED             (TOSA_SCOOP_JC_GPIO_BASE + 1)
-#define TOSA_GPIO_CHRG_ERR_LED         (TOSA_SCOOP_JC_GPIO_BASE + 2)
-#define TOSA_GPIO_TC6393XB_L3V_ON      (TOSA_SCOOP_JC_GPIO_BASE + 5)
-#define TOSA_GPIO_WLAN_LED             (TOSA_SCOOP_JC_GPIO_BASE + 7)
-
-#define        DAC_BASE        0x4e
-#define DAC_CH1                0
-#define DAC_CH2                1
-
-static void tosa_microdrive_attach(PXA2xxState *cpu)
-{
-    PCMCIACardState *md;
-    DriveInfo *dinfo;
-
-    dinfo = drive_get(IF_IDE, 0, 0);
-    if (!dinfo || dinfo->media_cd)
-        return;
-    md = dscm1xxxx_init(dinfo);
-    pxa2xx_pcmcia_attach(cpu->pcmcia[0], md);
-}
-
-static void tosa_out_switch(void *opaque, int line, int level)
-{
-    switch (line) {
-        case 0:
-            fprintf(stderr, "blue LED %s.\n", level ? "on" : "off");
-            break;
-        case 1:
-            fprintf(stderr, "green LED %s.\n", level ? "on" : "off");
-            break;
-        case 2:
-            fprintf(stderr, "amber LED %s.\n", level ? "on" : "off");
-            break;
-        case 3:
-            fprintf(stderr, "wlan LED %s.\n", level ? "on" : "off");
-            break;
-        default:
-            fprintf(stderr, "Uhandled out event: %d = %d\n", line, level);
-            break;
-    }
-}
-
-
-static void tosa_gpio_setup(PXA2xxState *cpu,
-                DeviceState *scp0,
-                DeviceState *scp1,
-                TC6393xbState *tmio)
-{
-    qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4);
-    /* MMC/SD host */
-    pxa2xx_mmci_handlers(cpu->mmc,
-                    qdev_get_gpio_in(scp0, TOSA_GPIO_SD_WP),
-                    qemu_irq_invert(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_nSD_DETECT)));
-
-    /* Handle reset */
-    qdev_connect_gpio_out(cpu->gpio, TOSA_GPIO_ON_RESET, cpu->reset);
-
-    /* PCMCIA signals: card's IRQ and Card-Detect */
-    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
-                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_IRQ),
-                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_CD));
-
-    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
-                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_JC_CF_IRQ),
-                        NULL);
-
-    qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
-    qdev_connect_gpio_out(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
-    qdev_connect_gpio_out(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
-    qdev_connect_gpio_out(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
-
-    qdev_connect_gpio_out(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio));
-
-    /* UDC Vbus */
-    qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_USB_IN));
-}
-
-static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value)
-{
-    fprintf(stderr, "TG: %d %02x\n", value >> 5, value & 0x1f);
-    return 0;
-}
-
-static int tosa_ssp_init(SSISlave *dev)
-{
-    /* Nothing to do.  */
-    return 0;
-}
-
-typedef struct {
-    I2CSlave i2c;
-    int len;
-    char buf[3];
-} TosaDACState;
-
-static int tosa_dac_send(I2CSlave *i2c, uint8_t data)
-{
-    TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c);
-    s->buf[s->len] = data;
-    if (s->len ++ > 2) {
-#ifdef VERBOSE
-        fprintf(stderr, "%s: message too long (%i bytes)\n", __FUNCTION__, s->len);
-#endif
-        return 1;
-    }
-
-    if (s->len == 2) {
-        fprintf(stderr, "dac: channel %d value 0x%02x\n",
-                s->buf[0], s->buf[1]);
-    }
-
-    return 0;
-}
-
-static void tosa_dac_event(I2CSlave *i2c, enum i2c_event event)
-{
-    TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c);
-    s->len = 0;
-    switch (event) {
-    case I2C_START_SEND:
-        break;
-    case I2C_START_RECV:
-        printf("%s: recv not supported!!!\n", __FUNCTION__);
-        break;
-    case I2C_FINISH:
-#ifdef VERBOSE
-        if (s->len < 2)
-            printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
-        if (s->len > 2)
-            printf("%s: message too long\n", __FUNCTION__);
-#endif
-        break;
-    default:
-        break;
-    }
-}
-
-static int tosa_dac_recv(I2CSlave *s)
-{
-    printf("%s: recv not supported!!!\n", __FUNCTION__);
-    return -1;
-}
-
-static int tosa_dac_init(I2CSlave *i2c)
-{
-    /* Nothing to do.  */
-    return 0;
-}
-
-static void tosa_tg_init(PXA2xxState *cpu)
-{
-    i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
-    i2c_create_slave(bus, "tosa_dac", DAC_BASE);
-    ssi_create_slave(cpu->ssp[1], "tosa-ssp");
-}
-
-
-static struct arm_boot_info tosa_binfo = {
-    .loader_start = PXA2XX_SDRAM_BASE,
-    .ram_size = 0x04000000,
-};
-
-static void tosa_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *rom = g_new(MemoryRegion, 1);
-    PXA2xxState *mpu;
-    TC6393xbState *tmio;
-    DeviceState *scp0, *scp1;
-
-    if (!cpu_model)
-        cpu_model = "pxa255";
-
-    mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
-
-    memory_region_init_ram(rom, "tosa.rom", TOSA_ROM);
-    vmstate_register_ram_global(rom);
-    memory_region_set_readonly(rom, true);
-    memory_region_add_subregion(address_space_mem, 0, rom);
-
-    tmio = tc6393xb_init(address_space_mem, 0x10000000,
-            qdev_get_gpio_in(mpu->gpio, TOSA_GPIO_TC6393XB_INT));
-
-    scp0 = sysbus_create_simple("scoop", 0x08800000, NULL);
-    scp1 = sysbus_create_simple("scoop", 0x14800040, NULL);
-
-    tosa_gpio_setup(mpu, scp0, scp1, tmio);
-
-    tosa_microdrive_attach(mpu);
-
-    tosa_tg_init(mpu);
-
-    tosa_binfo.kernel_filename = kernel_filename;
-    tosa_binfo.kernel_cmdline = kernel_cmdline;
-    tosa_binfo.initrd_filename = initrd_filename;
-    tosa_binfo.board_id = 0x208;
-    arm_load_kernel(mpu->cpu, &tosa_binfo);
-    sl_bootparam_write(SL_PXA_PARAM_BASE);
-}
-
-static QEMUMachine tosapda_machine = {
-    .name = "tosa",
-    .desc = "Tosa PDA (PXA255)",
-    .init = tosa_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void tosapda_machine_init(void)
-{
-    qemu_register_machine(&tosapda_machine);
-}
-
-machine_init(tosapda_machine_init);
-
-static void tosa_dac_class_init(ObjectClass *klass, void *data)
-{
-    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
-
-    k->init = tosa_dac_init;
-    k->event = tosa_dac_event;
-    k->recv = tosa_dac_recv;
-    k->send = tosa_dac_send;
-}
-
-static const TypeInfo tosa_dac_info = {
-    .name          = "tosa_dac",
-    .parent        = TYPE_I2C_SLAVE,
-    .instance_size = sizeof(TosaDACState),
-    .class_init    = tosa_dac_class_init,
-};
-
-static void tosa_ssp_class_init(ObjectClass *klass, void *data)
-{
-    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
-
-    k->init = tosa_ssp_init;
-    k->transfer = tosa_ssp_tansfer;
-}
-
-static const TypeInfo tosa_ssp_info = {
-    .name          = "tosa-ssp",
-    .parent        = TYPE_SSI_SLAVE,
-    .instance_size = sizeof(SSISlave),
-    .class_init    = tosa_ssp_class_init,
-};
-
-static void tosa_register_types(void)
-{
-    type_register_static(&tosa_dac_info);
-    type_register_static(&tosa_ssp_info);
-}
-
-type_init(tosa_register_types)
index a4823fb9f2c3efcf844a1f97ced96c79644aadc3..e3408ef4bad584bfd7ccbbd6a6f97ced68c4af44 100644 (file)
@@ -8,8 +8,8 @@
  * later version.
  */
 
-#include "ipack.h"
-#include "pci/pci.h"
+#include "hw/ipack.h"
+#include "hw/pci/pci.h"
 #include "qemu/bitops.h"
 #include <stdio.h>
 
index 740ff86aa8ad751dd8d51b15049ab02c821eef6e..a771cd5e52a8b731b2ce3dc10699a1699618a90d 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
 #include "ui/console.h"
-#include "devices.h"
+#include "hw/devices.h"
 
 #define TSC_CUT_RESOLUTION(value, p)   ((value) >> (16 - (p ? 12 : 10)))
 
index 2076c355d2225b303b994185cfedf4571b2ada17..b93e502e0587a39b8df9ab75ef24f0b19f011ae8 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "audio/audio.h"
 #include "qemu/timer.h"
 #include "ui/console.h"
-#include "omap.h"      /* For I2SCodec and uWireSlave */
-#include "devices.h"
+#include "hw/omap.h"   /* For I2SCodec and uWireSlave */
+#include "hw/devices.h"
 
 #define TSC_DATA_REGISTERS_PAGE                0x0
 #define TSC_CONTROL_REGISTERS_PAGE     0x1
index 2c7d0336510c31154a1393f528fb5e4c29eb696f..a5251a34ac6fed2451df09cbda310a5a23331676 100644 (file)
  */
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "usb.h"
-#include "omap.h"
-#include "irq.h"
-#include "devices.h"
-#include "sysbus.h"
+#include "hw/usb.h"
+#include "hw/omap.h"
+#include "hw/irq.h"
+#include "hw/devices.h"
+#include "hw/sysbus.h"
 
 typedef struct TUSBState {
     SysBusDevice busdev;
index 70d9b03e553162c6b8a8a1222fa4a0344c851873..7d020c4cba04a901c43d31facc62e233b5c86507 100644 (file)
@@ -19,9 +19,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "i2c.h"
+#include "hw/i2c.h"
 #include "sysemu/sysemu.h"
 #include "ui/console.h"
 
index 0725ce3ca7ca80aae854b974dbec64338496fd07..e0fd62852308e81f429a97a7770312b22724cb9f 100644 (file)
@@ -2,5 +2,3 @@
 
 # PKUnity-v3 SoC and board information
 obj-${CONFIG_PUV3} += puv3.o
-
-obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c
new file mode 100644 (file)
index 0000000..f9d0c2b
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Generic PKUnity SoC machine and board descriptor
+ *
+ * Copyright (C) 2010-2012 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or any later version.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+#include "ui/console.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+#include "hw/sysbus.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/pc.h"
+
+#undef DEBUG_PUV3
+#include "hw/puv3.h"
+
+#define KERNEL_LOAD_ADDR        0x03000000
+#define KERNEL_MAX_SIZE         0x00800000 /* Just a guess */
+
+static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
+{
+    CPUUniCore32State *env = opaque;
+
+    assert(irq == 0);
+    if (level) {
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void puv3_soc_init(CPUUniCore32State *env)
+{
+    qemu_irq *cpu_intc, irqs[PUV3_IRQS_NR];
+    DeviceState *dev;
+    MemoryRegion *i8042 = g_new(MemoryRegion, 1);
+    int i;
+
+    /* Initialize interrupt controller */
+    cpu_intc = qemu_allocate_irqs(puv3_intc_cpu_handler, env, 1);
+    dev = sysbus_create_simple("puv3_intc", PUV3_INTC_BASE, *cpu_intc);
+    for (i = 0; i < PUV3_IRQS_NR; i++) {
+        irqs[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    /* Initialize minimal necessary devices for kernel booting */
+    sysbus_create_simple("puv3_pm", PUV3_PM_BASE, NULL);
+    sysbus_create_simple("puv3_dma", PUV3_DMA_BASE, NULL);
+    sysbus_create_simple("puv3_ost", PUV3_OST_BASE, irqs[PUV3_IRQS_OST0]);
+    sysbus_create_varargs("puv3_gpio", PUV3_GPIO_BASE,
+            irqs[PUV3_IRQS_GPIOLOW0], irqs[PUV3_IRQS_GPIOLOW1],
+            irqs[PUV3_IRQS_GPIOLOW2], irqs[PUV3_IRQS_GPIOLOW3],
+            irqs[PUV3_IRQS_GPIOLOW4], irqs[PUV3_IRQS_GPIOLOW5],
+            irqs[PUV3_IRQS_GPIOLOW6], irqs[PUV3_IRQS_GPIOLOW7],
+            irqs[PUV3_IRQS_GPIOHIGH], NULL);
+
+    /* Keyboard (i8042), mouse disabled for nographic */
+    i8042_mm_init(irqs[PUV3_IRQS_PS2_KBD], NULL, i8042, PUV3_REGS_OFFSET, 4);
+    memory_region_add_subregion(get_system_memory(), PUV3_PS2_BASE, i8042);
+}
+
+static void puv3_board_init(CPUUniCore32State *env, ram_addr_t ram_size)
+{
+    MemoryRegion *ram_memory = g_new(MemoryRegion, 1);
+
+    /* SDRAM at address zero.  */
+    memory_region_init_ram(ram_memory, "puv3.ram", ram_size);
+    vmstate_register_ram_global(ram_memory);
+    memory_region_add_subregion(get_system_memory(), 0, ram_memory);
+}
+
+static void puv3_load_kernel(const char *kernel_filename)
+{
+    int size;
+
+    assert(kernel_filename != NULL);
+
+    /* only zImage format supported */
+    size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
+            KERNEL_MAX_SIZE);
+    if (size < 0) {
+        hw_error("Load kernel error: '%s'\n", kernel_filename);
+    }
+
+    /* cheat curses that we have a graphic console, only under ocd console */
+    graphic_console_init(NULL, NULL, NULL, NULL, NULL);
+}
+
+static void puv3_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *initrd_filename = args->initrd_filename;
+    CPUUniCore32State *env;
+
+    if (initrd_filename) {
+        hw_error("Please use kernel built-in initramdisk.\n");
+    }
+
+    if (!cpu_model) {
+        cpu_model = "UniCore-II";
+    }
+
+    env = cpu_init(cpu_model);
+    if (!env) {
+        hw_error("Unable to find CPU definition\n");
+    }
+
+    puv3_soc_init(env);
+    puv3_board_init(env, ram_size);
+    puv3_load_kernel(kernel_filename);
+}
+
+static QEMUMachine puv3_machine = {
+    .name = "puv3",
+    .desc = "PKUnity Version-3 based on UniCore32",
+    .init = puv3_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void puv3_machine_init(void)
+{
+    qemu_register_machine(&puv3_machine);
+}
+
+machine_init(puv3_machine_init)
index f1c3c20f375ed2560167f775c129c9e3d0a8c58c..cb95ad1f5eeacabe53fa44e56e02730e81fcfdf4 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc/mac.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
+#include "hw/hw.h"
+#include "hw/ppc/mac.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
 
 /* debug UniNorth */
 //#define DEBUG_UNIN
index 382496cf8230730ba1cbe37306dfa8932a6d7be1..1b10684ddea942180902cdefd9686b8e3face9cf 100644 (file)
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -25,7 +25,7 @@
  * THE SOFTWARE.
  */
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "qemu/queue.h"
 
 /* Constants related to the USB / PCI interaction */
index c08718b6791daf023f88a4a19eb87b4898be37fc..5473ac2cd52e162b8f936b6c3680308fa1be8908 100644 (file)
@@ -27,6 +27,7 @@
 #include "hw/usb.h"
 #include "hw/usb/desc.h"
 #include "net/net.h"
+#include "qapi/qmp/qerror.h"
 #include "qemu/queue.h"
 #include "qemu/config-file.h"
 #include "sysemu/sysemu.h"
index ad71e9d92d018d5ff82aebb052f70090b96a64fe..d0444aecac93ab326809e8b9d3152c476974cfa4 100644 (file)
@@ -21,8 +21,8 @@
  *
  */
 
-#include "sysbus.h"
-#include "bitbang_i2c.h"
+#include "hw/sysbus.h"
+#include "hw/bitbang_i2c.h"
 
 typedef struct {
     SysBusDevice busdev;
index 9d991599cfa9c8425d2616da81d3bb9ebf9d317c..0b97a4073d728b66d364c77e9ee81edaa3551cbb 100644 (file)
@@ -7,9 +7,9 @@
  * This code is licensed under the LGPL.
  */
 
-#include "sysbus.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
 #include "exec/address-spaces.h"
 
 typedef struct {
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
deleted file mode 100644 (file)
index e0a28f0..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * ARM Versatile Platform/Application Baseboard System emulation.
- *
- * Copyright (c) 2005-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "pci/pci.h"
-#include "i2c.h"
-#include "boards.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-#include "flash.h"
-
-#define VERSATILE_FLASH_ADDR 0x34000000
-#define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
-#define VERSATILE_FLASH_SECT_SIZE (256 * 1024)
-
-/* Primary interrupt controller.  */
-
-typedef struct vpb_sic_state
-{
-  SysBusDevice busdev;
-  MemoryRegion iomem;
-  uint32_t level;
-  uint32_t mask;
-  uint32_t pic_enable;
-  qemu_irq parent[32];
-  int irq;
-} vpb_sic_state;
-
-static const VMStateDescription vmstate_vpb_sic = {
-    .name = "versatilepb_sic",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(level, vpb_sic_state),
-        VMSTATE_UINT32(mask, vpb_sic_state),
-        VMSTATE_UINT32(pic_enable, vpb_sic_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void vpb_sic_update(vpb_sic_state *s)
-{
-    uint32_t flags;
-
-    flags = s->level & s->mask;
-    qemu_set_irq(s->parent[s->irq], flags != 0);
-}
-
-static void vpb_sic_update_pic(vpb_sic_state *s)
-{
-    int i;
-    uint32_t mask;
-
-    for (i = 21; i <= 30; i++) {
-        mask = 1u << i;
-        if (!(s->pic_enable & mask))
-            continue;
-        qemu_set_irq(s->parent[i], (s->level & mask) != 0);
-    }
-}
-
-static void vpb_sic_set_irq(void *opaque, int irq, int level)
-{
-    vpb_sic_state *s = (vpb_sic_state *)opaque;
-    if (level)
-        s->level |= 1u << irq;
-    else
-        s->level &= ~(1u << irq);
-    if (s->pic_enable & (1u << irq))
-        qemu_set_irq(s->parent[irq], level);
-    vpb_sic_update(s);
-}
-
-static uint64_t vpb_sic_read(void *opaque, hwaddr offset,
-                             unsigned size)
-{
-    vpb_sic_state *s = (vpb_sic_state *)opaque;
-
-    switch (offset >> 2) {
-    case 0: /* STATUS */
-        return s->level & s->mask;
-    case 1: /* RAWSTAT */
-        return s->level;
-    case 2: /* ENABLE */
-        return s->mask;
-    case 4: /* SOFTINT */
-        return s->level & 1;
-    case 8: /* PICENABLE */
-        return s->pic_enable;
-    default:
-        printf ("vpb_sic_read: Bad register offset 0x%x\n", (int)offset);
-        return 0;
-    }
-}
-
-static void vpb_sic_write(void *opaque, hwaddr offset,
-                          uint64_t value, unsigned size)
-{
-    vpb_sic_state *s = (vpb_sic_state *)opaque;
-
-    switch (offset >> 2) {
-    case 2: /* ENSET */
-        s->mask |= value;
-        break;
-    case 3: /* ENCLR */
-        s->mask &= ~value;
-        break;
-    case 4: /* SOFTINTSET */
-        if (value)
-            s->mask |= 1;
-        break;
-    case 5: /* SOFTINTCLR */
-        if (value)
-            s->mask &= ~1u;
-        break;
-    case 8: /* PICENSET */
-        s->pic_enable |= (value & 0x7fe00000);
-        vpb_sic_update_pic(s);
-        break;
-    case 9: /* PICENCLR */
-        s->pic_enable &= ~value;
-        vpb_sic_update_pic(s);
-        break;
-    default:
-        printf ("vpb_sic_write: Bad register offset 0x%x\n", (int)offset);
-        return;
-    }
-    vpb_sic_update(s);
-}
-
-static const MemoryRegionOps vpb_sic_ops = {
-    .read = vpb_sic_read,
-    .write = vpb_sic_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int vpb_sic_init(SysBusDevice *dev)
-{
-    vpb_sic_state *s = FROM_SYSBUS(vpb_sic_state, dev);
-    int i;
-
-    qdev_init_gpio_in(&dev->qdev, vpb_sic_set_irq, 32);
-    for (i = 0; i < 32; i++) {
-        sysbus_init_irq(dev, &s->parent[i]);
-    }
-    s->irq = 31;
-    memory_region_init_io(&s->iomem, &vpb_sic_ops, s, "vpb-sic", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-/* Board init.  */
-
-/* The AB and PB boards both use the same core, just with different
-   peripherals and expansion busses.  For now we emulate a subset of the
-   PB peripherals and just change the board ID.  */
-
-static struct arm_boot_info versatile_binfo;
-
-static void versatile_init(QEMUMachineInitArgs *args, int board_id)
-{
-    ARMCPU *cpu;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    qemu_irq *cpu_pic;
-    qemu_irq pic[32];
-    qemu_irq sic[32];
-    DeviceState *dev, *sysctl;
-    SysBusDevice *busdev;
-    DeviceState *pl041;
-    PCIBus *pci_bus;
-    NICInfo *nd;
-    i2c_bus *i2c;
-    int n;
-    int done_smc = 0;
-    DriveInfo *dinfo;
-
-    if (!args->cpu_model) {
-        args->cpu_model = "arm926";
-    }
-    cpu = cpu_arm_init(args->cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    memory_region_init_ram(ram, "versatile.ram", args->ram_size);
-    vmstate_register_ram_global(ram);
-    /* ??? RAM should repeat to fill physical memory space.  */
-    /* SDRAM at address zero.  */
-    memory_region_add_subregion(sysmem, 0, ram);
-
-    sysctl = qdev_create(NULL, "realview_sysctl");
-    qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
-    qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000);
-    qdev_init_nofail(sysctl);
-    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
-
-    cpu_pic = arm_pic_init_cpu(cpu);
-    dev = sysbus_create_varargs("pl190", 0x10140000,
-                                cpu_pic[ARM_PIC_CPU_IRQ],
-                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
-    for (n = 0; n < 32; n++) {
-        pic[n] = qdev_get_gpio_in(dev, n);
-    }
-    dev = sysbus_create_simple("versatilepb_sic", 0x10003000, NULL);
-    for (n = 0; n < 32; n++) {
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), n, pic[n]);
-        sic[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]);
-    sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]);
-
-    dev = qdev_create(NULL, "versatile_pci");
-    busdev = SYS_BUS_DEVICE(dev);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(busdev, 0, 0x41000000); /* PCI self-config */
-    sysbus_mmio_map(busdev, 1, 0x42000000); /* PCI config */
-    sysbus_connect_irq(busdev, 0, sic[27]);
-    sysbus_connect_irq(busdev, 1, sic[28]);
-    sysbus_connect_irq(busdev, 2, sic[29]);
-    sysbus_connect_irq(busdev, 3, sic[30]);
-    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
-
-    /* The Versatile PCI bridge does not provide access to PCI IO space,
-       so many of the qemu PCI devices are not useable.  */
-    for(n = 0; n < nb_nics; n++) {
-        nd = &nd_table[n];
-
-        if (!done_smc && (!nd->model || strcmp(nd->model, "smc91c111") == 0)) {
-            smc91c111_init(nd, 0x10010000, sic[25]);
-            done_smc = 1;
-        } else {
-            pci_nic_init_nofail(nd, "rtl8139", NULL);
-        }
-    }
-    if (usb_enabled(false)) {
-        pci_create_simple(pci_bus, -1, "pci-ohci");
-    }
-    n = drive_get_max_bus(IF_SCSI);
-    while (n >= 0) {
-        pci_create_simple(pci_bus, -1, "lsi53c895a");
-        n--;
-    }
-
-    sysbus_create_simple("pl011", 0x101f1000, pic[12]);
-    sysbus_create_simple("pl011", 0x101f2000, pic[13]);
-    sysbus_create_simple("pl011", 0x101f3000, pic[14]);
-    sysbus_create_simple("pl011", 0x10009000, sic[6]);
-
-    sysbus_create_simple("pl080", 0x10130000, pic[17]);
-    sysbus_create_simple("sp804", 0x101e2000, pic[4]);
-    sysbus_create_simple("sp804", 0x101e3000, pic[5]);
-
-    sysbus_create_simple("pl061", 0x101e4000, pic[6]);
-    sysbus_create_simple("pl061", 0x101e5000, pic[7]);
-    sysbus_create_simple("pl061", 0x101e6000, pic[8]);
-    sysbus_create_simple("pl061", 0x101e7000, pic[9]);
-
-    /* The versatile/PB actually has a modified Color LCD controller
-       that includes hardware cursor support from the PL111.  */
-    dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);
-    /* Wire up the mux control signals from the SYS_CLCD register */
-    qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
-
-    sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
-    sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
-
-    /* Add PL031 Real Time Clock. */
-    sysbus_create_simple("pl031", 0x101e8000, pic[10]);
-
-    dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
-    i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
-    i2c_create_slave(i2c, "ds1338", 0x68);
-
-    /* Add PL041 AACI Interface to the LM4549 codec */
-    pl041 = qdev_create(NULL, "pl041");
-    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
-    qdev_init_nofail(pl041);
-    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
-    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, sic[24]);
-
-    /* Memory map for Versatile/PB:  */
-    /* 0x10000000 System registers.  */
-    /* 0x10001000 PCI controller config registers.  */
-    /* 0x10002000 Serial bus interface.  */
-    /*  0x10003000 Secondary interrupt controller.  */
-    /* 0x10004000 AACI (audio).  */
-    /*  0x10005000 MMCI0.  */
-    /*  0x10006000 KMI0 (keyboard).  */
-    /*  0x10007000 KMI1 (mouse).  */
-    /* 0x10008000 Character LCD Interface.  */
-    /*  0x10009000 UART3.  */
-    /* 0x1000a000 Smart card 1.  */
-    /*  0x1000b000 MMCI1.  */
-    /*  0x10010000 Ethernet.  */
-    /* 0x10020000 USB.  */
-    /* 0x10100000 SSMC.  */
-    /* 0x10110000 MPMC.  */
-    /*  0x10120000 CLCD Controller.  */
-    /*  0x10130000 DMA Controller.  */
-    /*  0x10140000 Vectored interrupt controller.  */
-    /* 0x101d0000 AHB Monitor Interface.  */
-    /* 0x101e0000 System Controller.  */
-    /* 0x101e1000 Watchdog Interface.  */
-    /* 0x101e2000 Timer 0/1.  */
-    /* 0x101e3000 Timer 2/3.  */
-    /* 0x101e4000 GPIO port 0.  */
-    /* 0x101e5000 GPIO port 1.  */
-    /* 0x101e6000 GPIO port 2.  */
-    /* 0x101e7000 GPIO port 3.  */
-    /* 0x101e8000 RTC.  */
-    /* 0x101f0000 Smart card 0.  */
-    /*  0x101f1000 UART0.  */
-    /*  0x101f2000 UART1.  */
-    /*  0x101f3000 UART2.  */
-    /* 0x101f4000 SSPI.  */
-    /* 0x34000000 NOR Flash */
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash",
-                          VERSATILE_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
-                          VERSATILE_FLASH_SECT_SIZE,
-                          VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE,
-                          4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
-        fprintf(stderr, "qemu: Error registering flash memory.\n");
-    }
-
-    versatile_binfo.ram_size = args->ram_size;
-    versatile_binfo.kernel_filename = args->kernel_filename;
-    versatile_binfo.kernel_cmdline = args->kernel_cmdline;
-    versatile_binfo.initrd_filename = args->initrd_filename;
-    versatile_binfo.board_id = board_id;
-    arm_load_kernel(cpu, &versatile_binfo);
-}
-
-static void vpb_init(QEMUMachineInitArgs *args)
-{
-    versatile_init(args, 0x183);
-}
-
-static void vab_init(QEMUMachineInitArgs *args)
-{
-    versatile_init(args, 0x25e);
-}
-
-static QEMUMachine versatilepb_machine = {
-    .name = "versatilepb",
-    .desc = "ARM Versatile/PB (ARM926EJ-S)",
-    .init = vpb_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine versatileab_machine = {
-    .name = "versatileab",
-    .desc = "ARM Versatile/AB (ARM926EJ-S)",
-    .init = vab_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void versatile_machine_init(void)
-{
-    qemu_register_machine(&versatilepb_machine);
-    qemu_register_machine(&versatileab_machine);
-}
-
-machine_init(versatile_machine_init);
-
-static void vpb_sic_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = vpb_sic_init;
-    dc->no_user = 1;
-    dc->vmsd = &vmstate_vpb_sic;
-}
-
-static const TypeInfo vpb_sic_info = {
-    .name          = "versatilepb_sic",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(vpb_sic_state),
-    .class_init    = vpb_sic_class_init,
-};
-
-static void versatilepb_register_types(void)
-{
-    type_register_static(&vpb_sic_info);
-}
-
-type_init(versatilepb_register_types)
diff --git a/hw/vexpress.c b/hw/vexpress.c
deleted file mode 100644 (file)
index 741b044..0000000
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * ARM Versatile Express emulation.
- *
- * Copyright (c) 2010 - 2011 B Labs Ltd.
- * Copyright (c) 2011 Linaro Limited
- * Written by Bahadir Balban, Amit Mahajan, Peter Maydell
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- *
- *  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/>.
- *
- *  Contributions after 2012-01-13 are licensed under the terms of the
- *  GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "primecell.h"
-#include "devices.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "exec/address-spaces.h"
-#include "sysemu/blockdev.h"
-#include "flash.h"
-
-#define VEXPRESS_BOARD_ID 0x8e0
-#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
-#define VEXPRESS_FLASH_SECT_SIZE (256 * 1024)
-
-static struct arm_boot_info vexpress_binfo;
-
-/* Address maps for peripherals:
- * the Versatile Express motherboard has two possible maps,
- * the "legacy" one (used for A9) and the "Cortex-A Series"
- * map (used for newer cores).
- * Individual daughterboards can also have different maps for
- * their peripherals.
- */
-
-enum {
-    VE_SYSREGS,
-    VE_SP810,
-    VE_SERIALPCI,
-    VE_PL041,
-    VE_MMCI,
-    VE_KMI0,
-    VE_KMI1,
-    VE_UART0,
-    VE_UART1,
-    VE_UART2,
-    VE_UART3,
-    VE_WDT,
-    VE_TIMER01,
-    VE_TIMER23,
-    VE_SERIALDVI,
-    VE_RTC,
-    VE_COMPACTFLASH,
-    VE_CLCD,
-    VE_NORFLASH0,
-    VE_NORFLASH1,
-    VE_SRAM,
-    VE_VIDEORAM,
-    VE_ETHERNET,
-    VE_USB,
-    VE_DAPROM,
-};
-
-static hwaddr motherboard_legacy_map[] = {
-    /* CS7: 0x10000000 .. 0x10020000 */
-    [VE_SYSREGS] = 0x10000000,
-    [VE_SP810] = 0x10001000,
-    [VE_SERIALPCI] = 0x10002000,
-    [VE_PL041] = 0x10004000,
-    [VE_MMCI] = 0x10005000,
-    [VE_KMI0] = 0x10006000,
-    [VE_KMI1] = 0x10007000,
-    [VE_UART0] = 0x10009000,
-    [VE_UART1] = 0x1000a000,
-    [VE_UART2] = 0x1000b000,
-    [VE_UART3] = 0x1000c000,
-    [VE_WDT] = 0x1000f000,
-    [VE_TIMER01] = 0x10011000,
-    [VE_TIMER23] = 0x10012000,
-    [VE_SERIALDVI] = 0x10016000,
-    [VE_RTC] = 0x10017000,
-    [VE_COMPACTFLASH] = 0x1001a000,
-    [VE_CLCD] = 0x1001f000,
-    /* CS0: 0x40000000 .. 0x44000000 */
-    [VE_NORFLASH0] = 0x40000000,
-    /* CS1: 0x44000000 .. 0x48000000 */
-    [VE_NORFLASH1] = 0x44000000,
-    /* CS2: 0x48000000 .. 0x4a000000 */
-    [VE_SRAM] = 0x48000000,
-    /* CS3: 0x4c000000 .. 0x50000000 */
-    [VE_VIDEORAM] = 0x4c000000,
-    [VE_ETHERNET] = 0x4e000000,
-    [VE_USB] = 0x4f000000,
-};
-
-static hwaddr motherboard_aseries_map[] = {
-    /* CS0: 0x08000000 .. 0x0c000000 */
-    [VE_NORFLASH0] = 0x08000000,
-    /* CS4: 0x0c000000 .. 0x10000000 */
-    [VE_NORFLASH1] = 0x0c000000,
-    /* CS5: 0x10000000 .. 0x14000000 */
-    /* CS1: 0x14000000 .. 0x18000000 */
-    [VE_SRAM] = 0x14000000,
-    /* CS2: 0x18000000 .. 0x1c000000 */
-    [VE_VIDEORAM] = 0x18000000,
-    [VE_ETHERNET] = 0x1a000000,
-    [VE_USB] = 0x1b000000,
-    /* CS3: 0x1c000000 .. 0x20000000 */
-    [VE_DAPROM] = 0x1c000000,
-    [VE_SYSREGS] = 0x1c010000,
-    [VE_SP810] = 0x1c020000,
-    [VE_SERIALPCI] = 0x1c030000,
-    [VE_PL041] = 0x1c040000,
-    [VE_MMCI] = 0x1c050000,
-    [VE_KMI0] = 0x1c060000,
-    [VE_KMI1] = 0x1c070000,
-    [VE_UART0] = 0x1c090000,
-    [VE_UART1] = 0x1c0a0000,
-    [VE_UART2] = 0x1c0b0000,
-    [VE_UART3] = 0x1c0c0000,
-    [VE_WDT] = 0x1c0f0000,
-    [VE_TIMER01] = 0x1c110000,
-    [VE_TIMER23] = 0x1c120000,
-    [VE_SERIALDVI] = 0x1c160000,
-    [VE_RTC] = 0x1c170000,
-    [VE_COMPACTFLASH] = 0x1c1a0000,
-    [VE_CLCD] = 0x1c1f0000,
-};
-
-/* Structure defining the peculiarities of a specific daughterboard */
-
-typedef struct VEDBoardInfo VEDBoardInfo;
-
-typedef void DBoardInitFn(const VEDBoardInfo *daughterboard,
-                          ram_addr_t ram_size,
-                          const char *cpu_model,
-                          qemu_irq *pic, uint32_t *proc_id);
-
-struct VEDBoardInfo {
-    const hwaddr *motherboard_map;
-    hwaddr loader_start;
-    const hwaddr gic_cpu_if_addr;
-    DBoardInitFn *init;
-};
-
-static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
-                                  ram_addr_t ram_size,
-                                  const char *cpu_model,
-                                  qemu_irq *pic, uint32_t *proc_id)
-{
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *lowram = g_new(MemoryRegion, 1);
-    DeviceState *dev;
-    SysBusDevice *busdev;
-    qemu_irq *irqp;
-    int n;
-    qemu_irq cpu_irq[4];
-    ram_addr_t low_ram_size;
-
-    if (!cpu_model) {
-        cpu_model = "cortex-a9";
-    }
-
-    *proc_id = 0x0c000191;
-
-    for (n = 0; n < smp_cpus; n++) {
-        ARMCPU *cpu = cpu_arm_init(cpu_model);
-        if (!cpu) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        irqp = arm_pic_init_cpu(cpu);
-        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
-    }
-
-    if (ram_size > 0x40000000) {
-        /* 1GB is the maximum the address space permits */
-        fprintf(stderr, "vexpress-a9: cannot model more than 1GB RAM\n");
-        exit(1);
-    }
-
-    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
-    vmstate_register_ram_global(ram);
-    low_ram_size = ram_size;
-    if (low_ram_size > 0x4000000) {
-        low_ram_size = 0x4000000;
-    }
-    /* RAM is from 0x60000000 upwards. The bottom 64MB of the
-     * address space should in theory be remappable to various
-     * things including ROM or RAM; we always map the RAM there.
-     */
-    memory_region_init_alias(lowram, "vexpress.lowmem", ram, 0, low_ram_size);
-    memory_region_add_subregion(sysmem, 0x0, lowram);
-    memory_region_add_subregion(sysmem, 0x60000000, ram);
-
-    /* 0x1e000000 A9MPCore (SCU) private memory region */
-    dev = qdev_create(NULL, "a9mpcore_priv");
-    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0x1e000000);
-    for (n = 0; n < smp_cpus; n++) {
-        sysbus_connect_irq(busdev, n, cpu_irq[n]);
-    }
-    /* Interrupts [42:0] are from the motherboard;
-     * [47:43] are reserved; [63:48] are daughterboard
-     * peripherals. Note that some documentation numbers
-     * external interrupts starting from 32 (because the
-     * A9MP has internal interrupts 0..31).
-     */
-    for (n = 0; n < 64; n++) {
-        pic[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
-
-    /* 0x10020000 PL111 CLCD (daughterboard) */
-    sysbus_create_simple("pl111", 0x10020000, pic[44]);
-
-    /* 0x10060000 AXI RAM */
-    /* 0x100e0000 PL341 Dynamic Memory Controller */
-    /* 0x100e1000 PL354 Static Memory Controller */
-    /* 0x100e2000 System Configuration Controller */
-
-    sysbus_create_simple("sp804", 0x100e4000, pic[48]);
-    /* 0x100e5000 SP805 Watchdog module */
-    /* 0x100e6000 BP147 TrustZone Protection Controller */
-    /* 0x100e9000 PL301 'Fast' AXI matrix */
-    /* 0x100ea000 PL301 'Slow' AXI matrix */
-    /* 0x100ec000 TrustZone Address Space Controller */
-    /* 0x10200000 CoreSight debug APB */
-    /* 0x1e00a000 PL310 L2 Cache Controller */
-    sysbus_create_varargs("l2x0", 0x1e00a000, NULL);
-}
-
-static const VEDBoardInfo a9_daughterboard = {
-    .motherboard_map = motherboard_legacy_map,
-    .loader_start = 0x60000000,
-    .gic_cpu_if_addr = 0x1e000100,
-    .init = a9_daughterboard_init,
-};
-
-static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
-                                   ram_addr_t ram_size,
-                                   const char *cpu_model,
-                                   qemu_irq *pic, uint32_t *proc_id)
-{
-    int n;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    qemu_irq cpu_irq[4];
-    DeviceState *dev;
-    SysBusDevice *busdev;
-
-    if (!cpu_model) {
-        cpu_model = "cortex-a15";
-    }
-
-    *proc_id = 0x14000237;
-
-    for (n = 0; n < smp_cpus; n++) {
-        ARMCPU *cpu;
-        qemu_irq *irqp;
-
-        cpu = cpu_arm_init(cpu_model);
-        if (!cpu) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        irqp = arm_pic_init_cpu(cpu);
-        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
-    }
-
-    {
-        /* We have to use a separate 64 bit variable here to avoid the gcc
-         * "comparison is always false due to limited range of data type"
-         * warning if we are on a host where ram_addr_t is 32 bits.
-         */
-        uint64_t rsz = ram_size;
-        if (rsz > (30ULL * 1024 * 1024 * 1024)) {
-            fprintf(stderr, "vexpress-a15: cannot model more than 30GB RAM\n");
-            exit(1);
-        }
-    }
-
-    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
-    vmstate_register_ram_global(ram);
-    /* RAM is from 0x80000000 upwards; there is no low-memory alias for it. */
-    memory_region_add_subregion(sysmem, 0x80000000, ram);
-
-    /* 0x2c000000 A15MPCore private memory region (GIC) */
-    dev = qdev_create(NULL, "a15mpcore_priv");
-    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0x2c000000);
-    for (n = 0; n < smp_cpus; n++) {
-        sysbus_connect_irq(busdev, n, cpu_irq[n]);
-    }
-    /* Interrupts [42:0] are from the motherboard;
-     * [47:43] are reserved; [63:48] are daughterboard
-     * peripherals. Note that some documentation numbers
-     * external interrupts starting from 32 (because there
-     * are internal interrupts 0..31).
-     */
-    for (n = 0; n < 64; n++) {
-        pic[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    /* A15 daughterboard peripherals: */
-
-    /* 0x20000000: CoreSight interfaces: not modelled */
-    /* 0x2a000000: PL301 AXI interconnect: not modelled */
-    /* 0x2a420000: SCC: not modelled */
-    /* 0x2a430000: system counter: not modelled */
-    /* 0x2b000000: HDLCD controller: not modelled */
-    /* 0x2b060000: SP805 watchdog: not modelled */
-    /* 0x2b0a0000: PL341 dynamic memory controller: not modelled */
-    /* 0x2e000000: system SRAM */
-    memory_region_init_ram(sram, "vexpress.a15sram", 0x10000);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(sysmem, 0x2e000000, sram);
-
-    /* 0x7ffb0000: DMA330 DMA controller: not modelled */
-    /* 0x7ffd0000: PL354 static memory controller: not modelled */
-}
-
-static const VEDBoardInfo a15_daughterboard = {
-    .motherboard_map = motherboard_aseries_map,
-    .loader_start = 0x80000000,
-    .gic_cpu_if_addr = 0x2c002000,
-    .init = a15_daughterboard_init,
-};
-
-static void vexpress_common_init(const VEDBoardInfo *daughterboard,
-                                 QEMUMachineInitArgs *args)
-{
-    DeviceState *dev, *sysctl, *pl041;
-    qemu_irq pic[64];
-    uint32_t proc_id;
-    uint32_t sys_id;
-    DriveInfo *dinfo;
-    ram_addr_t vram_size, sram_size;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *vram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    const hwaddr *map = daughterboard->motherboard_map;
-
-    daughterboard->init(daughterboard, args->ram_size, args->cpu_model,
-                        pic, &proc_id);
-
-    /* Motherboard peripherals: the wiring is the same but the
-     * addresses vary between the legacy and A-Series memory maps.
-     */
-
-    sys_id = 0x1190f500;
-
-    sysctl = qdev_create(NULL, "realview_sysctl");
-    qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
-    qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
-    qdev_init_nofail(sysctl);
-    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]);
-
-    /* VE_SP810: not modelled */
-    /* VE_SERIALPCI: not modelled */
-
-    pl041 = qdev_create(NULL, "pl041");
-    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
-    qdev_init_nofail(pl041);
-    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, map[VE_PL041]);
-    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[11]);
-
-    dev = sysbus_create_varargs("pl181", map[VE_MMCI], pic[9], pic[10], NULL);
-    /* Wire up MMC card detect and read-only signals */
-    qdev_connect_gpio_out(dev, 0,
-                          qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT));
-    qdev_connect_gpio_out(dev, 1,
-                          qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN));
-
-    sysbus_create_simple("pl050_keyboard", map[VE_KMI0], pic[12]);
-    sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]);
-
-    sysbus_create_simple("pl011", map[VE_UART0], pic[5]);
-    sysbus_create_simple("pl011", map[VE_UART1], pic[6]);
-    sysbus_create_simple("pl011", map[VE_UART2], pic[7]);
-    sysbus_create_simple("pl011", map[VE_UART3], pic[8]);
-
-    sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
-    sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
-
-    /* VE_SERIALDVI: not modelled */
-
-    sysbus_create_simple("pl031", map[VE_RTC], pic[4]); /* RTC */
-
-    /* VE_COMPACTFLASH: not modelled */
-
-    sysbus_create_simple("pl111", map[VE_CLCD], pic[14]);
-
-    dinfo = drive_get_next(IF_PFLASH);
-    if (!pflash_cfi01_register(map[VE_NORFLASH0], NULL, "vexpress.flash0",
-            VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
-            VEXPRESS_FLASH_SECT_SIZE,
-            VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4,
-            0x00, 0x89, 0x00, 0x18, 0)) {
-        fprintf(stderr, "vexpress: error registering flash 0.\n");
-        exit(1);
-    }
-
-    dinfo = drive_get_next(IF_PFLASH);
-    if (!pflash_cfi01_register(map[VE_NORFLASH1], NULL, "vexpress.flash1",
-            VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
-            VEXPRESS_FLASH_SECT_SIZE,
-            VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4,
-            0x00, 0x89, 0x00, 0x18, 0)) {
-        fprintf(stderr, "vexpress: error registering flash 1.\n");
-        exit(1);
-    }
-
-    sram_size = 0x2000000;
-    memory_region_init_ram(sram, "vexpress.sram", sram_size);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(sysmem, map[VE_SRAM], sram);
-
-    vram_size = 0x800000;
-    memory_region_init_ram(vram, "vexpress.vram", vram_size);
-    vmstate_register_ram_global(vram);
-    memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram);
-
-    /* 0x4e000000 LAN9118 Ethernet */
-    if (nd_table[0].used) {
-        lan9118_init(&nd_table[0], map[VE_ETHERNET], pic[15]);
-    }
-
-    /* VE_USB: not modelled */
-
-    /* VE_DAPROM: not modelled */
-
-    vexpress_binfo.ram_size = args->ram_size;
-    vexpress_binfo.kernel_filename = args->kernel_filename;
-    vexpress_binfo.kernel_cmdline = args->kernel_cmdline;
-    vexpress_binfo.initrd_filename = args->initrd_filename;
-    vexpress_binfo.nb_cpus = smp_cpus;
-    vexpress_binfo.board_id = VEXPRESS_BOARD_ID;
-    vexpress_binfo.loader_start = daughterboard->loader_start;
-    vexpress_binfo.smp_loader_start = map[VE_SRAM];
-    vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
-    vexpress_binfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &vexpress_binfo);
-}
-
-static void vexpress_a9_init(QEMUMachineInitArgs *args)
-{
-    vexpress_common_init(&a9_daughterboard, args);
-}
-
-static void vexpress_a15_init(QEMUMachineInitArgs *args)
-{
-    vexpress_common_init(&a15_daughterboard, args);
-}
-
-static QEMUMachine vexpress_a9_machine = {
-    .name = "vexpress-a9",
-    .desc = "ARM Versatile Express for Cortex-A9",
-    .init = vexpress_a9_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine vexpress_a15_machine = {
-    .name = "vexpress-a15",
-    .desc = "ARM Versatile Express for Cortex-A15",
-    .init = vexpress_a15_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void vexpress_machine_init(void)
-{
-    qemu_register_machine(&vexpress_a9_machine);
-    qemu_register_machine(&vexpress_a15_machine);
-}
-
-machine_init(vexpress_machine_init);
index ad9ae360b2f6222c37f32592494657d8d2d7401f..288361d0fb9a1115d3ac267989c600716c232522 100644 (file)
@@ -31,9 +31,9 @@
 #include "exec/address-spaces.h"
 #include "sysemu/kvm.h"
 #include "exec/memory.h"
-#include "pci/msi.h"
-#include "pci/msix.h"
-#include "pci/pci.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
+#include "hw/pci/pci.h"
 #include "qemu-common.h"
 #include "qemu/error-report.h"
 #include "qemu/queue.h"
index 311c966f77adda164f00dbaed90b93fbc7253315..4aa62bf35efcc97103a3ee468125052450a4ab46 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "pc.h"
-#include "vga_int.h"
+#include "hw/pc.h"
+#include "hw/vga_int.h"
 #include "ui/pixel_ops.h"
 #include "qemu/timer.h"
 
index 762e45aaeb62adf28b6125e9f522b1b5ad03df8f..ffad5226fd445db312c078ae8e2e6b7a9c195faa 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "pc.h"
-#include "vga_int.h"
+#include "hw/pc.h"
+#include "hw/vga_int.h"
 #include "ui/pixel_ops.h"
 #include "qemu/timer.h"
-#include "loader.h"
+#include "hw/loader.h"
 
 typedef struct ISAVGAState {
     ISADevice dev;
index c491af20e4b5c9e0e82751ca19c7678f4e8e0e7c..18018ff1c318fcd40832a80c213431962ce60505 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "pci/pci.h"
-#include "vga_int.h"
+#include "hw/pci/pci.h"
+#include "hw/vga_int.h"
 #include "ui/pixel_ops.h"
 #include "qemu/timer.h"
-#include "loader.h"
+#include "hw/loader.h"
 
 #define PCI_VGA_IOPORT_OFFSET 0x400
 #define PCI_VGA_IOPORT_SIZE   (0x3e0 - 0x3c0)
index 1caf23d7b6561ea2d9ad47c064b56cf1b0e7a897..2213bc1a88d160326f4546d87e24a64cc277c662 100644 (file)
--- a/hw/vga.c
+++ b/hw/vga.c
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "vga.h"
+#include "hw/hw.h"
+#include "hw/vga.h"
 #include "ui/console.h"
-#include "pc.h"
-#include "pci/pci.h"
-#include "vga_int.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/vga_int.h"
 #include "ui/pixel_ops.h"
 #include "qemu/timer.h"
-#include "xen.h"
+#include "hw/xen.h"
 #include "trace.h"
 
 //#define DEBUG_VGA
@@ -986,28 +986,28 @@ typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
                                 const uint8_t *s, int width);
 
 #define DEPTH 8
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define DEPTH 15
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 15
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define DEPTH 16
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 16
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define DEPTH 32
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 32
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
 {
index 37777c267e7b9025abe6f82bb497eaf0f089c010..4d6aee3ecd819cc29d3ba29afa615584f9060df1 100644 (file)
@@ -14,7 +14,7 @@
  */
 
 #include <sys/ioctl.h>
-#include "vhost.h"
+#include "hw/vhost.h"
 #include "hw/hw.h"
 #include "qemu/range.h"
 #include <linux/vhost.h>
index d1df0e244757a5720714e7e48f1324d45d74f9eb..d3218a07f469469b53459b6887137959b1d197a2 100644 (file)
@@ -16,8 +16,8 @@
 #include "net/net.h"
 #include "net/tap.h"
 
-#include "virtio-net.h"
-#include "vhost_net.h"
+#include "hw/virtio-net.h"
+#include "hw/vhost_net.h"
 #include "qemu/error-report.h"
 
 #include "config.h"
@@ -36,7 +36,7 @@
 
 #include <stdio.h>
 
-#include "vhost.h"
+#include "hw/vhost.h"
 
 struct vhost_net {
     struct vhost_dev dev;
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
deleted file mode 100644 (file)
index 8c4e8e4..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Model of Xilinx Virtex5 ML507 PPC-440 refdesign.
- *
- * Copyright (c) 2010 Edgar E. Iglesias.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "hw.h"
-#include "serial.h"
-#include "flash.h"
-#include "sysemu/sysemu.h"
-#include "devices.h"
-#include "boards.h"
-#include "sysemu/device_tree.h"
-#include "loader.h"
-#include "elf.h"
-#include "qemu/log.h"
-#include "exec/address-spaces.h"
-
-#include "ppc.h"
-#include "ppc4xx.h"
-#include "ppc405.h"
-
-#include "sysemu/blockdev.h"
-#include "xilinx.h"
-
-#define EPAPR_MAGIC    (0x45504150)
-#define FLASH_SIZE     (16 * 1024 * 1024)
-
-static struct boot_info
-{
-    uint32_t bootstrap_pc;
-    uint32_t cmdline;
-    uint32_t fdt;
-    uint32_t ima_size;
-    void *vfdt;
-} boot_info;
-
-/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
-static void mmubooke_create_initial_mapping(CPUPPCState *env,
-                                     target_ulong va,
-                                     hwaddr pa)
-{
-    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
-
-    tlb->attr = 0;
-    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
-    tlb->size = 1 << 31; /* up to 0x80000000  */
-    tlb->EPN = va & TARGET_PAGE_MASK;
-    tlb->RPN = pa & TARGET_PAGE_MASK;
-    tlb->PID = 0;
-
-    tlb = &env->tlb.tlbe[1];
-    tlb->attr = 0;
-    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
-    tlb->size = 1 << 31; /* up to 0xffffffff  */
-    tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
-    tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
-    tlb->PID = 0;
-}
-
-static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
-                                      int do_init,
-                                      const char *cpu_model,
-                                      uint32_t sysclk)
-{
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    qemu_irq *irqs;
-
-    cpu = cpu_ppc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to initialize CPU!\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    ppc_booke_timers_init(cpu, sysclk, 0/* no flags */);
-
-    ppc_dcr_init(env, NULL, NULL);
-
-    /* interrupt controller */
-    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
-    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
-    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
-    ppcuic_init(env, irqs, 0x0C0, 0, 1);
-    return cpu;
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    struct boot_info *bi = env->load_info;
-
-    cpu_reset(CPU(cpu));
-    /* Linux Kernel Parameters (passing device tree):
-       *   r3: pointer to the fdt
-       *   r4: 0
-       *   r5: 0
-       *   r6: epapr magic
-       *   r7: size of IMA in bytes
-       *   r8: 0
-       *   r9: 0
-    */
-    env->gpr[1] = (16<<20) - 8;
-    /* Provide a device-tree.  */
-    env->gpr[3] = bi->fdt;
-    env->nip = bi->bootstrap_pc;
-
-    /* Create a mapping for the kernel.  */
-    mmubooke_create_initial_mapping(env, 0, 0);
-    env->gpr[6] = tswap32(EPAPR_MAGIC);
-    env->gpr[7] = bi->ima_size;
-}
-
-#define BINARY_DEVICE_TREE_FILE "virtex-ml507.dtb"
-static int xilinx_load_device_tree(hwaddr addr,
-                                      uint32_t ramsize,
-                                      hwaddr initrd_base,
-                                      hwaddr initrd_size,
-                                      const char *kernel_cmdline)
-{
-    char *path;
-    int fdt_size;
-#ifdef CONFIG_FDT
-    void *fdt;
-    int r;
-
-    /* Try the local "ppc.dtb" override.  */
-    fdt = load_device_tree("ppc.dtb", &fdt_size);
-    if (!fdt) {
-        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
-        if (path) {
-            fdt = load_device_tree(path, &fdt_size);
-            g_free(path);
-        }
-        if (!fdt) {
-            return 0;
-        }
-    }
-
-    r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
-    if (r < 0)
-        fprintf(stderr, "couldn't set /chosen/bootargs\n");
-    cpu_physical_memory_write (addr, (void *)fdt, fdt_size);
-#else
-    /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
-       to the kernel.  */
-    fdt_size = load_image_targphys("ppc.dtb", addr, 0x10000);
-    if (fdt_size < 0) {
-        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
-        if (path) {
-            fdt_size = load_image_targphys(path, addr, 0x10000);
-            g_free(path);
-        }
-    }
-
-    if (kernel_cmdline) {
-        fprintf(stderr,
-                "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
-    }
-#endif
-    return fdt_size;
-}
-
-static void virtex_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    MemoryRegion *address_space_mem = get_system_memory();
-    DeviceState *dev;
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    hwaddr ram_base = 0;
-    DriveInfo *dinfo;
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq irq[32], *cpu_irq;
-    int kernel_size;
-    int i;
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = "440-Xilinx";
-    }
-
-    cpu = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
-    env = &cpu->env;
-    qemu_register_reset(main_cpu_reset, cpu);
-
-    memory_region_init_ram(phys_ram, "ram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(0xfc000000, NULL, "virtex.flash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                          FLASH_SIZE >> 16,
-                          1, 0x89, 0x18, 0x0000, 0x0, 1);
-
-    cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT];
-    dev = xilinx_intc_create(0x81800000, cpu_irq[0], 0);
-    for (i = 0; i < 32; i++) {
-        irq[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    serial_mm_init(address_space_mem, 0x83e01003ULL, 2, irq[9], 115200,
-                   serial_hds[0], DEVICE_LITTLE_ENDIAN);
-
-    /* 2 timers at irq 2 @ 62 Mhz.  */
-    xilinx_timer_create(0x83c00000, irq[3], 0, 62 * 1000000);
-
-    if (kernel_filename) {
-        uint64_t entry, low, high;
-        hwaddr boot_offset;
-
-        /* Boots a kernel elf binary.  */
-        kernel_size = load_elf(kernel_filename, NULL, NULL,
-                               &entry, &low, &high, 1, ELF_MACHINE, 0);
-        boot_info.bootstrap_pc = entry & 0x00ffffff;
-
-        if (kernel_size < 0) {
-            boot_offset = 0x1200000;
-            /* If we failed loading ELF's try a raw image.  */
-            kernel_size = load_image_targphys(kernel_filename,
-                                              boot_offset,
-                                              ram_size);
-            boot_info.bootstrap_pc = boot_offset;
-            high = boot_info.bootstrap_pc + kernel_size + 8192;
-        }
-
-        boot_info.ima_size = kernel_size;
-
-        /* Provide a device-tree.  */
-        boot_info.fdt = high + (8192 * 2);
-        boot_info.fdt &= ~8191;
-        xilinx_load_device_tree(boot_info.fdt, ram_size, 0, 0, kernel_cmdline);
-    }
-    env->load_info = &boot_info;
-}
-
-static QEMUMachine virtex_machine = {
-    .name = "virtex-ml507",
-    .desc = "Xilinx Virtex ML507 reference design",
-    .init = virtex_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void virtex_machine_init(void)
-{
-    qemu_register_machine(&virtex_machine);
-}
-
-machine_init(virtex_machine_init);
index c0a790264c9742481d141c440c4b0701fa593c36..6bfcddc3799f2224391416e7d2b56f630bb73b5a 100644 (file)
 #include "qemu/iov.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
-#include "virtio.h"
-#include "pc.h"
+#include "hw/virtio.h"
+#include "hw/pc.h"
 #include "cpu.h"
 #include "sysemu/balloon.h"
-#include "virtio-balloon.h"
+#include "hw/virtio-balloon.h"
 #include "sysemu/kvm.h"
 #include "exec/address-spaces.h"
 #include "qapi/visitor.h"
index b1828f4a48587f25273cccaca08ea821669c5542..f37f31b4d76ebb5c20efe0accf81def23b8b3f10 100644 (file)
@@ -15,8 +15,8 @@
 #ifndef _QEMU_VIRTIO_BALLOON_H
 #define _QEMU_VIRTIO_BALLOON_H
 
-#include "virtio.h"
-#include "pci/pci.h"
+#include "hw/virtio.h"
+#include "hw/pci/pci.h"
 
 /* from Linux's linux/virtio_balloon.h */
 
index f5e6ee90b62cd7542027509ee970be213a29f5bf..6b6923665519301d3baa9351610cf5024c1355ba 100644 (file)
 #include "trace.h"
 #include "hw/block-common.h"
 #include "sysemu/blockdev.h"
-#include "virtio-blk.h"
+#include "hw/virtio-blk.h"
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-#include "hw/dataplane/virtio-blk.h"
+#include "dataplane/virtio-blk.h"
 #endif
-#include "scsi-defs.h"
+#include "hw/scsi-defs.h"
 #ifdef __linux__
 # include <scsi/sg.h>
 #endif
index 43ca4920808e6d09b966e356a8924afae9c50f43..7ef2f35852831e98229122f4c1a9f0dafb9c1356 100644 (file)
@@ -14,7 +14,7 @@
 #ifndef _QEMU_VIRTIO_BLK_H
 #define _QEMU_VIRTIO_BLK_H
 
-#include "virtio.h"
+#include "hw/virtio.h"
 #include "hw/block-common.h"
 
 /* from Linux's linux/virtio_blk.h */
index 6045d8ad86a4cb0e9b11bbfc96eeb6b42efda5d0..6c2aab00eb1ca1095263608800f70c5f5182bd5d 100644 (file)
  *
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/error-report.h"
-#include "qdev.h"
-#include "virtio-bus.h"
-#include "virtio.h"
+#include "hw/qdev.h"
+#include "hw/virtio-bus.h"
+#include "hw/virtio.h"
 
 /* #define DEBUG_VIRTIO_BUS */
 
index 7584a0e6ae3c7fed9bcb22616fb9a3717b6ea282..ae0f7078b4631e3d87654c413c226e6c062d8c17 100644 (file)
@@ -25,9 +25,9 @@
 #ifndef VIRTIO_BUS_H
 #define VIRTIO_BUS_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "sysemu/sysemu.h"
-#include "virtio.h"
+#include "hw/virtio.h"
 
 #define TYPE_VIRTIO_BUS "virtio-bus"
 #define VIRTIO_BUS_GET_CLASS(obj) \
index 194de6431e0ea2b2cc8ffaa4a370c4bb15eb2093..e2d1c58d9da92bac3f59e3727265362c22ac94c0 100644 (file)
@@ -13,7 +13,7 @@
 #include "char/char.h"
 #include "qemu/error-report.h"
 #include "trace.h"
-#include "virtio-serial.h"
+#include "hw/virtio-serial.h"
 
 typedef struct VirtConsole {
     VirtIOSerialPort port;
index bb2c26c4833303f132916ff2ce89557519770690..8c9d8713f3f3a7fe0817d8a649da37e93e31fa2e 100644 (file)
  */
 
 #include "qemu/iov.h"
-#include "virtio.h"
+#include "hw/virtio.h"
 #include "net/net.h"
 #include "net/checksum.h"
 #include "net/tap.h"
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
-#include "virtio-net.h"
-#include "vhost_net.h"
+#include "hw/virtio-net.h"
+#include "hw/vhost_net.h"
 
 #define VIRTIO_NET_VM_VERSION    11
 
index e654c13a9fced65d63cfdf01244692cd7b79929e..0c83ca5cfe7267a15ccc90479000b6ab2229520a 100644 (file)
@@ -14,8 +14,8 @@
 #ifndef _QEMU_VIRTIO_NET_H
 #define _QEMU_VIRTIO_NET_H
 
-#include "virtio.h"
-#include "pci/pci.h"
+#include "hw/virtio.h"
+#include "hw/pci/pci.h"
 
 #define ETH_ALEN    6
 
index ba56ab2d77b52772039729c170700a043fee05a3..39c1966cfc1064f4a8a6cd274883d6f182c1adf0 100644 (file)
 
 #include <inttypes.h>
 
-#include "virtio.h"
-#include "virtio-blk.h"
-#include "virtio-net.h"
-#include "virtio-serial.h"
-#include "virtio-scsi.h"
-#include "pci/pci.h"
+#include "hw/virtio.h"
+#include "hw/virtio-blk.h"
+#include "hw/virtio-net.h"
+#include "hw/virtio-serial.h"
+#include "hw/virtio-scsi.h"
+#include "hw/pci/pci.h"
 #include "qemu/error-report.h"
-#include "pci/msi.h"
-#include "pci/msix.h"
-#include "loader.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
+#include "hw/loader.h"
 #include "sysemu/kvm.h"
 #include "sysemu/blockdev.h"
-#include "virtio-pci.h"
+#include "hw/virtio-pci.h"
 #include "qemu/range.h"
-#include "virtio-bus.h"
+#include "hw/virtio-bus.h"
 
 /* from Linux's linux/virtio_pci.h */
 
@@ -255,7 +255,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
     proxy->ioeventfd_started = false;
 }
 
-void virtio_pci_reset(DeviceState *d)
+static void virtio_pci_reset(DeviceState *d)
 {
     VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
     virtio_pci_stop_ioeventfd(proxy);
@@ -1316,6 +1316,51 @@ static const TypeInfo virtio_scsi_info = {
     .class_init    = virtio_scsi_class_init,
 };
 
+#ifdef CONFIG_VIRTFS
+static int virtio_9p_init_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    VirtIODevice *vdev;
+
+    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
+    vdev->nvectors = proxy->nvectors;
+    virtio_init_pci(proxy, vdev);
+    /* make the actual value visible */
+    proxy->nvectors = vdev->nvectors;
+    return 0;
+}
+
+static Property virtio_9p_properties[] = {
+    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
+    DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_9p_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_9p_init_pci;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = PCI_DEVICE_ID_VIRTIO_9P;
+    k->revision = VIRTIO_PCI_ABI_VERSION;
+    k->class_id = 0x2;
+    dc->props = virtio_9p_properties;
+    dc->reset = virtio_pci_reset;
+}
+
+static const TypeInfo virtio_9p_info = {
+    .name          = "virtio-9p-pci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(VirtIOPCIProxy),
+    .class_init    = virtio_9p_class_init,
+};
+#endif
+
 /*
  * virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
  */
@@ -1478,6 +1523,9 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_rng_info);
     type_register_static(&virtio_pci_bus_info);
     type_register_static(&virtio_pci_info);
+#ifdef CONFIG_VIRTFS
+    type_register_static(&virtio_9p_info);
+#endif
 }
 
 type_init(virtio_pci_register_types)
index d24957cc25493dbf48b13e78afca0f3cca8e828c..2ae96f84d66dda8dbce31e2e338959d9b8fd72b3 100644 (file)
 #define QEMU_VIRTIO_PCI_H
 
 #include "hw/pci/msi.h"
-#include "virtio-blk.h"
-#include "virtio-net.h"
-#include "virtio-rng.h"
-#include "virtio-serial.h"
-#include "virtio-scsi.h"
-#include "virtio-bus.h"
+#include "hw/virtio-blk.h"
+#include "hw/virtio-net.h"
+#include "hw/virtio-rng.h"
+#include "hw/virtio-serial.h"
+#include "hw/virtio-scsi.h"
+#include "hw/virtio-bus.h"
+#include "hw/9pfs/virtio-9p-device.h"
 
 typedef struct VirtIOPCIProxy VirtIOPCIProxy;
 
@@ -75,7 +76,7 @@ struct VirtIOPCIProxy {
     VirtIOBlkConf blk;
     NICConf nic;
     uint32_t host_features;
-#ifdef CONFIG_LINUX
+#ifdef CONFIG_VIRTFS
     V9fsConf fsconf;
 #endif
     virtio_serial_conf serial;
@@ -90,7 +91,6 @@ struct VirtIOPCIProxy {
 };
 
 void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
-void virtio_pci_reset(DeviceState *d);
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev);
 
 /* Virtio ABI version, if we increment this, we break the guest driver. */
index e063127df638801f7283de5faaa49639eb618db3..54c1421f86dd712676ebb2fa55ba2ab4bbdebcf6 100644 (file)
  */
 
 #include "qemu/iov.h"
-#include "qdev.h"
-#include "virtio.h"
-#include "virtio-rng.h"
+#include "hw/qdev.h"
+#include "qapi/qmp/qerror.h"
+#include "hw/virtio.h"
+#include "hw/virtio-rng.h"
 #include "qemu/rng.h"
 
 typedef struct VirtIORNG {
index 0715865489a351ad2e6293c524267cbf561b55fd..72cc5198d4b5a4c856b6ebd0fa04877d709eb76e 100644 (file)
@@ -13,7 +13,8 @@
  *
  */
 
-#include "virtio-scsi.h"
+#include "hw/virtio-scsi.h"
+#include "qemu/error-report.h"
 #include <hw/scsi.h>
 #include <hw/scsi-defs.h>
 
index 8d9d15f0939bb95303e508a3f6863164050f4aa7..81b3279a574555246b98e91e7615f64fd2d90d07 100644 (file)
@@ -14,8 +14,8 @@
 #ifndef _QEMU_VIRTIO_SCSI_H
 #define _QEMU_VIRTIO_SCSI_H
 
-#include "virtio.h"
-#include "pci/pci.h"
+#include "hw/virtio.h"
+#include "hw/pci/pci.h"
 
 /* The ID for virtio_scsi */
 #define VIRTIO_ID_SCSI  8
index f76c5058ba60af6ccd6c6740a9f744b669443628..7d0515f551fa1d1d49c591a1dc879a2fdd43ff5a 100644 (file)
@@ -21,9 +21,9 @@
 #include "qemu/iov.h"
 #include "monitor/monitor.h"
 #include "qemu/queue.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
-#include "virtio-serial.h"
+#include "hw/virtio-serial.h"
 
 /* The virtio-serial bus on top of which the ports will ride as devices */
 struct VirtIOSerialBus {
index 16e39820a237f14b44ff1fd6f0a79a6a86ddb127..d2d9fb773e2296ed87ad28ec3fc4b99c0bd22d06 100644 (file)
@@ -15,8 +15,8 @@
 #ifndef _QEMU_VIRTIO_SERIAL_H
 #define _QEMU_VIRTIO_SERIAL_H
 
-#include "qdev.h"
-#include "virtio.h"
+#include "hw/qdev.h"
+#include "hw/virtio.h"
 
 /* == Interface shared between the guest kernel and qemu == */
 
index e2593485187cd9d63a1535a74fdb016b2a5c6aad..26fbc790ecd999842129f25d0d9f824e2d772edc 100644 (file)
@@ -15,9 +15,9 @@
 
 #include "trace.h"
 #include "qemu/error-report.h"
-#include "virtio.h"
+#include "hw/virtio.h"
 #include "qemu/atomic.h"
-#include "virtio-bus.h"
+#include "hw/virtio-bus.h"
 
 /* The alignment to use between consumer and producer parts of vring.
  * x86 pagesize again. */
index 1e206b83551d8d47a63f19d71ace0952e87c6fde..ca43fd70cd931ade51198cc2f1ea6a384d0894f7 100644 (file)
 #ifndef _QEMU_VIRTIO_H
 #define _QEMU_VIRTIO_H
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "net/net.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "sysemu/sysemu.h"
 #include "qemu/event_notifier.h"
-#ifdef CONFIG_LINUX
-#include "9p.h"
+#ifdef CONFIG_VIRTFS
+#include "hw/9pfs/virtio-9p-device.h"
 #endif
 
 /* from Linux's linux/virtio_config.h */
@@ -252,7 +252,7 @@ typedef struct VirtIOSCSIConf VirtIOSCSIConf;
 VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *conf);
 typedef struct VirtIORNGConf VirtIORNGConf;
 VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf);
-#ifdef CONFIG_LINUX
+#ifdef CONFIG_VIRTFS
 VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
 #endif
 
index b9afc2c4e8bd03b213ee6d3c655a068708408e32..a9d227e17d42c030960ca360859fdc672e44480d 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "ps2.h"
-#include "pc.h"
-#include "qdev.h"
+#include "hw/ps2.h"
+#include "hw/pc.h"
+#include "hw/qdev.h"
 
 /* debug only vmmouse */
 //#define DEBUG_VMMOUSE
index faead3a955a43cb67d4cf043c5cf2fc5078857ef..cc1466ae967769e0759bb17f50bf99e2d71e5b7e 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "isa.h"
-#include "pc.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
+#include "hw/pc.h"
 #include "sysemu/kvm.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 
 //#define VMPORT_DEBUG
 
index 8fc201bfb96ed54f1ff28aa7750f9b44095364db..db2f187e5635f92acf3e32caf05b9cdbd1a5496f 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "loader.h"
+#include "hw/hw.h"
+#include "hw/loader.h"
 #include "ui/console.h"
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 
 #undef VERBOSE
 #define HW_RECT_ACCEL
 #define HW_FILL_ACCEL
 #define HW_MOUSE_ACCEL
 
-#include "vga_int.h"
+#include "hw/vga_int.h"
 
 /* See http://vmware-svga.sf.net/ for some documentation on VMWare SVGA */
 
index 2d8e3988dbb25e02011cda3ef48c7cd7a5881d73..452950826c648e38c835e50545706e0c23aed698 100644 (file)
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "vt82c686.h"
-#include "i2c.h"
-#include "smbus.h"
-#include "pci/pci.h"
-#include "isa.h"
-#include "sysbus.h"
-#include "mips.h"
-#include "apm.h"
-#include "acpi.h"
-#include "pm_smbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/vt82c686.h"
+#include "hw/i2c.h"
+#include "hw/smbus.h"
+#include "hw/pci/pci.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
+#include "hw/mips.h"
+#include "hw/apm.h"
+#include "hw/acpi.h"
+#include "hw/pm_smbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/timer.h"
 #include "exec/address-spaces.h"
 
-typedef uint32_t pci_addr_t;
-#include "pci/pci_host.h"
 //#define DEBUG_VT82C686B
 
 #ifdef DEBUG_VT82C686B
index 37ce362811f294768887dd4ed629489d17e2bfc4..f13e507fcff3d65a74a3d0b08ba4d72270349cd0 100644 (file)
@@ -23,9 +23,9 @@
 
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "watchdog.h"
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/watchdog.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 
 /*#define I6300ESB_DEBUG 1*/
 
index 599a86f5f63fe00a00e7a4cb7de663ab13a38fa6..6c52808ac0425694ef4154dc5a2a5a8a158557ef 100644 (file)
 
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "watchdog.h"
-#include "hw.h"
-#include "isa.h"
-#include "pc.h"
+#include "hw/watchdog.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
+#include "hw/pc.h"
 
 /*#define IB700_DEBUG 1*/
 
index d3ea5ba8f5fed427bb2d35414828254b121df449..0904cf496df9dfe8fb59e5ba00752fc7b071341a 100644 (file)
@@ -7,8 +7,8 @@
  * This file is licensed under GNU GPL.
  */
 
-#include "hw.h"
-#include "i2c.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
 #include "audio/audio.h"
 
 #define IN_PORT_N      3
index 743b37b99109fd7c39e95be7f86abf9b259b5a1c..ff2e876b3d5e0ca6012694c240f98884d310837f 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include "qemu-common.h"
-#include "xen-host-pci-device.h"
+#include "hw/xen-host-pci-device.h"
 
 #define XEN_HOST_PCI_MAX_EXT_CAP \
     ((PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE) / (PCI_CAP_SIZEOF + 4))
index 942b24dccc1098ca10e391cb268ffb08dcab09cb..c2486f0c19a7300fd2b18a26ba71153032dfbee5 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef XEN_HOST_PCI_DEVICE_H
 #define XEN_HOST_PCI_DEVICE_H
 
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 
 enum {
     XEN_HOST_PCI_REGION_TYPE_IO = 1 << 1,
index 1d1d15c289c68baee0e45f7bf18f92562f96630d..8f387b64033fda474184213f51702c2a6a7cc33c 100644 (file)
@@ -11,7 +11,7 @@
  */
 #include "hw/apic_internal.h"
 #include "hw/pci/msi.h"
-#include "xen.h"
+#include "hw/xen.h"
 
 static uint64_t xen_apic_mem_read(void *opaque, hwaddr addr,
                                   unsigned size)
index 3fa30098ca55379691a23f74170c795543f785da..24381b55e58575644aba56feb0e3159638136fff 100644 (file)
 #include <sys/mman.h>
 #include <sys/signal.h>
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "char/char.h"
 #include "qemu/log.h"
-#include "xen_backend.h"
+#include "hw/xen_backend.h"
 
 #include <xen/grant_table.h>
 
index f37afb1f05837bfd97f72ee6f4f7a7a7fb11c628..6d5c699c51c564223f05cacb43b362159b7e5d53 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef QEMU_HW_XEN_BACKEND_H
 #define QEMU_HW_XEN_BACKEND_H 1
 
-#include "xen_common.h"
+#include "hw/xen_common.h"
 #include "sysemu/sysemu.h"
 #include "net/net.h"
 
index 95bc9a7825b748c2763df82062bd2cf4904a6ae9..c37bde3f7e0bceadb68bae5d9a7222ec588bc014 100644 (file)
@@ -14,8 +14,8 @@
 #endif
 #include <xen/io/xenbus.h>
 
-#include "hw.h"
-#include "xen.h"
+#include "hw/hw.h"
+#include "hw/xen.h"
 #include "qemu/queue.h"
 
 /*
index 44141f8692a05b0973d1742093054e8bdbc65060..a8db6f8d8f109d47e4a75314861ceedbe9ec6562 100644 (file)
@@ -29,9 +29,9 @@
 #include <stdarg.h>
 #include <sys/mman.h>
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "char/char.h"
-#include "xen_backend.h"
+#include "hw/xen_backend.h"
 
 #include <xen/io/console.h>
 
index e2ba741d54251d9d82ed3675d0d76b4320670c68..cdcaf62f26f81e452c3afd3d060bc60a7f29526b 100644 (file)
@@ -1,4 +1,4 @@
-#include "xen_backend.h"
+#include "hw/xen_backend.h"
 #include "sysemu/blockdev.h"
 
 /* ------------------------------------------------------------- */
index 7fea87156d733b41cd51e047e2c41c2fc8ffdd7b..cc09a2f1fa20bbd76d78c7513b5be7a1c52a0995 100644 (file)
@@ -35,9 +35,9 @@
 #include <sys/mman.h>
 #include <sys/uio.h>
 
-#include "hw.h"
-#include "xen_backend.h"
-#include "xen_blkif.h"
+#include "hw/hw.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_blkif.h"
 #include "sysemu/blockdev.h"
 
 /* ------------------------------------------------------------- */
diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c
deleted file mode 100644 (file)
index a4272f0..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-#include <signal.h>
-#include "xen_backend.h"
-#include "xen_domainbuild.h"
-#include "qemu/timer.h"
-#include "qemu/log.h"
-
-#include <xenguest.h>
-
-static int xenstore_domain_mkdir(char *path)
-{
-    struct xs_permissions perms_ro[] = {{
-            .id    = 0, /* set owner: dom0 */
-        },{
-            .id    = xen_domid,
-            .perms = XS_PERM_READ,
-        }};
-    struct xs_permissions perms_rw[] = {{
-            .id    = 0, /* set owner: dom0 */
-        },{
-            .id    = xen_domid,
-            .perms = XS_PERM_READ | XS_PERM_WRITE,
-        }};
-    const char *writable[] = { "device", "control", "error", NULL };
-    char subpath[256];
-    int i;
-
-    if (!xs_mkdir(xenstore, 0, path)) {
-        fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
-       return -1;
-    }
-    if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) {
-        fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
-       return -1;
-    }
-
-    for (i = 0; writable[i]; i++) {
-        snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]);
-        if (!xs_mkdir(xenstore, 0, subpath)) {
-            fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
-            return -1;
-        }
-        if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
-            fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
-            return -1;
-        }
-    }
-    return 0;
-}
-
-int xenstore_domain_init1(const char *kernel, const char *ramdisk,
-                          const char *cmdline)
-{
-    char *dom, uuid_string[42], vm[256], path[256];
-    int i;
-
-    snprintf(uuid_string, sizeof(uuid_string), UUID_FMT,
-             qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3],
-             qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
-             qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
-             qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
-    dom = xs_get_domain_path(xenstore, xen_domid);
-    snprintf(vm,  sizeof(vm),  "/vm/%s", uuid_string);
-
-    xenstore_domain_mkdir(dom);
-
-    xenstore_write_str(vm, "image/ostype",  "linux");
-    if (kernel)
-        xenstore_write_str(vm, "image/kernel",  kernel);
-    if (ramdisk)
-        xenstore_write_str(vm, "image/ramdisk", ramdisk);
-    if (cmdline)
-        xenstore_write_str(vm, "image/cmdline", cmdline);
-
-    /* name + id */
-    xenstore_write_str(vm,  "name",   qemu_name ? qemu_name : "no-name");
-    xenstore_write_str(vm,  "uuid",   uuid_string);
-    xenstore_write_str(dom, "name",   qemu_name ? qemu_name : "no-name");
-    xenstore_write_int(dom, "domid",  xen_domid);
-    xenstore_write_str(dom, "vm",     vm);
-
-    /* memory */
-    xenstore_write_int(dom, "memory/target", ram_size >> 10);  // kB
-    xenstore_write_int(vm, "memory",         ram_size >> 20);  // MB
-    xenstore_write_int(vm, "maxmem",         ram_size >> 20);  // MB
-
-    /* cpus */
-    for (i = 0; i < smp_cpus; i++) {
-       snprintf(path, sizeof(path), "cpu/%d/availability",i);
-       xenstore_write_str(dom, path, "online");
-    }
-    xenstore_write_int(vm, "vcpu_avail",  smp_cpus);
-    xenstore_write_int(vm, "vcpus",       smp_cpus);
-
-    /* vnc password */
-    xenstore_write_str(vm, "vncpassword", "" /* FIXME */);
-
-    free(dom);
-    return 0;
-}
-
-int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
-                          int console_port, int console_mfn)
-{
-    char *dom;
-
-    dom = xs_get_domain_path(xenstore, xen_domid);
-
-    /* signal new domain */
-    xs_introduce_domain(xenstore,
-                        xen_domid,
-                        xenstore_mfn,
-                        xenstore_port);
-
-    /* xenstore */
-    xenstore_write_int(dom, "store/ring-ref",   xenstore_mfn);
-    xenstore_write_int(dom, "store/port",       xenstore_port);
-
-    /* console */
-    xenstore_write_str(dom, "console/type",     "ioemu");
-    xenstore_write_int(dom, "console/limit",    128 * 1024);
-    xenstore_write_int(dom, "console/ring-ref", console_mfn);
-    xenstore_write_int(dom, "console/port",     console_port);
-    xen_config_dev_console(0);
-
-    free(dom);
-    return 0;
-}
-
-/* ------------------------------------------------------------- */
-
-static QEMUTimer *xen_poll;
-
-/* check domain state once per second */
-static void xen_domain_poll(void *opaque)
-{
-    struct xc_dominfo info;
-    int rc;
-
-    rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info);
-    if ((rc != 1) || (info.domid != xen_domid)) {
-        qemu_log("xen: domain %d is gone\n", xen_domid);
-        goto quit;
-    }
-    if (info.dying) {
-        qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid,
-                 info.crashed  ? "crashed"  : "",
-                 info.shutdown ? "shutdown" : "");
-        goto quit;
-    }
-
-    qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
-    return;
-
-quit:
-    qemu_system_shutdown_request();
-}
-
-static int xen_domain_watcher(void)
-{
-    int qemu_running = 1;
-    int fd[2], i, n, rc;
-    char byte;
-
-    if (pipe(fd) != 0) {
-        qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno));
-        return -1;
-    }
-    if (fork() != 0)
-        return 0; /* not child */
-
-    /* close all file handles, except stdio/out/err,
-     * our watch pipe and the xen interface handle */
-    n = getdtablesize();
-    for (i = 3; i < n; i++) {
-        if (i == fd[0])
-            continue;
-        if (i == xc_fd(xen_xc)) {
-            continue;
-        }
-        close(i);
-    }
-
-    /* ignore term signals */
-    signal(SIGINT,  SIG_IGN);
-    signal(SIGTERM, SIG_IGN);
-
-    /* wait for qemu exiting */
-    while (qemu_running) {
-        rc = read(fd[0], &byte, 1);
-        switch (rc) {
-        case -1:
-            if (errno == EINTR)
-                continue;
-            qemu_log("%s: Huh? read error: %s\n", __FUNCTION__, strerror(errno));
-            qemu_running = 0;
-            break;
-        case 0:
-            /* EOF -> qemu exited */
-            qemu_running = 0;
-            break;
-        default:
-            qemu_log("%s: Huh? data on the watch pipe?\n", __FUNCTION__);
-            break;
-        }
-    }
-
-    /* cleanup */
-    qemu_log("%s: destroy domain %d\n", __FUNCTION__, xen_domid);
-    xc_domain_destroy(xen_xc, xen_domid);
-    _exit(0);
-}
-
-/* normal cleanup */
-static void xen_domain_cleanup(void)
-{
-    char *dom;
-
-    dom = xs_get_domain_path(xenstore, xen_domid);
-    if (dom) {
-        xs_rm(xenstore, 0, dom);
-        free(dom);
-    }
-    xs_release_domain(xenstore, xen_domid);
-}
-
-int xen_domain_build_pv(const char *kernel, const char *ramdisk,
-                        const char *cmdline)
-{
-    uint32_t ssidref = 0;
-    uint32_t flags = 0;
-    xen_domain_handle_t uuid;
-    unsigned int xenstore_port = 0, console_port = 0;
-    unsigned long xenstore_mfn = 0, console_mfn = 0;
-    int rc;
-
-    memcpy(uuid, qemu_uuid, sizeof(uuid));
-    rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_create() failed\n");
-        goto err;
-    }
-    qemu_log("xen: created domain %d\n", xen_domid);
-    atexit(xen_domain_cleanup);
-    if (xen_domain_watcher() == -1) {
-        goto err;
-    }
-
-    xenstore_domain_init1(kernel, ramdisk, cmdline);
-
-    rc = xc_domain_max_vcpus(xen_xc, xen_domid, smp_cpus);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_max_vcpus() failed\n");
-        goto err;
-    }
-
-#if 0
-    rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n");
-        goto err;
-    }
-#endif
-
-    rc = xc_domain_setmaxmem(xen_xc, xen_domid, ram_size >> 10);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_setmaxmem() failed\n");
-        goto err;
-    }
-
-    xenstore_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
-    console_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
-
-    rc = xc_linux_build(xen_xc, xen_domid, ram_size >> 20,
-                        kernel, ramdisk, cmdline,
-                        0, flags,
-                        xenstore_port, &xenstore_mfn,
-                        console_port, &console_mfn);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_linux_build() failed\n");
-        goto err;
-    }
-
-    xenstore_domain_init2(xenstore_port, xenstore_mfn,
-                          console_port, console_mfn);
-
-    qemu_log("xen: unpausing domain %d\n", xen_domid);
-    rc = xc_domain_unpause(xen_xc, xen_domid);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_unpause() failed\n");
-        goto err;
-    }
-
-    xen_poll = qemu_new_timer_ms(rt_clock, xen_domain_poll, NULL);
-    qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
-    return 0;
-
-err:
-    return -1;
-}
index dea0121868c086a4dca7bf7056e7f7ed8f19c44a..681cbe5fd8d8f2b69c3ba3bd51ab0eeea5e8722e 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef QEMU_HW_XEN_DOMAINBUILD_H
 #define QEMU_HW_XEN_DOMAINBUILD_H 1
 
-#include "xen_common.h"
+#include "hw/xen_common.h"
 
 int xenstore_domain_init1(const char *kernel, const char *ramdisk,
                           const char *cmdline);
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
deleted file mode 100644 (file)
index 66e8981..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * QEMU Xen PV Machine
- *
- * Copyright (c) 2007 Red Hat
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw.h"
-#include "pc.h"
-#include "boards.h"
-#include "xen_backend.h"
-#include "xen_domainbuild.h"
-#include "sysemu/blockdev.h"
-
-static void xen_init_pv(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    X86CPU *cpu;
-    CPUX86State *env;
-    DriveInfo *dinfo;
-    int i;
-
-    /* Initialize a dummy CPU */
-    if (cpu_model == NULL) {
-#ifdef TARGET_X86_64
-        cpu_model = "qemu64";
-#else
-        cpu_model = "qemu32";
-#endif
-    }
-    cpu = cpu_x86_init(cpu_model);
-    env = &cpu->env;
-    env->halted = 1;
-
-    /* Initialize backend core & drivers */
-    if (xen_be_init() != 0) {
-        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
-        exit(1);
-    }
-
-    switch (xen_mode) {
-    case XEN_ATTACH:
-        /* nothing to do, xend handles everything */
-        break;
-    case XEN_CREATE:
-        if (xen_domain_build_pv(kernel_filename, initrd_filename,
-                                kernel_cmdline) < 0) {
-            fprintf(stderr, "xen pv domain creation failed\n");
-            exit(1);
-        }
-        break;
-    case XEN_EMULATE:
-        fprintf(stderr, "xen emulation not implemented (yet)\n");
-        exit(1);
-        break;
-    }
-
-    xen_be_register("console", &xen_console_ops);
-    xen_be_register("vkbd", &xen_kbdmouse_ops);
-    xen_be_register("vfb", &xen_framebuffer_ops);
-    xen_be_register("qdisk", &xen_blkdev_ops);
-    xen_be_register("qnic", &xen_netdev_ops);
-
-    /* configure framebuffer */
-    if (xenfb_enabled) {
-        xen_config_dev_vfb(0, "vnc");
-        xen_config_dev_vkbd(0);
-    }
-
-    /* configure disks */
-    for (i = 0; i < 16; i++) {
-        dinfo = drive_get(IF_XEN, 0, i);
-        if (!dinfo)
-            continue;
-        xen_config_dev_blk(dinfo);
-    }
-
-    /* configure nics */
-    for (i = 0; i < nb_nics; i++) {
-        if (!nd_table[i].model || 0 != strcmp(nd_table[i].model, "xen"))
-            continue;
-        xen_config_dev_nic(nd_table + i);
-    }
-
-    /* config cleanup hook */
-    atexit(xen_config_cleanup);
-
-    /* setup framebuffer */
-    xen_init_display(xen_domid);
-}
-
-static QEMUMachine xenpv_machine = {
-    .name = "xenpv",
-    .desc = "Xen Para-virtualized PC",
-    .init = xen_init_pv,
-    .max_cpus = 1,
-    .default_machine_opts = "accel=xen",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void xenpv_machine_init(void)
-{
-    qemu_register_machine(&xenpv_machine);
-}
-
-machine_init(xenpv_machine_init);
index 34961c287a3a494c6bc6ca932aa9f380864a594f..b6d36793b35e15e8ec01badd195abecee3a3afd4 100644 (file)
 #include <sys/mman.h>
 #include <sys/wait.h>
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "net/net.h"
 #include "net/checksum.h"
 #include "net/util.h"
-#include "xen_backend.h"
+#include "hw/xen_backend.h"
 
 #include <xen/io/netif.h>
 
index 8866468c9948813ec3b55ad6e4c6e12bc684f0f1..5e11c950abf90fa8684b3b7bb12216e7650d70f8 100644 (file)
 
 #include <assert.h>
 
-#include "hw.h"
-#include "pc.h"
-#include "pci/pci.h"
-#include "irq.h"
-#include "xen_common.h"
-#include "xen_backend.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/irq.h"
+#include "hw/xen_common.h"
+#include "hw/xen_backend.h"
 #include "trace.h"
 #include "exec/address-spaces.h"
 
index 9db5f6e9645461b4c6919458ebbb16539066db54..ce695d0e64db8d22ab8ce8a76a60f4df5db2ec96 100644 (file)
 
 #include <sys/ioctl.h>
 
-#include "pci/pci.h"
-#include "xen.h"
-#include "xen_backend.h"
-#include "xen_pt.h"
+#include "hw/pci/pci.h"
+#include "hw/xen.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_pt.h"
 #include "qemu/range.h"
 #include "exec/address-spaces.h"
 
index e3497302cf41dc5dee8b59e6e2b7b6f68dd50fd6..1cd9f44704134e05ef9cbdd7690cda63a350fe12 100644 (file)
@@ -2,9 +2,9 @@
 #define XEN_PT_H
 
 #include "qemu-common.h"
-#include "xen_common.h"
-#include "pci/pci.h"
-#include "xen-host-pci-device.h"
+#include "hw/xen_common.h"
+#include "hw/pci/pci.h"
+#include "hw/xen-host-pci-device.h"
 
 void xen_pt_log(const PCIDevice *d, const char *f, ...) GCC_FMT_ATTR(2, 3);
 
index 54a179af90ac55cb2868fb8dd46d3cdb022e9c33..55838216d9e81c7e8b050359f8e28167ab0d684c 100644 (file)
@@ -13,8 +13,8 @@
  */
 
 #include "qemu/timer.h"
-#include "xen_backend.h"
-#include "xen_pt.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_pt.h"
 
 #define XEN_PT_MERGE_VALUE(value, data, val_mask) \
     (((value) & (val_mask)) | ((data) & ~(val_mask)))
index db757cd1f10e9c653fbb088c5378413956addf30..a54ee2bfd96b4b64a556aa6ae95a4ae89a1a5525 100644 (file)
@@ -11,9 +11,9 @@
 
 #include <sys/mman.h>
 
-#include "xen_backend.h"
-#include "xen_pt.h"
-#include "apic-msidef.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_pt.h"
+#include "hw/apic-msidef.h"
 
 
 #define XEN_PT_AUTO_ASSIGN -1
index 7f1f6b464324a677949627613ed482789719ebf6..3462ded619a914889cff7f9315c7f4b9bc947ec2 100644 (file)
 #include <string.h>
 #include <time.h>
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
 #include "char/char.h"
-#include "xen_backend.h"
+#include "hw/xen_backend.h"
 
 #include <xen/event_channel.h>
 #include <xen/io/fbif.h>
index 50722988b9880418717c11170b68a313d4716521..5275f4810dc001a1fa29301ae0f519f4a75f4b87 100644 (file)
@@ -24,7 +24,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 #include "qemu/log.h"
 #include "net/net.h"
diff --git a/hw/xics.c b/hw/xics.c
deleted file mode 100644 (file)
index 9ef0d61..0000000
--- a/hw/xics.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
- *
- * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
- *
- * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-
-#include "hw.h"
-#include "trace.h"
-#include "hw/spapr.h"
-#include "hw/xics.h"
-
-/*
- * ICP: Presentation layer
- */
-
-struct icp_server_state {
-    uint32_t xirr;
-    uint8_t pending_priority;
-    uint8_t mfrr;
-    qemu_irq output;
-};
-
-#define XISR_MASK  0x00ffffff
-#define CPPR_MASK  0xff000000
-
-#define XISR(ss)   (((ss)->xirr) & XISR_MASK)
-#define CPPR(ss)   (((ss)->xirr) >> 24)
-
-struct ics_state;
-
-struct icp_state {
-    long nr_servers;
-    struct icp_server_state *ss;
-    struct ics_state *ics;
-};
-
-static void ics_reject(struct ics_state *ics, int nr);
-static void ics_resend(struct ics_state *ics);
-static void ics_eoi(struct ics_state *ics, int nr);
-
-static void icp_check_ipi(struct icp_state *icp, int server)
-{
-    struct icp_server_state *ss = icp->ss + server;
-
-    if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
-        return;
-    }
-
-    trace_xics_icp_check_ipi(server, ss->mfrr);
-
-    if (XISR(ss)) {
-        ics_reject(icp->ics, XISR(ss));
-    }
-
-    ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
-    ss->pending_priority = ss->mfrr;
-    qemu_irq_raise(ss->output);
-}
-
-static void icp_resend(struct icp_state *icp, int server)
-{
-    struct icp_server_state *ss = icp->ss + server;
-
-    if (ss->mfrr < CPPR(ss)) {
-        icp_check_ipi(icp, server);
-    }
-    ics_resend(icp->ics);
-}
-
-static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr)
-{
-    struct icp_server_state *ss = icp->ss + server;
-    uint8_t old_cppr;
-    uint32_t old_xisr;
-
-    old_cppr = CPPR(ss);
-    ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24);
-
-    if (cppr < old_cppr) {
-        if (XISR(ss) && (cppr <= ss->pending_priority)) {
-            old_xisr = XISR(ss);
-            ss->xirr &= ~XISR_MASK; /* Clear XISR */
-            qemu_irq_lower(ss->output);
-            ics_reject(icp->ics, old_xisr);
-        }
-    } else {
-        if (!XISR(ss)) {
-            icp_resend(icp, server);
-        }
-    }
-}
-
-static void icp_set_mfrr(struct icp_state *icp, int server, uint8_t mfrr)
-{
-    struct icp_server_state *ss = icp->ss + server;
-
-    ss->mfrr = mfrr;
-    if (mfrr < CPPR(ss)) {
-        icp_check_ipi(icp, server);
-    }
-}
-
-static uint32_t icp_accept(struct icp_server_state *ss)
-{
-    uint32_t xirr = ss->xirr;
-
-    qemu_irq_lower(ss->output);
-    ss->xirr = ss->pending_priority << 24;
-
-    trace_xics_icp_accept(xirr, ss->xirr);
-
-    return xirr;
-}
-
-static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
-{
-    struct icp_server_state *ss = icp->ss + server;
-
-    /* Send EOI -> ICS */
-    ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
-    trace_xics_icp_eoi(server, xirr, ss->xirr);
-    ics_eoi(icp->ics, xirr & XISR_MASK);
-    if (!XISR(ss)) {
-        icp_resend(icp, server);
-    }
-}
-
-static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority)
-{
-    struct icp_server_state *ss = icp->ss + server;
-
-    trace_xics_icp_irq(server, nr, priority);
-
-    if ((priority >= CPPR(ss))
-        || (XISR(ss) && (ss->pending_priority <= priority))) {
-        ics_reject(icp->ics, nr);
-    } else {
-        if (XISR(ss)) {
-            ics_reject(icp->ics, XISR(ss));
-        }
-        ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
-        ss->pending_priority = priority;
-        trace_xics_icp_raise(ss->xirr, ss->pending_priority);
-        qemu_irq_raise(ss->output);
-    }
-}
-
-/*
- * ICS: Source layer
- */
-
-struct ics_irq_state {
-    int server;
-    uint8_t priority;
-    uint8_t saved_priority;
-#define XICS_STATUS_ASSERTED           0x1
-#define XICS_STATUS_SENT               0x2
-#define XICS_STATUS_REJECTED           0x4
-#define XICS_STATUS_MASKED_PENDING     0x8
-    uint8_t status;
-};
-
-struct ics_state {
-    int nr_irqs;
-    int offset;
-    qemu_irq *qirqs;
-    bool *islsi;
-    struct ics_irq_state *irqs;
-    struct icp_state *icp;
-};
-
-static int ics_valid_irq(struct ics_state *ics, uint32_t nr)
-{
-    return (nr >= ics->offset)
-        && (nr < (ics->offset + ics->nr_irqs));
-}
-
-static void resend_msi(struct ics_state *ics, int srcno)
-{
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    /* FIXME: filter by server#? */
-    if (irq->status & XICS_STATUS_REJECTED) {
-        irq->status &= ~XICS_STATUS_REJECTED;
-        if (irq->priority != 0xff) {
-            icp_irq(ics->icp, irq->server, srcno + ics->offset,
-                    irq->priority);
-        }
-    }
-}
-
-static void resend_lsi(struct ics_state *ics, int srcno)
-{
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    if ((irq->priority != 0xff)
-        && (irq->status & XICS_STATUS_ASSERTED)
-        && !(irq->status & XICS_STATUS_SENT)) {
-        irq->status |= XICS_STATUS_SENT;
-        icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
-    }
-}
-
-static void set_irq_msi(struct ics_state *ics, int srcno, int val)
-{
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    trace_xics_set_irq_msi(srcno, srcno + ics->offset);
-
-    if (val) {
-        if (irq->priority == 0xff) {
-            irq->status |= XICS_STATUS_MASKED_PENDING;
-            trace_xics_masked_pending();
-        } else  {
-            icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
-        }
-    }
-}
-
-static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
-{
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
-    if (val) {
-        irq->status |= XICS_STATUS_ASSERTED;
-    } else {
-        irq->status &= ~XICS_STATUS_ASSERTED;
-    }
-    resend_lsi(ics, srcno);
-}
-
-static void ics_set_irq(void *opaque, int srcno, int val)
-{
-    struct ics_state *ics = (struct ics_state *)opaque;
-
-    if (ics->islsi[srcno]) {
-        set_irq_lsi(ics, srcno, val);
-    } else {
-        set_irq_msi(ics, srcno, val);
-    }
-}
-
-static void write_xive_msi(struct ics_state *ics, int srcno)
-{
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    if (!(irq->status & XICS_STATUS_MASKED_PENDING)
-        || (irq->priority == 0xff)) {
-        return;
-    }
-
-    irq->status &= ~XICS_STATUS_MASKED_PENDING;
-    icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
-}
-
-static void write_xive_lsi(struct ics_state *ics, int srcno)
-{
-    resend_lsi(ics, srcno);
-}
-
-static void ics_write_xive(struct ics_state *ics, int nr, int server,
-                           uint8_t priority, uint8_t saved_priority)
-{
-    int srcno = nr - ics->offset;
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    irq->server = server;
-    irq->priority = priority;
-    irq->saved_priority = saved_priority;
-
-    trace_xics_ics_write_xive(nr, srcno, server, priority);
-
-    if (ics->islsi[srcno]) {
-        write_xive_lsi(ics, srcno);
-    } else {
-        write_xive_msi(ics, srcno);
-    }
-}
-
-static void ics_reject(struct ics_state *ics, int nr)
-{
-    struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
-
-    trace_xics_ics_reject(nr, nr - ics->offset);
-    irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
-    irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
-}
-
-static void ics_resend(struct ics_state *ics)
-{
-    int i;
-
-    for (i = 0; i < ics->nr_irqs; i++) {
-        /* FIXME: filter by server#? */
-        if (ics->islsi[i]) {
-            resend_lsi(ics, i);
-        } else {
-            resend_msi(ics, i);
-        }
-    }
-}
-
-static void ics_eoi(struct ics_state *ics, int nr)
-{
-    int srcno = nr - ics->offset;
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    trace_xics_ics_eoi(nr);
-
-    if (ics->islsi[srcno]) {
-        irq->status &= ~XICS_STATUS_SENT;
-    }
-}
-
-/*
- * Exported functions
- */
-
-qemu_irq xics_get_qirq(struct icp_state *icp, int irq)
-{
-    if (!ics_valid_irq(icp->ics, irq)) {
-        return NULL;
-    }
-
-    return icp->ics->qirqs[irq - icp->ics->offset];
-}
-
-void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi)
-{
-    assert(ics_valid_irq(icp->ics, irq));
-
-    icp->ics->islsi[irq - icp->ics->offset] = lsi;
-}
-
-static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                           target_ulong opcode, target_ulong *args)
-{
-    CPUState *cs = CPU(cpu);
-    target_ulong cppr = args[0];
-
-    icp_set_cppr(spapr->icp, cs->cpu_index, cppr);
-    return H_SUCCESS;
-}
-
-static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                          target_ulong opcode, target_ulong *args)
-{
-    target_ulong server = args[0];
-    target_ulong mfrr = args[1];
-
-    if (server >= spapr->icp->nr_servers) {
-        return H_PARAMETER;
-    }
-
-    icp_set_mfrr(spapr->icp, server, mfrr);
-    return H_SUCCESS;
-}
-
-static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                           target_ulong opcode, target_ulong *args)
-{
-    CPUState *cs = CPU(cpu);
-    uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index);
-
-    args[0] = xirr;
-    return H_SUCCESS;
-}
-
-static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                          target_ulong opcode, target_ulong *args)
-{
-    CPUState *cs = CPU(cpu);
-    target_ulong xirr = args[0];
-
-    icp_eoi(spapr->icp, cs->cpu_index, xirr);
-    return H_SUCCESS;
-}
-
-static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token,
-                          uint32_t nargs, target_ulong args,
-                          uint32_t nret, target_ulong rets)
-{
-    struct ics_state *ics = spapr->icp->ics;
-    uint32_t nr, server, priority;
-
-    if ((nargs != 3) || (nret != 1)) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    nr = rtas_ld(args, 0);
-    server = rtas_ld(args, 1);
-    priority = rtas_ld(args, 2);
-
-    if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
-        || (priority > 0xff)) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    ics_write_xive(ics, nr, server, priority, priority);
-
-    rtas_st(rets, 0, 0); /* Success */
-}
-
-static void rtas_get_xive(sPAPREnvironment *spapr, uint32_t token,
-                          uint32_t nargs, target_ulong args,
-                          uint32_t nret, target_ulong rets)
-{
-    struct ics_state *ics = spapr->icp->ics;
-    uint32_t nr;
-
-    if ((nargs != 1) || (nret != 3)) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    nr = rtas_ld(args, 0);
-
-    if (!ics_valid_irq(ics, nr)) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    rtas_st(rets, 0, 0); /* Success */
-    rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
-    rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
-}
-
-static void rtas_int_off(sPAPREnvironment *spapr, uint32_t token,
-                         uint32_t nargs, target_ulong args,
-                         uint32_t nret, target_ulong rets)
-{
-    struct ics_state *ics = spapr->icp->ics;
-    uint32_t nr;
-
-    if ((nargs != 1) || (nret != 1)) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    nr = rtas_ld(args, 0);
-
-    if (!ics_valid_irq(ics, nr)) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
-                   ics->irqs[nr - ics->offset].priority);
-
-    rtas_st(rets, 0, 0); /* Success */
-}
-
-static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token,
-                        uint32_t nargs, target_ulong args,
-                        uint32_t nret, target_ulong rets)
-{
-    struct ics_state *ics = spapr->icp->ics;
-    uint32_t nr;
-
-    if ((nargs != 1) || (nret != 1)) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    nr = rtas_ld(args, 0);
-
-    if (!ics_valid_irq(ics, nr)) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
-                   ics->irqs[nr - ics->offset].saved_priority,
-                   ics->irqs[nr - ics->offset].saved_priority);
-
-    rtas_st(rets, 0, 0); /* Success */
-}
-
-static void xics_reset(void *opaque)
-{
-    struct icp_state *icp = (struct icp_state *)opaque;
-    struct ics_state *ics = icp->ics;
-    int i;
-
-    for (i = 0; i < icp->nr_servers; i++) {
-        icp->ss[i].xirr = 0;
-        icp->ss[i].pending_priority = 0xff;
-        icp->ss[i].mfrr = 0xff;
-        /* Make all outputs are deasserted */
-        qemu_set_irq(icp->ss[i].output, 0);
-    }
-
-    memset(ics->irqs, 0, sizeof(struct ics_irq_state) * ics->nr_irqs);
-    for (i = 0; i < ics->nr_irqs; i++) {
-        ics->irqs[i].priority = 0xff;
-        ics->irqs[i].saved_priority = 0xff;
-    }
-}
-
-struct icp_state *xics_system_init(int nr_irqs)
-{
-    CPUPPCState *env;
-    CPUState *cpu;
-    int max_server_num;
-    struct icp_state *icp;
-    struct ics_state *ics;
-
-    max_server_num = -1;
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
-        if (cpu->cpu_index > max_server_num) {
-            max_server_num = cpu->cpu_index;
-        }
-    }
-
-    icp = g_malloc0(sizeof(*icp));
-    icp->nr_servers = max_server_num + 1;
-    icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
-        struct icp_server_state *ss = &icp->ss[cpu->cpu_index];
-
-        switch (PPC_INPUT(env)) {
-        case PPC_FLAGS_INPUT_POWER7:
-            ss->output = env->irq_inputs[POWER7_INPUT_INT];
-            break;
-
-        case PPC_FLAGS_INPUT_970:
-            ss->output = env->irq_inputs[PPC970_INPUT_INT];
-            break;
-
-        default:
-            hw_error("XICS interrupt model does not support this CPU bus "
-                     "model\n");
-            exit(1);
-        }
-    }
-
-    ics = g_malloc0(sizeof(*ics));
-    ics->nr_irqs = nr_irqs;
-    ics->offset = XICS_IRQ_BASE;
-    ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state));
-    ics->islsi = g_malloc0(nr_irqs * sizeof(bool));
-
-    icp->ics = ics;
-    ics->icp = icp;
-
-    ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs);
-
-    spapr_register_hypercall(H_CPPR, h_cppr);
-    spapr_register_hypercall(H_IPI, h_ipi);
-    spapr_register_hypercall(H_XIRR, h_xirr);
-    spapr_register_hypercall(H_EOI, h_eoi);
-
-    spapr_rtas_register("ibm,set-xive", rtas_set_xive);
-    spapr_rtas_register("ibm,get-xive", rtas_get_xive);
-    spapr_rtas_register("ibm,int-off", rtas_int_off);
-    spapr_rtas_register("ibm,int-on", rtas_int_on);
-
-    qemu_register_reset(xics_reset, icp);
-
-    return icp;
-}
index 09bc2e4913a0748c318b2aa5775fd3ed8dfa1e3c..6c1ee21c5470289acad9972ebc9179147895b0cb 100644 (file)
@@ -2,8 +2,9 @@
 #define HW_XILINX_H 1
 
 
-#include "stream.h"
 #include "qemu-common.h"
+#include "qapi/qmp/qerror.h"
+#include "hw/stream.h"
 #include "net/net.h"
 
 static inline DeviceState *
index cc51584dfc791b3c91821ddab50702582019d920..8db1a74acfa8f4f2e52b8a3ac26ca4e2fc61581e 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "qemu/log.h"
-#include "qdev-addr.h"
+#include "hw/qdev-addr.h"
 
-#include "stream.h"
+#include "hw/stream.h"
 
 #define D(x)
 
index e5d9251b8b6f51847a88380b9a6ea5e63137ea09..578529022418a8e440698b3f09ed62f8d748304a 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/log.h"
 #include "net/net.h"
 #include "net/checksum.h"
+#include "qapi/qmp/qerror.h"
 
-#include "stream.h"
+#include "hw/stream.h"
 
 #define DPHY(x)
 
index 21c6f8c49caa8606735a624675f283d70fa3783e..b2e35237f8678a5077d0177680a619d117f2de82 100644 (file)
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "hw.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
 #include "net/net.h"
 
 #define D(x)
index 0c34149c276efd87fea9a88ee30cd7246405c42b..b106e724ab23423dca2c6e5efcd073baf4a4e06d 100644 (file)
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "hw.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
 
 #define D(x)
 
index be581c2ac5c3abec24b9f280ceef42633e778693..f6bd3bac231fb8638bf3f8ff6309453d44623f29 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
-#include "fifo.h"
+#include "qemu/fifo8.h"
 
-#include "ssi.h"
+#include "hw/ssi.h"
 
 #ifdef XILINX_SPI_ERR_DEBUG
 #define DB_PRINT(...) do { \
index 42e019dc057ceaf60735c09e2e44b456152a1773..6c21b9668bd0b0f8852b092686fb73f9daf7de1b 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "qemu/log.h"
-#include "fifo.h"
-#include "ssi.h"
+#include "qemu/fifo8.h"
+#include "hw/ssi.h"
 #include "qemu/bitops.h"
 
 #ifdef XILINX_SPIPS_ERR_DEBUG
index aa162efaadbd29f00b1d70ddd4c038418aad0bad..0c39cff08953b599ee297d0c065552747e84e2a6 100644 (file)
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "ptimer.h"
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
 #include "qemu/log.h"
 
 #define D(x)
index 9963982ef6628f182b1347ba5817e54b69ee98c8..079f4d4e1a86102f1fa2a00af73af09a99018498 100644 (file)
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 
 #define DUART(x)
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
deleted file mode 100644 (file)
index 2f67d90..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Xilinx Zynq Baseboard System emulation.
- *
- * Copyright (c) 2010 Xilinx.
- * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.croshtwaite@petalogix.com)
- * Copyright (c) 2012 Petalogix Pty Ltd.
- * Written by Haibing Ma
- *
- * 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.
- *
- * 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 "sysbus.h"
-#include "arm-misc.h"
-#include "net/net.h"
-#include "exec/address-spaces.h"
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "flash.h"
-#include "sysemu/blockdev.h"
-#include "loader.h"
-#include "ssi.h"
-
-#define NUM_SPI_FLASHES 4
-#define NUM_QSPI_FLASHES 2
-#define NUM_QSPI_BUSSES 2
-
-#define FLASH_SIZE (64 * 1024 * 1024)
-#define FLASH_SECTOR_SIZE (128 * 1024)
-
-#define IRQ_OFFSET 32 /* pic interrupts start from index 32 */
-
-static struct arm_boot_info zynq_binfo = {};
-
-static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    qemu_check_nic_model(nd, "cadence_gem");
-    dev = qdev_create(NULL, "cadence_gem");
-    qdev_set_nic_properties(dev, nd);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(s, 0, base);
-    sysbus_connect_irq(s, 0, irq);
-}
-
-static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
-                                         bool is_qspi)
-{
-    DeviceState *dev;
-    SysBusDevice *busdev;
-    SSIBus *spi;
-    DeviceState *flash_dev;
-    int i, j;
-    int num_busses =  is_qspi ? NUM_QSPI_BUSSES : 1;
-    int num_ss = is_qspi ? NUM_QSPI_FLASHES : NUM_SPI_FLASHES;
-
-    dev = qdev_create(NULL, "xilinx,spips");
-    qdev_prop_set_uint8(dev, "num-txrx-bytes", is_qspi ? 4 : 1);
-    qdev_prop_set_uint8(dev, "num-ss-bits", num_ss);
-    qdev_prop_set_uint8(dev, "num-busses", num_busses);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, base_addr);
-    if (is_qspi) {
-        sysbus_mmio_map(busdev, 1, 0xFC000000);
-    }
-    sysbus_connect_irq(busdev, 0, irq);
-
-    for (i = 0; i < num_busses; ++i) {
-        char bus_name[16];
-        qemu_irq cs_line;
-
-        snprintf(bus_name, 16, "spi%d", i);
-        spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
-
-        for (j = 0; j < num_ss; ++j) {
-            flash_dev = ssi_create_slave_no_init(spi, "n25q128");
-            qdev_init_nofail(flash_dev);
-
-            cs_line = qdev_get_gpio_in(flash_dev, 0);
-            sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line);
-        }
-    }
-
-}
-
-static void zynq_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    ARMCPU *cpu;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
-    MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
-    DeviceState *dev;
-    SysBusDevice *busdev;
-    qemu_irq *irqp;
-    qemu_irq pic[64];
-    NICInfo *nd;
-    int n;
-    qemu_irq cpu_irq;
-
-    if (!cpu_model) {
-        cpu_model = "cortex-a9";
-    }
-
-    cpu = cpu_arm_init(cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    irqp = arm_pic_init_cpu(cpu);
-    cpu_irq = irqp[ARM_PIC_CPU_IRQ];
-
-    /* max 2GB ram */
-    if (ram_size > 0x80000000) {
-        ram_size = 0x80000000;
-    }
-
-    /* DDR remapped to address zero.  */
-    memory_region_init_ram(ext_ram, "zynq.ext_ram", ram_size);
-    vmstate_register_ram_global(ext_ram);
-    memory_region_add_subregion(address_space_mem, 0, ext_ram);
-
-    /* 256K of on-chip memory */
-    memory_region_init_ram(ocm_ram, "zynq.ocm_ram", 256 << 10);
-    vmstate_register_ram_global(ocm_ram);
-    memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram);
-
-    DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
-
-    /* AMD */
-    pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE,
-                          FLASH_SIZE/FLASH_SECTOR_SIZE, 1,
-                          1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
-                              0);
-
-    dev = qdev_create(NULL, "xilinx,zynq_slcr");
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000);
-
-    dev = qdev_create(NULL, "a9mpcore_priv");
-    qdev_prop_set_uint32(dev, "num-cpu", 1);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0xF8F00000);
-    sysbus_connect_irq(busdev, 0, cpu_irq);
-
-    for (n = 0; n < 64; n++) {
-        pic[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET], false);
-    zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false);
-    zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true);
-
-    sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]);
-    sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]);
-
-    sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]);
-    sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]);
-
-    sysbus_create_varargs("cadence_ttc", 0xF8001000,
-            pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);
-    sysbus_create_varargs("cadence_ttc", 0xF8002000,
-            pic[69-IRQ_OFFSET], pic[70-IRQ_OFFSET], pic[71-IRQ_OFFSET], NULL);
-
-    for (n = 0; n < nb_nics; n++) {
-        nd = &nd_table[n];
-        if (n == 0) {
-            gem_init(nd, 0xE000B000, pic[54-IRQ_OFFSET]);
-        } else if (n == 1) {
-            gem_init(nd, 0xE000C000, pic[77-IRQ_OFFSET]);
-        }
-    }
-
-    dev = qdev_create(NULL, "generic-sdhci");
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
-
-    dev = qdev_create(NULL, "generic-sdhci");
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
-
-    zynq_binfo.ram_size = ram_size;
-    zynq_binfo.kernel_filename = kernel_filename;
-    zynq_binfo.kernel_cmdline = kernel_cmdline;
-    zynq_binfo.initrd_filename = initrd_filename;
-    zynq_binfo.nb_cpus = 1;
-    zynq_binfo.board_id = 0xd32;
-    zynq_binfo.loader_start = 0;
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &zynq_binfo);
-}
-
-static QEMUMachine zynq_machine = {
-    .name = "xilinx-zynq-a9",
-    .desc = "Xilinx Zynq Platform Baseboard for Cortex-A9",
-    .init = zynq_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 1,
-    .no_sdcard = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void zynq_machine_init(void)
-{
-    qemu_register_machine(&zynq_machine);
-}
-
-machine_init(zynq_machine_init);
index 7f00bc82564be1853b9272981dc4d96cb9d38c64..4bccd0ddcdce1260cfe76e082a609aec1a2d1892 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci/pci_ids.h"
-#include "pci/msi.h"
-#include "pci/pcie.h"
-#include "xio3130_downstream.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/pcie.h"
+#include "hw/xio3130_downstream.h"
 
 #define PCI_DEVICE_ID_TI_XIO3130D       0x8233  /* downstream port */
 #define XIO3130_REVISION                0x1
index 559dff656523a7f135369a6c875e28a835be1221..8426d9ffa675c8719bf6348b3965b58064de75c5 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef QEMU_XIO3130_DOWNSTREAM_H
 #define QEMU_XIO3130_DOWNSTREAM_H
 
-#include "pci/pcie_port.h"
+#include "hw/pci/pcie_port.h"
 
 PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
                                   const char *bus_name, pci_map_irq_fn map_irq,
index 70b15d37c8f558000d9d05765b1e6c37b4d02dc2..82556aaadcae34242ee803ae3cdb9fee81c4c2bf 100644 (file)
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci/pci_ids.h"
-#include "pci/msi.h"
-#include "pci/pcie.h"
-#include "xio3130_upstream.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/pcie.h"
+#include "hw/xio3130_upstream.h"
 
 #define PCI_DEVICE_ID_TI_XIO3130U       0x8232  /* upstream port */
 #define XIO3130_REVISION                0x2
index fa09656b3525c57cb4a925cf1f0d752f51c3d489..08c1d5f75b61df0f03706debf764c23709d59589 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef QEMU_XIO3130_UPSTREAM_H
 #define QEMU_XIO3130_UPSTREAM_H
 
-#include "pci/pcie_port.h"
+#include "hw/pci/pcie_port.h"
 
 PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
                                 const char *bus_name, pci_map_irq_fn map_irq,
index 79698e903d31058df06c93960fc76b86a5ecf54b..6ead7820c45ddb825b816ee87c1257fcaf2c9b05 100644 (file)
@@ -1,5 +1,3 @@
-obj-y += xtensa_pic.o
+obj-y += pic_cpu.o
 obj-y += xtensa_sim.o
 obj-y += xtensa_lx60.o
-
-obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/xtensa/pic_cpu.c b/hw/xtensa/pic_cpu.c
new file mode 100644 (file)
index 0000000..f485a14
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "hw/hw.h"
+#include "qemu/log.h"
+#include "qemu/timer.h"
+
+void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d)
+{
+    uint32_t old_ccount = env->sregs[CCOUNT];
+
+    env->sregs[CCOUNT] += d;
+
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
+        int i;
+        for (i = 0; i < env->config->nccompare; ++i) {
+            if (env->sregs[CCOMPARE + i] - old_ccount <= d) {
+                xtensa_timer_irq(env, i, 1);
+            }
+        }
+    }
+}
+
+void check_interrupts(CPUXtensaState *env)
+{
+    int minlevel = xtensa_get_cintlevel(env);
+    uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
+    int level;
+
+    /* If the CPU is halted advance CCOUNT according to the vm_clock time
+     * elapsed since the moment when it was advanced last time.
+     */
+    if (env->halted) {
+        int64_t now = qemu_get_clock_ns(vm_clock);
+
+        xtensa_advance_ccount(env,
+                muldiv64(now - env->halt_clock,
+                    env->config->clock_freq_khz, 1000000));
+        env->halt_clock = now;
+    }
+    for (level = env->config->nlevel; level > minlevel; --level) {
+        if (env->config->level_mask[level] & int_set_enabled) {
+            env->pending_irq_level = level;
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            qemu_log_mask(CPU_LOG_INT,
+                    "%s level = %d, cintlevel = %d, "
+                    "pc = %08x, a0 = %08x, ps = %08x, "
+                    "intset = %08x, intenable = %08x, "
+                    "ccount = %08x\n",
+                    __func__, level, xtensa_get_cintlevel(env),
+                    env->pc, env->regs[0], env->sregs[PS],
+                    env->sregs[INTSET], env->sregs[INTENABLE],
+                    env->sregs[CCOUNT]);
+            return;
+        }
+    }
+    env->pending_irq_level = 0;
+    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+}
+
+static void xtensa_set_irq(void *opaque, int irq, int active)
+{
+    CPUXtensaState *env = opaque;
+
+    if (irq >= env->config->ninterrupt) {
+        qemu_log("%s: bad IRQ %d\n", __func__, irq);
+    } else {
+        uint32_t irq_bit = 1 << irq;
+
+        if (active) {
+            env->sregs[INTSET] |= irq_bit;
+        } else if (env->config->interrupt[irq].inttype == INTTYPE_LEVEL) {
+            env->sregs[INTSET] &= ~irq_bit;
+        }
+
+        check_interrupts(env);
+    }
+}
+
+void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active)
+{
+    qemu_set_irq(env->irq_inputs[env->config->timerint[id]], active);
+}
+
+void xtensa_rearm_ccompare_timer(CPUXtensaState *env)
+{
+    int i;
+    uint32_t wake_ccount = env->sregs[CCOUNT] - 1;
+
+    for (i = 0; i < env->config->nccompare; ++i) {
+        if (env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] <
+                wake_ccount - env->sregs[CCOUNT]) {
+            wake_ccount = env->sregs[CCOMPARE + i];
+        }
+    }
+    env->wake_ccount = wake_ccount;
+    qemu_mod_timer(env->ccompare_timer, env->halt_clock +
+            muldiv64(wake_ccount - env->sregs[CCOUNT],
+                1000000, env->config->clock_freq_khz));
+}
+
+static void xtensa_ccompare_cb(void *opaque)
+{
+    XtensaCPU *cpu = opaque;
+    CPUXtensaState *env = &cpu->env;
+
+    if (env->halted) {
+        env->halt_clock = qemu_get_clock_ns(vm_clock);
+        xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]);
+        if (!cpu_has_work(CPU(cpu))) {
+            env->sregs[CCOUNT] = env->wake_ccount + 1;
+            xtensa_rearm_ccompare_timer(env);
+        }
+    }
+}
+
+void xtensa_irq_init(CPUXtensaState *env)
+{
+    XtensaCPU *cpu = xtensa_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(
+            xtensa_set_irq, env, env->config->ninterrupt);
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT) &&
+            env->config->nccompare > 0) {
+        env->ccompare_timer =
+            qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, cpu);
+    }
+}
+
+void *xtensa_get_extint(CPUXtensaState *env, unsigned extint)
+{
+    if (extint < env->config->nextint) {
+        unsigned irq = env->config->extint[extint];
+        return env->irq_inputs[irq];
+    } else {
+        qemu_log("%s: trying to acquire invalid external interrupt %d\n",
+                __func__, extint);
+        return NULL;
+    }
+}
diff --git a/hw/xtensa/xtensa_lx60.c b/hw/xtensa/xtensa_lx60.c
new file mode 100644 (file)
index 0000000..f2a63d8
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "hw/serial.h"
+#include "net/net.h"
+#include "hw/sysbus.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "char/char.h"
+#include "hw/xtensa_bootparam.h"
+
+typedef struct LxBoardDesc {
+    size_t flash_size;
+    size_t flash_sector_size;
+    size_t sram_size;
+} LxBoardDesc;
+
+typedef struct Lx60FpgaState {
+    MemoryRegion iomem;
+    uint32_t leds;
+    uint32_t switches;
+} Lx60FpgaState;
+
+static void lx60_fpga_reset(void *opaque)
+{
+    Lx60FpgaState *s = opaque;
+
+    s->leds = 0;
+    s->switches = 0;
+}
+
+static uint64_t lx60_fpga_read(void *opaque, hwaddr addr,
+        unsigned size)
+{
+    Lx60FpgaState *s = opaque;
+
+    switch (addr) {
+    case 0x0: /*build date code*/
+        return 0x09272011;
+
+    case 0x4: /*processor clock frequency, Hz*/
+        return 10000000;
+
+    case 0x8: /*LEDs (off = 0, on = 1)*/
+        return s->leds;
+
+    case 0xc: /*DIP switches (off = 0, on = 1)*/
+        return s->switches;
+    }
+    return 0;
+}
+
+static void lx60_fpga_write(void *opaque, hwaddr addr,
+        uint64_t val, unsigned size)
+{
+    Lx60FpgaState *s = opaque;
+
+    switch (addr) {
+    case 0x8: /*LEDs (off = 0, on = 1)*/
+        s->leds = val;
+        break;
+
+    case 0x10: /*board reset*/
+        if (val == 0xdead) {
+            qemu_system_reset_request();
+        }
+        break;
+    }
+}
+
+static const MemoryRegionOps lx60_fpga_ops = {
+    .read = lx60_fpga_read,
+    .write = lx60_fpga_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space,
+        hwaddr base)
+{
+    Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState));
+
+    memory_region_init_io(&s->iomem, &lx60_fpga_ops, s,
+            "lx60.fpga", 0x10000);
+    memory_region_add_subregion(address_space, base, &s->iomem);
+    lx60_fpga_reset(s);
+    qemu_register_reset(lx60_fpga_reset, s);
+    return s;
+}
+
+static void lx60_net_init(MemoryRegion *address_space,
+        hwaddr base,
+        hwaddr descriptors,
+        hwaddr buffers,
+        qemu_irq irq, NICInfo *nd)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    MemoryRegion *ram;
+
+    dev = qdev_create(NULL, "open_eth");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, irq);
+    memory_region_add_subregion(address_space, base,
+            sysbus_mmio_get_region(s, 0));
+    memory_region_add_subregion(address_space, descriptors,
+            sysbus_mmio_get_region(s, 1));
+
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, "open_eth.ram", 16384);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space, buffers, ram);
+}
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+    return cpu_get_phys_page_debug(env, addr);
+}
+
+static void lx60_reset(void *opaque)
+{
+    XtensaCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+static void lx_init(const LxBoardDesc *board, QEMUMachineInitArgs *args)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    int be = 1;
+#else
+    int be = 0;
+#endif
+    MemoryRegion *system_memory = get_system_memory();
+    XtensaCPU *cpu = NULL;
+    CPUXtensaState *env = NULL;
+    MemoryRegion *ram, *rom, *system_io;
+    DriveInfo *dinfo;
+    pflash_t *flash = NULL;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    int n;
+
+    if (!cpu_model) {
+        cpu_model = XTENSA_DEFAULT_CPU_MODEL;
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        cpu = cpu_xtensa_init(cpu_model);
+        if (cpu == NULL) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        env = &cpu->env;
+
+        env->sregs[PRID] = n;
+        qemu_register_reset(lx60_reset, cpu);
+        /* Need MMU initialized prior to ELF loading,
+         * so that ELF gets loaded into virtual addresses
+         */
+        cpu_reset(CPU(cpu));
+    }
+
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, "lx60.dram", args->ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(system_memory, 0, ram);
+
+    system_io = g_malloc(sizeof(*system_io));
+    memory_region_init(system_io, "lx60.io", 224 * 1024 * 1024);
+    memory_region_add_subregion(system_memory, 0xf0000000, system_io);
+    lx60_fpga_init(system_io, 0x0d020000);
+    if (nd_table[0].used) {
+        lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000,
+                xtensa_get_extint(env, 1), nd_table);
+    }
+
+    if (!serial_hds[0]) {
+        serial_hds[0] = qemu_chr_new("serial0", "null", NULL);
+    }
+
+    serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0),
+            115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (dinfo) {
+        flash = pflash_cfi01_register(0xf8000000,
+                NULL, "lx60.io.flash", board->flash_size,
+                dinfo->bdrv, board->flash_sector_size,
+                board->flash_size / board->flash_sector_size,
+                4, 0x0000, 0x0000, 0x0000, 0x0000, be);
+        if (flash == NULL) {
+            fprintf(stderr, "Unable to mount pflash\n");
+            exit(1);
+        }
+    }
+
+    /* Use presence of kernel file name as 'boot from SRAM' switch. */
+    if (kernel_filename) {
+        rom = g_malloc(sizeof(*rom));
+        memory_region_init_ram(rom, "lx60.sram", board->sram_size);
+        vmstate_register_ram_global(rom);
+        memory_region_add_subregion(system_memory, 0xfe000000, rom);
+
+        /* Put kernel bootparameters to the end of that SRAM */
+        if (kernel_cmdline) {
+            size_t cmdline_size = strlen(kernel_cmdline) + 1;
+            size_t bp_size = sizeof(BpTag[4]) + cmdline_size;
+            uint32_t tagptr = (0xfe000000 + board->sram_size - bp_size) & ~0xff;
+
+            env->regs[2] = tagptr;
+
+            tagptr = put_tag(tagptr, 0x7b0b, 0, NULL);
+            if (cmdline_size > 1) {
+                tagptr = put_tag(tagptr, 0x1001,
+                        cmdline_size, kernel_cmdline);
+            }
+            tagptr = put_tag(tagptr, 0x7e0b, 0, NULL);
+        }
+        uint64_t elf_entry;
+        uint64_t elf_lowaddr;
+        int success = load_elf(kernel_filename, translate_phys_addr, env,
+                &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0);
+        if (success > 0) {
+            env->pc = elf_entry;
+        }
+    } else {
+        if (flash) {
+            MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash);
+            MemoryRegion *flash_io = g_malloc(sizeof(*flash_io));
+
+            memory_region_init_alias(flash_io, "lx60.flash",
+                    flash_mr, 0, board->flash_size);
+            memory_region_add_subregion(system_memory, 0xfe000000,
+                    flash_io);
+        }
+    }
+}
+
+static void xtensa_lx60_init(QEMUMachineInitArgs *args)
+{
+    static const LxBoardDesc lx60_board = {
+        .flash_size = 0x400000,
+        .flash_sector_size = 0x10000,
+        .sram_size = 0x20000,
+    };
+    lx_init(&lx60_board, args);
+}
+
+static void xtensa_lx200_init(QEMUMachineInitArgs *args)
+{
+    static const LxBoardDesc lx200_board = {
+        .flash_size = 0x1000000,
+        .flash_sector_size = 0x20000,
+        .sram_size = 0x2000000,
+    };
+    lx_init(&lx200_board, args);
+}
+
+static QEMUMachine xtensa_lx60_machine = {
+    .name = "lx60",
+    .desc = "lx60 EVB (" XTENSA_DEFAULT_CPU_MODEL ")",
+    .init = xtensa_lx60_init,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine xtensa_lx200_machine = {
+    .name = "lx200",
+    .desc = "lx200 EVB (" XTENSA_DEFAULT_CPU_MODEL ")",
+    .init = xtensa_lx200_init,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void xtensa_lx_machines_init(void)
+{
+    qemu_register_machine(&xtensa_lx60_machine);
+    qemu_register_machine(&xtensa_lx200_machine);
+}
+
+machine_init(xtensa_lx_machines_init);
diff --git a/hw/xtensa/xtensa_sim.c b/hw/xtensa/xtensa_sim.c
new file mode 100644 (file)
index 0000000..5241f8d
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+    return cpu_get_phys_page_debug(env, addr);
+}
+
+static void sim_reset(void *opaque)
+{
+    XtensaCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+static void xtensa_sim_init(QEMUMachineInitArgs *args)
+{
+    XtensaCPU *cpu = NULL;
+    CPUXtensaState *env = NULL;
+    MemoryRegion *ram, *rom;
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    int n;
+
+    if (!cpu_model) {
+        cpu_model = XTENSA_DEFAULT_CPU_MODEL;
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        cpu = cpu_xtensa_init(cpu_model);
+        if (cpu == NULL) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        env = &cpu->env;
+
+        env->sregs[PRID] = n;
+        qemu_register_reset(sim_reset, cpu);
+        /* Need MMU initialized prior to ELF loading,
+         * so that ELF gets loaded into virtual addresses
+         */
+        sim_reset(cpu);
+    }
+
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, "xtensa.sram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(get_system_memory(), 0, ram);
+
+    rom = g_malloc(sizeof(*rom));
+    memory_region_init_ram(rom, "xtensa.rom", 0x1000);
+    vmstate_register_ram_global(rom);
+    memory_region_add_subregion(get_system_memory(), 0xfe000000, rom);
+
+    if (kernel_filename) {
+        uint64_t elf_entry;
+        uint64_t elf_lowaddr;
+#ifdef TARGET_WORDS_BIGENDIAN
+        int success = load_elf(kernel_filename, translate_phys_addr, env,
+                &elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
+#else
+        int success = load_elf(kernel_filename, translate_phys_addr, env,
+                &elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
+#endif
+        if (success > 0) {
+            env->pc = elf_entry;
+        }
+    }
+}
+
+static QEMUMachine xtensa_sim_machine = {
+    .name = "sim",
+    .desc = "sim machine (" XTENSA_DEFAULT_CPU_MODEL ")",
+    .is_default = true,
+    .init = xtensa_sim_init,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void xtensa_sim_machine_init(void)
+{
+    qemu_register_machine(&xtensa_sim_machine);
+}
+
+machine_init(xtensa_sim_machine_init);
diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
deleted file mode 100644 (file)
index a810b9e..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the Open Source and Linux Lab nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "loader.h"
-#include "elf.h"
-#include "exec/memory.h"
-#include "exec/address-spaces.h"
-#include "serial.h"
-#include "net/net.h"
-#include "sysbus.h"
-#include "flash.h"
-#include "sysemu/blockdev.h"
-#include "char/char.h"
-#include "xtensa_bootparam.h"
-
-typedef struct LxBoardDesc {
-    size_t flash_size;
-    size_t flash_sector_size;
-    size_t sram_size;
-} LxBoardDesc;
-
-typedef struct Lx60FpgaState {
-    MemoryRegion iomem;
-    uint32_t leds;
-    uint32_t switches;
-} Lx60FpgaState;
-
-static void lx60_fpga_reset(void *opaque)
-{
-    Lx60FpgaState *s = opaque;
-
-    s->leds = 0;
-    s->switches = 0;
-}
-
-static uint64_t lx60_fpga_read(void *opaque, hwaddr addr,
-        unsigned size)
-{
-    Lx60FpgaState *s = opaque;
-
-    switch (addr) {
-    case 0x0: /*build date code*/
-        return 0x09272011;
-
-    case 0x4: /*processor clock frequency, Hz*/
-        return 10000000;
-
-    case 0x8: /*LEDs (off = 0, on = 1)*/
-        return s->leds;
-
-    case 0xc: /*DIP switches (off = 0, on = 1)*/
-        return s->switches;
-    }
-    return 0;
-}
-
-static void lx60_fpga_write(void *opaque, hwaddr addr,
-        uint64_t val, unsigned size)
-{
-    Lx60FpgaState *s = opaque;
-
-    switch (addr) {
-    case 0x8: /*LEDs (off = 0, on = 1)*/
-        s->leds = val;
-        break;
-
-    case 0x10: /*board reset*/
-        if (val == 0xdead) {
-            qemu_system_reset_request();
-        }
-        break;
-    }
-}
-
-static const MemoryRegionOps lx60_fpga_ops = {
-    .read = lx60_fpga_read,
-    .write = lx60_fpga_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space,
-        hwaddr base)
-{
-    Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState));
-
-    memory_region_init_io(&s->iomem, &lx60_fpga_ops, s,
-            "lx60.fpga", 0x10000);
-    memory_region_add_subregion(address_space, base, &s->iomem);
-    lx60_fpga_reset(s);
-    qemu_register_reset(lx60_fpga_reset, s);
-    return s;
-}
-
-static void lx60_net_init(MemoryRegion *address_space,
-        hwaddr base,
-        hwaddr descriptors,
-        hwaddr buffers,
-        qemu_irq irq, NICInfo *nd)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    MemoryRegion *ram;
-
-    dev = qdev_create(NULL, "open_eth");
-    qdev_set_nic_properties(dev, nd);
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, irq);
-    memory_region_add_subregion(address_space, base,
-            sysbus_mmio_get_region(s, 0));
-    memory_region_add_subregion(address_space, descriptors,
-            sysbus_mmio_get_region(s, 1));
-
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "open_eth.ram", 16384);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space, buffers, ram);
-}
-
-static uint64_t translate_phys_addr(void *env, uint64_t addr)
-{
-    return cpu_get_phys_page_debug(env, addr);
-}
-
-static void lx60_reset(void *opaque)
-{
-    XtensaCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-static void lx_init(const LxBoardDesc *board, QEMUMachineInitArgs *args)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
-    int be = 1;
-#else
-    int be = 0;
-#endif
-    MemoryRegion *system_memory = get_system_memory();
-    XtensaCPU *cpu = NULL;
-    CPUXtensaState *env = NULL;
-    MemoryRegion *ram, *rom, *system_io;
-    DriveInfo *dinfo;
-    pflash_t *flash = NULL;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    int n;
-
-    if (!cpu_model) {
-        cpu_model = XTENSA_DEFAULT_CPU_MODEL;
-    }
-
-    for (n = 0; n < smp_cpus; n++) {
-        cpu = cpu_xtensa_init(cpu_model);
-        if (cpu == NULL) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        env = &cpu->env;
-
-        env->sregs[PRID] = n;
-        qemu_register_reset(lx60_reset, cpu);
-        /* Need MMU initialized prior to ELF loading,
-         * so that ELF gets loaded into virtual addresses
-         */
-        cpu_reset(CPU(cpu));
-    }
-
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "lx60.dram", args->ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(system_memory, 0, ram);
-
-    system_io = g_malloc(sizeof(*system_io));
-    memory_region_init(system_io, "lx60.io", 224 * 1024 * 1024);
-    memory_region_add_subregion(system_memory, 0xf0000000, system_io);
-    lx60_fpga_init(system_io, 0x0d020000);
-    if (nd_table[0].used) {
-        lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000,
-                xtensa_get_extint(env, 1), nd_table);
-    }
-
-    if (!serial_hds[0]) {
-        serial_hds[0] = qemu_chr_new("serial0", "null", NULL);
-    }
-
-    serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0),
-            115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (dinfo) {
-        flash = pflash_cfi01_register(0xf8000000,
-                NULL, "lx60.io.flash", board->flash_size,
-                dinfo->bdrv, board->flash_sector_size,
-                board->flash_size / board->flash_sector_size,
-                4, 0x0000, 0x0000, 0x0000, 0x0000, be);
-        if (flash == NULL) {
-            fprintf(stderr, "Unable to mount pflash\n");
-            exit(1);
-        }
-    }
-
-    /* Use presence of kernel file name as 'boot from SRAM' switch. */
-    if (kernel_filename) {
-        rom = g_malloc(sizeof(*rom));
-        memory_region_init_ram(rom, "lx60.sram", board->sram_size);
-        vmstate_register_ram_global(rom);
-        memory_region_add_subregion(system_memory, 0xfe000000, rom);
-
-        /* Put kernel bootparameters to the end of that SRAM */
-        if (kernel_cmdline) {
-            size_t cmdline_size = strlen(kernel_cmdline) + 1;
-            size_t bp_size = sizeof(BpTag[4]) + cmdline_size;
-            uint32_t tagptr = (0xfe000000 + board->sram_size - bp_size) & ~0xff;
-
-            env->regs[2] = tagptr;
-
-            tagptr = put_tag(tagptr, 0x7b0b, 0, NULL);
-            if (cmdline_size > 1) {
-                tagptr = put_tag(tagptr, 0x1001,
-                        cmdline_size, kernel_cmdline);
-            }
-            tagptr = put_tag(tagptr, 0x7e0b, 0, NULL);
-        }
-        uint64_t elf_entry;
-        uint64_t elf_lowaddr;
-        int success = load_elf(kernel_filename, translate_phys_addr, env,
-                &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0);
-        if (success > 0) {
-            env->pc = elf_entry;
-        }
-    } else {
-        if (flash) {
-            MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash);
-            MemoryRegion *flash_io = g_malloc(sizeof(*flash_io));
-
-            memory_region_init_alias(flash_io, "lx60.flash",
-                    flash_mr, 0, board->flash_size);
-            memory_region_add_subregion(system_memory, 0xfe000000,
-                    flash_io);
-        }
-    }
-}
-
-static void xtensa_lx60_init(QEMUMachineInitArgs *args)
-{
-    static const LxBoardDesc lx60_board = {
-        .flash_size = 0x400000,
-        .flash_sector_size = 0x10000,
-        .sram_size = 0x20000,
-    };
-    lx_init(&lx60_board, args);
-}
-
-static void xtensa_lx200_init(QEMUMachineInitArgs *args)
-{
-    static const LxBoardDesc lx200_board = {
-        .flash_size = 0x1000000,
-        .flash_sector_size = 0x20000,
-        .sram_size = 0x2000000,
-    };
-    lx_init(&lx200_board, args);
-}
-
-static QEMUMachine xtensa_lx60_machine = {
-    .name = "lx60",
-    .desc = "lx60 EVB (" XTENSA_DEFAULT_CPU_MODEL ")",
-    .init = xtensa_lx60_init,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine xtensa_lx200_machine = {
-    .name = "lx200",
-    .desc = "lx200 EVB (" XTENSA_DEFAULT_CPU_MODEL ")",
-    .init = xtensa_lx200_init,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void xtensa_lx_machines_init(void)
-{
-    qemu_register_machine(&xtensa_lx60_machine);
-    qemu_register_machine(&xtensa_lx200_machine);
-}
-
-machine_init(xtensa_lx_machines_init);
diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
deleted file mode 100644 (file)
index 97d36be..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the Open Source and Linux Lab nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "hw.h"
-#include "qemu/log.h"
-#include "qemu/timer.h"
-
-void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d)
-{
-    uint32_t old_ccount = env->sregs[CCOUNT];
-
-    env->sregs[CCOUNT] += d;
-
-    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
-        int i;
-        for (i = 0; i < env->config->nccompare; ++i) {
-            if (env->sregs[CCOMPARE + i] - old_ccount <= d) {
-                xtensa_timer_irq(env, i, 1);
-            }
-        }
-    }
-}
-
-void check_interrupts(CPUXtensaState *env)
-{
-    int minlevel = xtensa_get_cintlevel(env);
-    uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
-    int level;
-
-    /* If the CPU is halted advance CCOUNT according to the vm_clock time
-     * elapsed since the moment when it was advanced last time.
-     */
-    if (env->halted) {
-        int64_t now = qemu_get_clock_ns(vm_clock);
-
-        xtensa_advance_ccount(env,
-                muldiv64(now - env->halt_clock,
-                    env->config->clock_freq_khz, 1000000));
-        env->halt_clock = now;
-    }
-    for (level = env->config->nlevel; level > minlevel; --level) {
-        if (env->config->level_mask[level] & int_set_enabled) {
-            env->pending_irq_level = level;
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
-            qemu_log_mask(CPU_LOG_INT,
-                    "%s level = %d, cintlevel = %d, "
-                    "pc = %08x, a0 = %08x, ps = %08x, "
-                    "intset = %08x, intenable = %08x, "
-                    "ccount = %08x\n",
-                    __func__, level, xtensa_get_cintlevel(env),
-                    env->pc, env->regs[0], env->sregs[PS],
-                    env->sregs[INTSET], env->sregs[INTENABLE],
-                    env->sregs[CCOUNT]);
-            return;
-        }
-    }
-    env->pending_irq_level = 0;
-    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-}
-
-static void xtensa_set_irq(void *opaque, int irq, int active)
-{
-    CPUXtensaState *env = opaque;
-
-    if (irq >= env->config->ninterrupt) {
-        qemu_log("%s: bad IRQ %d\n", __func__, irq);
-    } else {
-        uint32_t irq_bit = 1 << irq;
-
-        if (active) {
-            env->sregs[INTSET] |= irq_bit;
-        } else if (env->config->interrupt[irq].inttype == INTTYPE_LEVEL) {
-            env->sregs[INTSET] &= ~irq_bit;
-        }
-
-        check_interrupts(env);
-    }
-}
-
-void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active)
-{
-    qemu_set_irq(env->irq_inputs[env->config->timerint[id]], active);
-}
-
-void xtensa_rearm_ccompare_timer(CPUXtensaState *env)
-{
-    int i;
-    uint32_t wake_ccount = env->sregs[CCOUNT] - 1;
-
-    for (i = 0; i < env->config->nccompare; ++i) {
-        if (env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] <
-                wake_ccount - env->sregs[CCOUNT]) {
-            wake_ccount = env->sregs[CCOMPARE + i];
-        }
-    }
-    env->wake_ccount = wake_ccount;
-    qemu_mod_timer(env->ccompare_timer, env->halt_clock +
-            muldiv64(wake_ccount - env->sregs[CCOUNT],
-                1000000, env->config->clock_freq_khz));
-}
-
-static void xtensa_ccompare_cb(void *opaque)
-{
-    XtensaCPU *cpu = opaque;
-    CPUXtensaState *env = &cpu->env;
-
-    if (env->halted) {
-        env->halt_clock = qemu_get_clock_ns(vm_clock);
-        xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]);
-        if (!cpu_has_work(CPU(cpu))) {
-            env->sregs[CCOUNT] = env->wake_ccount + 1;
-            xtensa_rearm_ccompare_timer(env);
-        }
-    }
-}
-
-void xtensa_irq_init(CPUXtensaState *env)
-{
-    XtensaCPU *cpu = xtensa_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(
-            xtensa_set_irq, env, env->config->ninterrupt);
-    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT) &&
-            env->config->nccompare > 0) {
-        env->ccompare_timer =
-            qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, cpu);
-    }
-}
-
-void *xtensa_get_extint(CPUXtensaState *env, unsigned extint)
-{
-    if (extint < env->config->nextint) {
-        unsigned irq = env->config->extint[extint];
-        return env->irq_inputs[irq];
-    } else {
-        qemu_log("%s: trying to acquire invalid external interrupt %d\n",
-                __func__, extint);
-        return NULL;
-    }
-}
diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c
deleted file mode 100644 (file)
index 864e57c..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the Open Source and Linux Lab nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "sysemu/sysemu.h"
-#include "boards.h"
-#include "loader.h"
-#include "elf.h"
-#include "exec/memory.h"
-#include "exec/address-spaces.h"
-
-static uint64_t translate_phys_addr(void *env, uint64_t addr)
-{
-    return cpu_get_phys_page_debug(env, addr);
-}
-
-static void sim_reset(void *opaque)
-{
-    XtensaCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-static void xtensa_sim_init(QEMUMachineInitArgs *args)
-{
-    XtensaCPU *cpu = NULL;
-    CPUXtensaState *env = NULL;
-    MemoryRegion *ram, *rom;
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    int n;
-
-    if (!cpu_model) {
-        cpu_model = XTENSA_DEFAULT_CPU_MODEL;
-    }
-
-    for (n = 0; n < smp_cpus; n++) {
-        cpu = cpu_xtensa_init(cpu_model);
-        if (cpu == NULL) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        env = &cpu->env;
-
-        env->sregs[PRID] = n;
-        qemu_register_reset(sim_reset, cpu);
-        /* Need MMU initialized prior to ELF loading,
-         * so that ELF gets loaded into virtual addresses
-         */
-        sim_reset(cpu);
-    }
-
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "xtensa.sram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(get_system_memory(), 0, ram);
-
-    rom = g_malloc(sizeof(*rom));
-    memory_region_init_ram(rom, "xtensa.rom", 0x1000);
-    vmstate_register_ram_global(rom);
-    memory_region_add_subregion(get_system_memory(), 0xfe000000, rom);
-
-    if (kernel_filename) {
-        uint64_t elf_entry;
-        uint64_t elf_lowaddr;
-#ifdef TARGET_WORDS_BIGENDIAN
-        int success = load_elf(kernel_filename, translate_phys_addr, env,
-                &elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
-#else
-        int success = load_elf(kernel_filename, translate_phys_addr, env,
-                &elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
-#endif
-        if (success > 0) {
-            env->pc = elf_entry;
-        }
-    }
-}
-
-static QEMUMachine xtensa_sim_machine = {
-    .name = "sim",
-    .desc = "sim machine (" XTENSA_DEFAULT_CPU_MODEL ")",
-    .is_default = true,
-    .init = xtensa_sim_init,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void xtensa_sim_machine_init(void)
-{
-    qemu_register_machine(&xtensa_sim_machine);
-}
-
-machine_init(xtensa_sim_machine_init);
diff --git a/hw/z2.c b/hw/z2.c
deleted file mode 100644 (file)
index 731550f..0000000
--- a/hw/z2.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * PXA270-based Zipit Z2 device
- *
- * Copyright (c) 2011 by Vasily Khoruzhick <anarsoul@gmail.com>
- *
- * Code is based on mainstone platform.
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "hw.h"
-#include "pxa.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "i2c.h"
-#include "ssi.h"
-#include "boards.h"
-#include "sysemu/sysemu.h"
-#include "flash.h"
-#include "sysemu/blockdev.h"
-#include "ui/console.h"
-#include "audio/audio.h"
-#include "exec/address-spaces.h"
-
-#ifdef DEBUG_Z2
-#define DPRINTF(fmt, ...) \
-        printf(fmt, ## __VA_ARGS__)
-#else
-#define DPRINTF(fmt, ...)
-#endif
-
-static struct keymap map[0x100] = {
-    [0 ... 0xff] = { -1, -1 },
-    [0x3b] = {0, 0}, /* Option = F1 */
-    [0xc8] = {0, 1}, /* Up */
-    [0xd0] = {0, 2}, /* Down */
-    [0xcb] = {0, 3}, /* Left */
-    [0xcd] = {0, 4}, /* Right */
-    [0xcf] = {0, 5}, /* End */
-    [0x0d] = {0, 6}, /* KPPLUS */
-    [0xc7] = {1, 0}, /* Home */
-    [0x10] = {1, 1}, /* Q */
-    [0x17] = {1, 2}, /* I */
-    [0x22] = {1, 3}, /* G */
-    [0x2d] = {1, 4}, /* X */
-    [0x1c] = {1, 5}, /* Enter */
-    [0x0c] = {1, 6}, /* KPMINUS */
-    [0xc9] = {2, 0}, /* PageUp */
-    [0x11] = {2, 1}, /* W */
-    [0x18] = {2, 2}, /* O */
-    [0x23] = {2, 3}, /* H */
-    [0x2e] = {2, 4}, /* C */
-    [0x38] = {2, 5}, /* LeftAlt */
-    [0xd1] = {3, 0}, /* PageDown */
-    [0x12] = {3, 1}, /* E */
-    [0x19] = {3, 2}, /* P */
-    [0x24] = {3, 3}, /* J */
-    [0x2f] = {3, 4}, /* V */
-    [0x2a] = {3, 5}, /* LeftShift */
-    [0x01] = {4, 0}, /* Esc */
-    [0x13] = {4, 1}, /* R */
-    [0x1e] = {4, 2}, /* A */
-    [0x25] = {4, 3}, /* K */
-    [0x30] = {4, 4}, /* B */
-    [0x1d] = {4, 5}, /* LeftCtrl */
-    [0x0f] = {5, 0}, /* Tab */
-    [0x14] = {5, 1}, /* T */
-    [0x1f] = {5, 2}, /* S */
-    [0x26] = {5, 3}, /* L */
-    [0x31] = {5, 4}, /* N */
-    [0x39] = {5, 5}, /* Space */
-    [0x3c] = {6, 0}, /* Stop = F2 */
-    [0x15] = {6, 1}, /* Y */
-    [0x20] = {6, 2}, /* D */
-    [0x0e] = {6, 3}, /* Backspace */
-    [0x32] = {6, 4}, /* M */
-    [0x33] = {6, 5}, /* Comma */
-    [0x3d] = {7, 0}, /* Play = F3 */
-    [0x16] = {7, 1}, /* U */
-    [0x21] = {7, 2}, /* F */
-    [0x2c] = {7, 3}, /* Z */
-    [0x27] = {7, 4}, /* Semicolon */
-    [0x34] = {7, 5}, /* Dot */
-};
-
-#define Z2_RAM_SIZE     0x02000000
-#define Z2_FLASH_BASE   0x00000000
-#define Z2_FLASH_SIZE   0x00800000
-
-static struct arm_boot_info z2_binfo = {
-    .loader_start   = PXA2XX_SDRAM_BASE,
-    .ram_size       = Z2_RAM_SIZE,
-};
-
-#define Z2_GPIO_SD_DETECT   96
-#define Z2_GPIO_AC_IN       0
-#define Z2_GPIO_KEY_ON      1
-#define Z2_GPIO_LCD_CS      88
-
-typedef struct {
-    SSISlave ssidev;
-    int32_t selected;
-    int32_t enabled;
-    uint8_t buf[3];
-    uint32_t cur_reg;
-    int pos;
-} ZipitLCD;
-
-static uint32_t zipit_lcd_transfer(SSISlave *dev, uint32_t value)
-{
-    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
-    uint16_t val;
-    if (z->selected) {
-        z->buf[z->pos] = value & 0xff;
-        z->pos++;
-    }
-    if (z->pos == 3) {
-        switch (z->buf[0]) {
-        case 0x74:
-            DPRINTF("%s: reg: 0x%.2x\n", __func__, z->buf[2]);
-            z->cur_reg = z->buf[2];
-            break;
-        case 0x76:
-            val = z->buf[1] << 8 | z->buf[2];
-            DPRINTF("%s: value: 0x%.4x\n", __func__, val);
-            if (z->cur_reg == 0x22 && val == 0x0000) {
-                z->enabled = 1;
-                printf("%s: LCD enabled\n", __func__);
-            } else if (z->cur_reg == 0x10 && val == 0x0000) {
-                z->enabled = 0;
-                printf("%s: LCD disabled\n", __func__);
-            }
-            break;
-        default:
-            DPRINTF("%s: unknown command!\n", __func__);
-            break;
-        }
-        z->pos = 0;
-    }
-    return 0;
-}
-
-static void z2_lcd_cs(void *opaque, int line, int level)
-{
-    ZipitLCD *z2_lcd = opaque;
-    z2_lcd->selected = !level;
-}
-
-static int zipit_lcd_init(SSISlave *dev)
-{
-    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
-    z->selected = 0;
-    z->enabled = 0;
-    z->pos = 0;
-
-    return 0;
-}
-
-static VMStateDescription vmstate_zipit_lcd_state = {
-    .name = "zipit-lcd",
-    .version_id = 2,
-    .minimum_version_id = 2,
-    .minimum_version_id_old = 2,
-    .fields = (VMStateField[]) {
-        VMSTATE_SSI_SLAVE(ssidev, ZipitLCD),
-        VMSTATE_INT32(selected, ZipitLCD),
-        VMSTATE_INT32(enabled, ZipitLCD),
-        VMSTATE_BUFFER(buf, ZipitLCD),
-        VMSTATE_UINT32(cur_reg, ZipitLCD),
-        VMSTATE_INT32(pos, ZipitLCD),
-        VMSTATE_END_OF_LIST(),
-    }
-};
-
-static void zipit_lcd_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
-
-    k->init = zipit_lcd_init;
-    k->transfer = zipit_lcd_transfer;
-    dc->vmsd = &vmstate_zipit_lcd_state;
-}
-
-static const TypeInfo zipit_lcd_info = {
-    .name          = "zipit-lcd",
-    .parent        = TYPE_SSI_SLAVE,
-    .instance_size = sizeof(ZipitLCD),
-    .class_init    = zipit_lcd_class_init,
-};
-
-typedef struct {
-    I2CSlave i2c;
-    int len;
-    uint8_t buf[3];
-} AER915State;
-
-static int aer915_send(I2CSlave *i2c, uint8_t data)
-{
-    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
-    s->buf[s->len] = data;
-    if (s->len++ > 2) {
-        DPRINTF("%s: message too long (%i bytes)\n",
-            __func__, s->len);
-        return 1;
-    }
-
-    if (s->len == 2) {
-        DPRINTF("%s: reg %d value 0x%02x\n", __func__,
-                s->buf[0], s->buf[1]);
-    }
-
-    return 0;
-}
-
-static void aer915_event(I2CSlave *i2c, enum i2c_event event)
-{
-    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
-    switch (event) {
-    case I2C_START_SEND:
-        s->len = 0;
-        break;
-    case I2C_START_RECV:
-        if (s->len != 1) {
-            DPRINTF("%s: short message!?\n", __func__);
-        }
-        break;
-    case I2C_FINISH:
-        break;
-    default:
-        break;
-    }
-}
-
-static int aer915_recv(I2CSlave *slave)
-{
-    int retval = 0x00;
-    AER915State *s = FROM_I2C_SLAVE(AER915State, slave);
-
-    switch (s->buf[0]) {
-    /* Return hardcoded battery voltage,
-     * 0xf0 means ~4.1V
-     */
-    case 0x02:
-        retval = 0xf0;
-        break;
-    /* Return 0x00 for other regs,
-     * we don't know what they are for,
-     * anyway they return 0x00 on real hardware.
-     */
-    default:
-        break;
-    }
-
-    return retval;
-}
-
-static int aer915_init(I2CSlave *i2c)
-{
-    /* Nothing to do.  */
-    return 0;
-}
-
-static VMStateDescription vmstate_aer915_state = {
-    .name = "aer915",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_INT32(len, AER915State),
-        VMSTATE_BUFFER(buf, AER915State),
-        VMSTATE_END_OF_LIST(),
-    }
-};
-
-static void aer915_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
-
-    k->init = aer915_init;
-    k->event = aer915_event;
-    k->recv = aer915_recv;
-    k->send = aer915_send;
-    dc->vmsd = &vmstate_aer915_state;
-}
-
-static const TypeInfo aer915_info = {
-    .name          = "aer915",
-    .parent        = TYPE_I2C_SLAVE,
-    .instance_size = sizeof(AER915State),
-    .class_init    = aer915_class_init,
-};
-
-static void z2_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    uint32_t sector_len = 0x10000;
-    PXA2xxState *mpu;
-    DriveInfo *dinfo;
-    int be;
-    void *z2_lcd;
-    i2c_bus *bus;
-    DeviceState *wm;
-
-    if (!cpu_model) {
-        cpu_model = "pxa270-c5";
-    }
-
-    /* Setup CPU & memory */
-    mpu = pxa270_init(address_space_mem, z2_binfo.ram_size, cpu_model);
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "Flash image must be given with the "
-                "'pflash' parameter\n");
-        exit(1);
-    }
-
-    if (!pflash_cfi01_register(Z2_FLASH_BASE,
-                               NULL, "z2.flash0", Z2_FLASH_SIZE,
-                               dinfo->bdrv, sector_len,
-                               Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
-                               be)) {
-        fprintf(stderr, "qemu: Error registering flash memory.\n");
-        exit(1);
-    }
-
-    /* setup keypad */
-    pxa27x_register_keypad(mpu->kp, map, 0x100);
-
-    /* MMC/SD host */
-    pxa2xx_mmci_handlers(mpu->mmc,
-        NULL,
-        qdev_get_gpio_in(mpu->gpio, Z2_GPIO_SD_DETECT));
-
-    type_register_static(&zipit_lcd_info);
-    type_register_static(&aer915_info);
-    z2_lcd = ssi_create_slave(mpu->ssp[1], "zipit-lcd");
-    bus = pxa2xx_i2c_bus(mpu->i2c[0]);
-    i2c_create_slave(bus, "aer915", 0x55);
-    wm = i2c_create_slave(bus, "wm8750", 0x1b);
-    mpu->i2s->opaque = wm;
-    mpu->i2s->codec_out = wm8750_dac_dat;
-    mpu->i2s->codec_in = wm8750_adc_dat;
-    wm8750_data_req_set(wm, mpu->i2s->data_req, mpu->i2s);
-
-    qdev_connect_gpio_out(mpu->gpio, Z2_GPIO_LCD_CS,
-        qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
-
-    if (kernel_filename) {
-        z2_binfo.kernel_filename = kernel_filename;
-        z2_binfo.kernel_cmdline = kernel_cmdline;
-        z2_binfo.initrd_filename = initrd_filename;
-        z2_binfo.board_id = 0x6dd;
-        arm_load_kernel(mpu->cpu, &z2_binfo);
-    }
-}
-
-static QEMUMachine z2_machine = {
-    .name = "z2",
-    .desc = "Zipit Z2 (PXA27x)",
-    .init = z2_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void z2_machine_init(void)
-{
-    qemu_register_machine(&z2_machine);
-}
-
-machine_init(z2_machine_init);
index 2defe3b48dd63cc4dd0ea8c1b2a5b463b615b91b..7d3258cc663a890801853c84d3834f89c05cfcae 100644 (file)
@@ -15,9 +15,9 @@
  * 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 "hw.h"
-#include "sharpsl.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sharpsl.h"
+#include "hw/sysbus.h"
 
 #undef REG_FMT
 #define REG_FMT                        "0x%02lx"
index 27b00f07d4ad6bbd7e76de0dace3dcacf77d0efe..84183272618406869555ee32a3b156728dabb0b4 100644 (file)
@@ -14,9 +14,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 
 #ifdef ZYNQ_ARM_SLCR_ERR_DEBUG
index f27276c2d8363e4365f3e859616c6620b842c4d5..94a409b708ffbdfdc7e7ba19d71020f73f15f9d9 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef QEMU_VMSTATE_H
 #define QEMU_VMSTATE_H 1
 
+#include <migration/qemu-file.h>
+
 typedef void SaveStateHandler(QEMUFile *f, void *opaque);
 typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
 
diff --git a/include/monitor/qdev.h b/include/monitor/qdev.h
new file mode 100644 (file)
index 0000000..8d16e11
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef QEMU_QDEV_MONITOR_H
+#define QEMU_QDEV_MONITOR_H
+
+#include "hw/qdev-core.h"
+#include "monitor/monitor.h"
+
+/*** monitor commands ***/
+
+void do_info_qtree(Monitor *mon, const QDict *qdict);
+void do_info_qdm(Monitor *mon, const QDict *qdict);
+int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int qdev_device_help(QemuOpts *opts);
+DeviceState *qdev_device_add(QemuOpts *opts);
+
+#endif
diff --git a/include/qemu/fifo8.h b/include/qemu/fifo8.h
new file mode 100644 (file)
index 0000000..d318f71
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef FIFO_H
+#define FIFO_H
+
+#include "migration/vmstate.h"
+
+typedef struct {
+    /* All fields are private */
+    uint8_t *data;
+    uint32_t capacity;
+    uint32_t head;
+    uint32_t num;
+} Fifo8;
+
+/**
+ * fifo8_create:
+ * @fifo: struct Fifo8 to initialise with new FIFO
+ * @capacity: capacity of the newly created FIFO
+ *
+ * Create a FIFO of the specified size. Clients should call fifo8_destroy()
+ * when finished using the fifo. The FIFO is initially empty.
+ */
+
+void fifo8_create(Fifo8 *fifo, uint32_t capacity);
+
+/**
+ * fifo8_destroy:
+ * @fifo: FIFO to cleanup
+ *
+ * Cleanup a FIFO created with fifo8_create(). Frees memory created for FIFO
+  *storage. The FIFO is no longer usable after this has been called.
+ */
+
+void fifo8_destroy(Fifo8 *fifo);
+
+/**
+ * fifo8_push:
+ * @fifo: FIFO to push to
+ * @data: data byte to push
+ *
+ * Push a data byte to the FIFO. Behaviour is undefined if the FIFO is full.
+ * Clients are responsible for checking for fullness using fifo8_is_full().
+ */
+
+void fifo8_push(Fifo8 *fifo, uint8_t data);
+
+/**
+ * fifo8_pop:
+ * @fifo: fifo to pop from
+ *
+ * Pop a data byte from the FIFO. Behaviour is undefined if the FIFO is empty.
+ * Clients are responsible for checking for emptyness using fifo8_is_empty().
+ *
+ * Returns: The popped data byte.
+ */
+
+uint8_t fifo8_pop(Fifo8 *fifo);
+
+/**
+ * fifo8_reset:
+ * @fifo: FIFO to reset
+ *
+ * Reset a FIFO. All data is discarded and the FIFO is emptied.
+ */
+
+void fifo8_reset(Fifo8 *fifo);
+
+/**
+ * fifo8_is_empty:
+ * @fifo: FIFO to check
+ *
+ * Check if a FIFO is empty.
+ *
+ * Returns: True if the fifo is empty, false otherwise.
+ */
+
+bool fifo8_is_empty(Fifo8 *fifo);
+
+/**
+ * fifo8_is_full:
+ * @fifo: FIFO to check
+ *
+ * Check if a FIFO is full.
+ *
+ * Returns: True if the fifo is full, false otherwise.
+ */
+
+bool fifo8_is_full(Fifo8 *fifo);
+
+extern const VMStateDescription vmstate_fifo8;
+
+#define VMSTATE_FIFO8(_field, _state) {                              \
+    .name       = (stringify(_field)),                               \
+    .size       = sizeof(Fifo8),                                     \
+    .vmsd       = &vmstate_fifo8,                                    \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = vmstate_offset_value(_state, _field, Fifo8),       \
+}
+
+#endif /* FIFO_H */
index 32a6e74fd951748e4e7d2297c165d5f72622604b..c48530bd550ee6c60067a32fcb7f5391b359ba67 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -23,7 +23,7 @@
  */
 #include <dirent.h>
 #include "hw/hw.h"
-#include "hw/qdev.h"
+#include "monitor/qdev.h"
 #include "hw/usb.h"
 #include "hw/pcmcia.h"
 #include "hw/pc.h"
diff --git a/qdev-monitor.c b/qdev-monitor.c
new file mode 100644 (file)
index 0000000..9a78ccf
--- /dev/null
@@ -0,0 +1,684 @@
+/*
+ *  Dynamic device configuration and creation.
+ *
+ *  Copyright (c) 2009 CodeSourcery
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/qdev.h"
+#include "monitor/monitor.h"
+#include "monitor/qdev.h"
+#include "qmp-commands.h"
+#include "sysemu/arch_init.h"
+#include "qemu/config-file.h"
+
+/*
+ * Aliases were a bad idea from the start.  Let's keep them
+ * from spreading further.
+ */
+typedef struct QDevAlias
+{
+    const char *typename;
+    const char *alias;
+    uint32_t arch_mask;
+} QDevAlias;
+
+static const QDevAlias qdev_alias_table[] = {
+    { "virtio-blk-pci", "virtio-blk", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
+    { "virtio-net-pci", "virtio-net", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
+    { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
+    { "virtio-balloon-pci", "virtio-balloon",
+            QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
+    { "virtio-blk-s390", "virtio-blk", QEMU_ARCH_S390X },
+    { "virtio-net-s390", "virtio-net", QEMU_ARCH_S390X },
+    { "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X },
+    { "lsi53c895a", "lsi" },
+    { "ich9-ahci", "ahci" },
+    { "kvm-pci-assign", "pci-assign" },
+    { }
+};
+
+static const char *qdev_class_get_alias(DeviceClass *dc)
+{
+    const char *typename = object_class_get_name(OBJECT_CLASS(dc));
+    int i;
+
+    for (i = 0; qdev_alias_table[i].typename; i++) {
+        if (qdev_alias_table[i].arch_mask &&
+            !(qdev_alias_table[i].arch_mask & arch_type)) {
+            continue;
+        }
+
+        if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
+            return qdev_alias_table[i].alias;
+        }
+    }
+
+    return NULL;
+}
+
+static bool qdev_class_has_alias(DeviceClass *dc)
+{
+    return (qdev_class_get_alias(dc) != NULL);
+}
+
+static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
+{
+    DeviceClass *dc;
+    bool *show_no_user = opaque;
+
+    dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
+
+    if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
+        return;
+    }
+
+    error_printf("name \"%s\"", object_class_get_name(klass));
+    if (dc->bus_type) {
+        error_printf(", bus %s", dc->bus_type);
+    }
+    if (qdev_class_has_alias(dc)) {
+        error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
+    }
+    if (dc->desc) {
+        error_printf(", desc \"%s\"", dc->desc);
+    }
+    if (dc->no_user) {
+        error_printf(", no-user");
+    }
+    error_printf("\n");
+}
+
+static int set_property(const char *name, const char *value, void *opaque)
+{
+    DeviceState *dev = opaque;
+
+    if (strcmp(name, "driver") == 0)
+        return 0;
+    if (strcmp(name, "bus") == 0)
+        return 0;
+
+    if (qdev_prop_parse(dev, name, value) == -1) {
+        return -1;
+    }
+    return 0;
+}
+
+static const char *find_typename_by_alias(const char *alias)
+{
+    int i;
+
+    for (i = 0; qdev_alias_table[i].alias; i++) {
+        if (qdev_alias_table[i].arch_mask &&
+            !(qdev_alias_table[i].arch_mask & arch_type)) {
+            continue;
+        }
+
+        if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
+            return qdev_alias_table[i].typename;
+        }
+    }
+
+    return NULL;
+}
+
+int qdev_device_help(QemuOpts *opts)
+{
+    const char *driver;
+    Property *prop;
+    ObjectClass *klass;
+
+    driver = qemu_opt_get(opts, "driver");
+    if (driver && is_help_option(driver)) {
+        bool show_no_user = false;
+        object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
+        return 1;
+    }
+
+    if (!driver || !qemu_opt_has_help_opt(opts)) {
+        return 0;
+    }
+
+    klass = object_class_by_name(driver);
+    if (!klass) {
+        const char *typename = find_typename_by_alias(driver);
+
+        if (typename) {
+            driver = typename;
+            klass = object_class_by_name(driver);
+        }
+    }
+
+    if (!klass) {
+        return 0;
+    }
+    do {
+        for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
+            /*
+             * TODO Properties without a parser are just for dirty hacks.
+             * qdev_prop_ptr is the only such PropertyInfo.  It's marked
+             * for removal.  This conditional should be removed along with
+             * it.
+             */
+            if (!prop->info->set) {
+                continue;           /* no way to set it, don't show */
+            }
+            error_printf("%s.%s=%s\n", driver, prop->name,
+                         prop->info->legacy_name ?: prop->info->name);
+        }
+        klass = object_class_get_parent(klass);
+    } while (klass != object_class_by_name(TYPE_DEVICE));
+    return 1;
+}
+
+static Object *qdev_get_peripheral(void)
+{
+    static Object *dev;
+
+    if (dev == NULL) {
+        dev = container_get(qdev_get_machine(), "/peripheral");
+    }
+
+    return dev;
+}
+
+static Object *qdev_get_peripheral_anon(void)
+{
+    static Object *dev;
+
+    if (dev == NULL) {
+        dev = container_get(qdev_get_machine(), "/peripheral-anon");
+    }
+
+    return dev;
+}
+
+static void qbus_list_bus(DeviceState *dev)
+{
+    BusState *child;
+    const char *sep = " ";
+
+    error_printf("child busses at \"%s\":",
+                 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
+    QLIST_FOREACH(child, &dev->child_bus, sibling) {
+        error_printf("%s\"%s\"", sep, child->name);
+        sep = ", ";
+    }
+    error_printf("\n");
+}
+
+static void qbus_list_dev(BusState *bus)
+{
+    BusChild *kid;
+    const char *sep = " ";
+
+    error_printf("devices at \"%s\":", bus->name);
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
+        if (dev->id)
+            error_printf("/\"%s\"", dev->id);
+        sep = ", ";
+    }
+    error_printf("\n");
+}
+
+static BusState *qbus_find_bus(DeviceState *dev, char *elem)
+{
+    BusState *child;
+
+    QLIST_FOREACH(child, &dev->child_bus, sibling) {
+        if (strcmp(child->name, elem) == 0) {
+            return child;
+        }
+    }
+    return NULL;
+}
+
+static DeviceState *qbus_find_dev(BusState *bus, char *elem)
+{
+    BusChild *kid;
+
+    /*
+     * try to match in order:
+     *   (1) instance id, if present
+     *   (2) driver name
+     *   (3) driver alias, if present
+     */
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
+            return dev;
+        }
+    }
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
+            return dev;
+        }
+    }
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        DeviceClass *dc = DEVICE_GET_CLASS(dev);
+
+        if (qdev_class_has_alias(dc) &&
+            strcmp(qdev_class_get_alias(dc), elem) == 0) {
+            return dev;
+        }
+    }
+    return NULL;
+}
+
+static BusState *qbus_find_recursive(BusState *bus, const char *name,
+                                     const char *bus_typename)
+{
+    BusClass *bus_class = BUS_GET_CLASS(bus);
+    BusChild *kid;
+    BusState *child, *ret;
+    int match = 1;
+
+    if (name && (strcmp(bus->name, name) != 0)) {
+        match = 0;
+    }
+    if (bus_typename && !object_dynamic_cast(OBJECT(bus), bus_typename)) {
+        match = 0;
+    }
+    if ((bus_class->max_dev != 0) && (bus_class->max_dev <= bus->max_index)) {
+        if (name != NULL) {
+            /* bus was explicitly specified: return an error. */
+            qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full",
+                          bus->name);
+            return NULL;
+        } else {
+            /* bus was not specified: try to find another one. */
+            match = 0;
+        }
+    }
+    if (match) {
+        return bus;
+    }
+
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        QLIST_FOREACH(child, &dev->child_bus, sibling) {
+            ret = qbus_find_recursive(child, name, bus_typename);
+            if (ret) {
+                return ret;
+            }
+        }
+    }
+    return NULL;
+}
+
+static BusState *qbus_find(const char *path)
+{
+    DeviceState *dev;
+    BusState *bus;
+    char elem[128];
+    int pos, len;
+
+    /* find start element */
+    if (path[0] == '/') {
+        bus = sysbus_get_default();
+        pos = 0;
+    } else {
+        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
+            assert(!path[0]);
+            elem[0] = len = 0;
+        }
+        bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
+        if (!bus) {
+            qerror_report(QERR_BUS_NOT_FOUND, elem);
+            return NULL;
+        }
+        pos = len;
+    }
+
+    for (;;) {
+        assert(path[pos] == '/' || !path[pos]);
+        while (path[pos] == '/') {
+            pos++;
+        }
+        if (path[pos] == '\0') {
+            return bus;
+        }
+
+        /* find device */
+        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
+            assert(0);
+            elem[0] = len = 0;
+        }
+        pos += len;
+        dev = qbus_find_dev(bus, elem);
+        if (!dev) {
+            qerror_report(QERR_DEVICE_NOT_FOUND, elem);
+            if (!monitor_cur_is_qmp()) {
+                qbus_list_dev(bus);
+            }
+            return NULL;
+        }
+
+        assert(path[pos] == '/' || !path[pos]);
+        while (path[pos] == '/') {
+            pos++;
+        }
+        if (path[pos] == '\0') {
+            /* last specified element is a device.  If it has exactly
+             * one child bus accept it nevertheless */
+            switch (dev->num_child_bus) {
+            case 0:
+                qerror_report(QERR_DEVICE_NO_BUS, elem);
+                return NULL;
+            case 1:
+                return QLIST_FIRST(&dev->child_bus);
+            default:
+                qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
+                if (!monitor_cur_is_qmp()) {
+                    qbus_list_bus(dev);
+                }
+                return NULL;
+            }
+        }
+
+        /* find bus */
+        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
+            assert(0);
+            elem[0] = len = 0;
+        }
+        pos += len;
+        bus = qbus_find_bus(dev, elem);
+        if (!bus) {
+            qerror_report(QERR_BUS_NOT_FOUND, elem);
+            if (!monitor_cur_is_qmp()) {
+                qbus_list_bus(dev);
+            }
+            return NULL;
+        }
+    }
+}
+
+DeviceState *qdev_device_add(QemuOpts *opts)
+{
+    ObjectClass *obj;
+    DeviceClass *k;
+    const char *driver, *path, *id;
+    DeviceState *qdev;
+    BusState *bus;
+
+    driver = qemu_opt_get(opts, "driver");
+    if (!driver) {
+        qerror_report(QERR_MISSING_PARAMETER, "driver");
+        return NULL;
+    }
+
+    /* find driver */
+    obj = object_class_by_name(driver);
+    if (!obj) {
+        const char *typename = find_typename_by_alias(driver);
+
+        if (typename) {
+            driver = typename;
+            obj = object_class_by_name(driver);
+        }
+    }
+
+    if (!obj) {
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
+        return NULL;
+    }
+
+    k = DEVICE_CLASS(obj);
+
+    /* find bus */
+    path = qemu_opt_get(opts, "bus");
+    if (path != NULL) {
+        bus = qbus_find(path);
+        if (!bus) {
+            return NULL;
+        }
+        if (!object_dynamic_cast(OBJECT(bus), k->bus_type)) {
+            qerror_report(QERR_BAD_BUS_FOR_DEVICE,
+                          driver, object_get_typename(OBJECT(bus)));
+            return NULL;
+        }
+    } else {
+        bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type);
+        if (!bus) {
+            qerror_report(QERR_NO_BUS_FOR_DEVICE,
+                          k->bus_type, driver);
+            return NULL;
+        }
+    }
+    if (qdev_hotplug && !bus->allow_hotplug) {
+        qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
+        return NULL;
+    }
+
+    if (!bus) {
+        bus = sysbus_get_default();
+    }
+
+    /* create device, set properties */
+    qdev = DEVICE(object_new(driver));
+    qdev_set_parent_bus(qdev, bus);
+
+    id = qemu_opts_id(opts);
+    if (id) {
+        qdev->id = id;
+    }
+    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
+        qdev_free(qdev);
+        return NULL;
+    }
+    if (qdev->id) {
+        object_property_add_child(qdev_get_peripheral(), qdev->id,
+                                  OBJECT(qdev), NULL);
+    } else {
+        static int anon_count;
+        gchar *name = g_strdup_printf("device[%d]", anon_count++);
+        object_property_add_child(qdev_get_peripheral_anon(), name,
+                                  OBJECT(qdev), NULL);
+        g_free(name);
+    }        
+    if (qdev_init(qdev) < 0) {
+        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
+        return NULL;
+    }
+    qdev->opts = opts;
+    return qdev;
+}
+
+
+#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
+static void qbus_print(Monitor *mon, BusState *bus, int indent);
+
+static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
+                             int indent)
+{
+    if (!props)
+        return;
+    for (; props->name; props++) {
+        Error *err = NULL;
+        char *value;
+        char *legacy_name = g_strdup_printf("legacy-%s", props->name);
+        if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
+            value = object_property_get_str(OBJECT(dev), legacy_name, &err);
+        } else {
+            value = object_property_print(OBJECT(dev), props->name, &err);
+        }
+        g_free(legacy_name);
+
+        if (err) {
+            error_free(err);
+            continue;
+        }
+        qdev_printf("%s = %s\n", props->name,
+                    value && *value ? value : "<null>");
+        g_free(value);
+    }
+}
+
+static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int indent)
+{
+    BusClass *bc = BUS_GET_CLASS(bus);
+
+    if (bc->print_dev) {
+        bc->print_dev(mon, dev, indent);
+    }
+}
+
+static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
+{
+    ObjectClass *class;
+    BusState *child;
+    qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
+                dev->id ? dev->id : "");
+    indent += 2;
+    if (dev->num_gpio_in) {
+        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
+    }
+    if (dev->num_gpio_out) {
+        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
+    }
+    class = object_get_class(OBJECT(dev));
+    do {
+        qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
+        class = object_class_get_parent(class);
+    } while (class != object_class_by_name(TYPE_DEVICE));
+    bus_print_dev(dev->parent_bus, mon, dev, indent);
+    QLIST_FOREACH(child, &dev->child_bus, sibling) {
+        qbus_print(mon, child, indent);
+    }
+}
+
+static void qbus_print(Monitor *mon, BusState *bus, int indent)
+{
+    BusChild *kid;
+
+    qdev_printf("bus: %s\n", bus->name);
+    indent += 2;
+    qdev_printf("type %s\n", object_get_typename(OBJECT(bus)));
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        qdev_print(mon, dev, indent);
+    }
+}
+#undef qdev_printf
+
+void do_info_qtree(Monitor *mon, const QDict *qdict)
+{
+    if (sysbus_get_default())
+        qbus_print(mon, sysbus_get_default(), 0);
+}
+
+void do_info_qdm(Monitor *mon, const QDict *qdict)
+{
+    object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
+}
+
+int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    Error *local_err = NULL;
+    QemuOpts *opts;
+    DeviceState *dev;
+
+    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+    if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
+        qemu_opts_del(opts);
+        return 0;
+    }
+    dev = qdev_device_add(opts);
+    if (!dev) {
+        qemu_opts_del(opts);
+        return -1;
+    }
+    object_unref(OBJECT(dev));
+    return 0;
+}
+
+void qmp_device_del(const char *id, Error **errp)
+{
+    DeviceState *dev;
+
+    dev = qdev_find_recursive(sysbus_get_default(), id);
+    if (NULL == dev) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
+        return;
+    }
+
+    qdev_unplug(dev, errp);
+}
+
+void qdev_machine_init(void)
+{
+    qdev_get_peripheral_anon();
+    qdev_get_peripheral();
+}
+
+QemuOptsList qemu_device_opts = {
+    .name = "device",
+    .implied_opt_name = "driver",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
+    .desc = {
+        /*
+         * no elements => accept any
+         * sanity checking will happen later
+         * when setting device properties
+         */
+        { /* end of list */ }
+    },
+};
+
+QemuOptsList qemu_global_opts = {
+    .name = "global",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
+    .desc = {
+        {
+            .name = "driver",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "property",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "value",
+            .type = QEMU_OPT_STRING,
+        },
+        { /* end of list */ }
+    },
+};
+
+int qemu_global_option(const char *str)
+{
+    char driver[64], property[64];
+    QemuOpts *opts;
+    int rc, offset;
+
+    rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
+    if (rc < 2 || str[offset] != '=') {
+        error_report("can't parse: \"%s\"", str);
+        return -1;
+    }
+
+    opts = qemu_opts_create_nofail(&qemu_global_opts);
+    qemu_opt_set(opts, "driver", driver);
+    qemu_opt_set(opts, "property", property);
+    qemu_opt_set(opts, "value", str+offset+1);
+    return 0;
+}
index b82d6433d213c2186aa6fc2bb93f54bc6d794f85..04aa589c7ebd6e70c64ee3c87eb23ce5978946de 100644 (file)
@@ -535,8 +535,6 @@ int send_all(int fd, const void *_buf, int len1)
 }
 #endif /* !_WIN32 */
 
-#ifndef _WIN32
-
 typedef struct IOWatchPoll
 {
     GSource *src;
@@ -634,6 +632,7 @@ static guint io_add_watch_poll(GIOChannel *channel,
     return tag;
 }
 
+#ifndef _WIN32
 static GIOChannel *io_channel_from_fd(int fd)
 {
     GIOChannel *chan;
@@ -649,6 +648,7 @@ static GIOChannel *io_channel_from_fd(int fd)
 
     return chan;
 }
+#endif
 
 static GIOChannel *io_channel_from_socket(int fd)
 {
@@ -699,6 +699,8 @@ static int io_channel_send_all(GIOChannel *fd, const void *_buf, int len1)
     return len1 - len;
 }
 
+#ifndef _WIN32
+
 typedef struct FDCharDriver {
     CharDriverState *chr;
     GIOChannel *fd_in, *fd_out;
index 6f9334a97fd74410e4dcd3649e8cc5ed044ea559..cd76f2a00c44ebfba28ca52a8f9d158dfeb0ffd3 100644 (file)
@@ -2132,7 +2132,7 @@ gluster[+transport]://[server[:port]]/volname/image[?socket=...]
 
 Example
 @example
-qemu-system-x86_84 --drive file=gluster://192.0.2.1/testvol/a.img
+qemu-system-x86_64 --drive file=gluster://192.0.2.1/testvol/a.img
 @end example
 
 See also @url{http://www.gluster.org}.
index a2603947dbc25b4770768999c18648291a243695..9c55b34354cfd58ea3243578dca2af9576ef772c 100644 (file)
@@ -15,6 +15,7 @@ stub-obj-y += mon-printf.o
 stub-obj-y += mon-print-filename.o
 stub-obj-y += mon-protocol-event.o
 stub-obj-y += mon-set-error.o
+stub-obj-y += pci-drive-hot-add.o
 stub-obj-y += reset.o
 stub-obj-y += set-fd-handler.o
 stub-obj-y += slirp.o
diff --git a/stubs/pci-drive-hot-add.c b/stubs/pci-drive-hot-add.c
new file mode 100644 (file)
index 0000000..1d98145
--- /dev/null
@@ -0,0 +1,10 @@
+#include <monitor/monitor.h>
+#include <sysemu/sysemu.h>
+#include <sysemu/blockdev.h>
+
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo)
+{
+    /* On non-x86 we don't do PCI hotplug */
+    monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
+    return -1;
+}
index c5fd042610f81fad3a91ae5450676c8317e38159..9ab583b860135d8f89a8948bf63f6488345992cb 100644 (file)
@@ -565,8 +565,8 @@ int main(int argc, char **argv)
     qtest_add_func("/rtc/basic/bcd-12h", basic_12h_bcd);
     qtest_add_func("/rtc/set-year/20xx", set_year_20xx);
     qtest_add_func("/rtc/set-year/1980", set_year_1980);
-    qtest_add_func("/rtc/register_b_set_flag", register_b_set_flag);
-    qtest_add_func("/rtc/fuzz-registers", fuzz_registers);
+    qtest_add_func("/rtc/misc/register_b_set_flag", register_b_set_flag);
+    qtest_add_func("/rtc/misc/fuzz-registers", fuzz_registers);
     ret = g_test_run();
 
     if (s) {
index a27ae430320722901f769aeccc0f2fecf37fc983..3064fc7767e88170d419a6c6e179b7c027cff11c 100644 (file)
@@ -460,6 +460,7 @@ scsi_req_data(int target, int lun, int tag, int len) "target %d lun %d tag %d le
 scsi_req_data_canceled(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d"
 scsi_req_dequeue(int target, int lun, int tag) "target %d lun %d tag %d"
 scsi_req_continue(int target, int lun, int tag) "target %d lun %d tag %d"
+scsi_req_continue_canceled(int target, int lun, int tag) "target %d lun %d tag %d"
 scsi_req_parsed(int target, int lun, int tag, int cmd, int mode, int xfer) "target %d lun %d tag %d command %d dir %d length %d"
 scsi_req_parsed_lba(int target, int lun, int tag, int cmd, uint64_t lba) "target %d lun %d tag %d command %d lba %"PRIu64
 scsi_req_parse_bad(int target, int lun, int tag, int cmd) "target %d lun %d tag %d command %d"
index 495a178557bc057b4662a5744ade756b765444ba..cad5ce87dbe7d8f9b0d19bd2fd27b6ce3d8012f5 100644 (file)
@@ -3,6 +3,7 @@ util-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o event_notifier-win
 util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o event_notifier-posix.o
 util-obj-y += envlist.o path.o host-utils.o cache-utils.o module.o
 util-obj-y += bitmap.o bitops.o hbitmap.o
+util-obj-y += fifo8.o
 util-obj-y += acl.o
 util-obj-y += error.o qemu-error.o
 util-obj-$(CONFIG_POSIX) += compatfd.o
diff --git a/util/fifo8.c b/util/fifo8.c
new file mode 100644 (file)
index 0000000..013e903
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Generic FIFO component, implemented as a circular buffer.
+ *
+ * Copyright (c) 2012 Peter A. G. Crosthwaite
+ *
+ * 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.
+ *
+ * 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 "qemu-common.h"
+#include "qemu/fifo8.h"
+
+void fifo8_create(Fifo8 *fifo, uint32_t capacity)
+{
+    fifo->data = g_new(uint8_t, capacity);
+    fifo->capacity = capacity;
+    fifo->head = 0;
+    fifo->num = 0;
+}
+
+void fifo8_destroy(Fifo8 *fifo)
+{
+    g_free(fifo->data);
+}
+
+void fifo8_push(Fifo8 *fifo, uint8_t data)
+{
+    if (fifo->num == fifo->capacity) {
+        abort();
+    }
+    fifo->data[(fifo->head + fifo->num) % fifo->capacity] = data;
+    fifo->num++;
+}
+
+uint8_t fifo8_pop(Fifo8 *fifo)
+{
+    uint8_t ret;
+
+    if (fifo->num == 0) {
+        abort();
+    }
+    ret = fifo->data[fifo->head++];
+    fifo->head %= fifo->capacity;
+    fifo->num--;
+    return ret;
+}
+
+void fifo8_reset(Fifo8 *fifo)
+{
+    fifo->num = 0;
+}
+
+bool fifo8_is_empty(Fifo8 *fifo)
+{
+    return (fifo->num == 0);
+}
+
+bool fifo8_is_full(Fifo8 *fifo)
+{
+    return (fifo->num == fifo->capacity);
+}
+
+const VMStateDescription vmstate_fifo8 = {
+    .name = "Fifo8",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
+        VMSTATE_UINT32(head, Fifo8),
+        VMSTATE_UINT32(num, Fifo8),
+        VMSTATE_END_OF_LIST()
+    }
+};
index c4082610df6fd941a0c9504f163c5b49909a6df4..bd59ac90c1d92d457cb86d755c1f688046ff01c8 100644 (file)
@@ -57,7 +57,7 @@ static const char *qemu_version = QEMU_VERSION;
 int socket_set_cork(int fd, int v)
 {
 #if defined(SOL_TCP) && defined(TCP_CORK)
-    return setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v));
+    return qemu_setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v));
 #else
     return 0;
 #endif
@@ -66,7 +66,7 @@ int socket_set_cork(int fd, int v)
 int socket_set_nodelay(int fd)
 {
     int v = 1;
-    return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
+    return qemu_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
 }
 
 int qemu_madvise(void *addr, size_t len, int advice)
index db6ec03a7832eaaca6094a93897cbde8901638d7..01ca8901cf26cff93c916b806a8d59fc8b009b6a 100644 (file)
@@ -2,6 +2,7 @@
 #include "qemu/error-report.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
+#include "qapi/qmp/qerror.h"
 #include "hw/qdev.h"
 #include "qapi/error.h"
 
diff --git a/vl.c b/vl.c
index 5dc05581f5a554d789a809583f281ee970bdbc28..154f7bae6a691c4a217936343b59e434179dcbe6 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -125,6 +125,7 @@ int main(int argc, char **argv)
 #include "hw/xen.h"
 #include "hw/qdev.h"
 #include "hw/loader.h"
+#include "monitor/qdev.h"
 #include "bt/bt.h"
 #include "net/net.h"
 #include "net/slirp.h"