QOM device refactorings
* QTest coverage for all machines * QOM realize for Milkymist UART * QOM realize for ARM MPCore * device_add bug fixes and cleanups * QOM for PCMCIA/MicroDrive (last legacy IDE device) -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJSeSW3AAoJEPou0S0+fgE/CXAQALxw6JvDBht/S/QaLG9ZrjJQ THsG9sZNSXNea7B4+z5ZJKKWce14vz9hyKqliXykgDqZg7KmPG0ywQT94AcPL0KL ylbeJbNmRr7EbSquV1hxowVNLt9PBWmmhVRpEOw3PB14hSaDTNe4lqq50PE8wJAq 4x1V4xsH5psC2FjHWAfKyaMYZX7XjZ4r00Ir0lbHAa4sIwCskrngoaGMShrxh6RK KA9EoWFACkwEW2fX6lpLYbm35I1cIG1VQIG8cebpMlqrLpFiFceyGfB6S+RlhlXc z+iyQTsO0FYdi7tUpjnsRKmR3cxL3Ea1egP7nzziQkj7K4kVOtWz+ClOwuxw8ZjM Oh5GVz8XLpfegm66YZQItZ+LuZAB2PBTesUFHkf7nC7UTJwzTX6erTYonbQi3xHy /W+AuyNRFQ81HRoHHps/Jb8+6OYEML9079y8PtK1ZmTufZtSCIxvLqZ9ipQZwA7P a9je2YOoaKEQZ0glir26oOUBinEQMXbPk+yUSDS092dqRs6tN0xRAZtdHrS9ouOt pt8xkXI+D0m+1aGE7ISPOUqdjT18LnEOLC7/Uq5XCWLDBGOEn6S1oPWGnYAOYqLf ZsF3pWZUCzvbgxDTNvZlxv0Xx7VKxhO5K5ZFXouaCBlFn7B1BfgK7oD+k7t5HFKc lZhC2kh5vUQPFgFl0T6W =YzDu -----END PGP SIGNATURE----- Merge remote-tracking branch 'afaerber/tags/qom-devices-for-anthony' into staging QOM device refactorings * QTest coverage for all machines * QOM realize for Milkymist UART * QOM realize for ARM MPCore * device_add bug fixes and cleanups * QOM for PCMCIA/MicroDrive (last legacy IDE device) # gpg: Signature made Tue 05 Nov 2013 09:07:03 AM PST using RSA key ID 3E7E013F # gpg: Can't check signature: public key not found # By Andreas Färber (49) and others # Via Andreas Färber * afaerber/tags/qom-devices-for-anthony: (54 commits) pcmcia/pxa2xx: QOM'ify PXA2xxPCMCIAState ide: Drop ide_init2_with_non_qdev_drives() microdrive: Coding Style cleanups pcmcia: QOM'ify PCMCIACardState and MicroDriveState pxa: Fix typo "dettach" qom: Fix pointer to int property helpers' documentation qdev-monitor: Inline qdev_init() for device_add qdev-monitor: Avoid qdev as variable name qdev: Drop misleading qdev_free() function qdev-monitor: Unref device when device_add fails qdev-monitor: Fix crash when device_add is called with abstract driver qdev-monitor: Clean up qdev_device_add() variable naming arm11mpcore: Split off RealView MPCore arm11mpcore: Prepare for QOM embedding arm11mpcore: Convert mpcore_rirq_state to QOM realize realview_gic: Prepare for QOM embedding realview_gic: Convert to QOM realize arm11mpcore: Convert ARM11MPCorePriveState to QOM realize arm11mpcore: Split off SCU device arm11mpcore: Create container MemoryRegion in instance_init ...
This commit is contained in:
commit
a30b377e0a
@ -61,6 +61,7 @@ CONFIG_BITBANG_I2C=y
|
||||
CONFIG_FRAMEBUFFER=y
|
||||
CONFIG_XILINX_SPIPS=y
|
||||
|
||||
CONFIG_ARM11SCU=y
|
||||
CONFIG_A9SCU=y
|
||||
CONFIG_MARVELL_88W8618=y
|
||||
CONFIG_OMAP=y
|
||||
|
@ -18,6 +18,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += net/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += nvram/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += pci/
|
||||
devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += pcmcia/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += scsi/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += sd/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += ssi/
|
||||
|
@ -328,7 +328,7 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
|
||||
if (pc->no_hotplug) {
|
||||
slot_free = false;
|
||||
} else {
|
||||
qdev_free(qdev);
|
||||
object_unparent(OBJECT(qdev));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/loader.h"
|
||||
#include "elf.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
/* Bitbanded IO. Each word corresponds to a single bit. */
|
||||
|
||||
@ -232,21 +234,22 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
|
||||
big_endian = 0;
|
||||
#endif
|
||||
|
||||
if (!kernel_filename) {
|
||||
if (!kernel_filename && !qtest_enabled()) {
|
||||
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);
|
||||
if (kernel_filename) {
|
||||
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) {
|
||||
error_report("Could not load kernel '%s'", kernel_filename);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Hack to map an additional page of ram at the top of the address
|
||||
|
@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/arm/arm.h"
|
||||
@ -96,7 +97,7 @@ static void lan9215_init(uint32_t base, qemu_irq irq)
|
||||
static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
|
||||
Exynos4BoardType board_type)
|
||||
{
|
||||
if (smp_cpus != EXYNOS4210_NCPUS) {
|
||||
if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) {
|
||||
fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus"
|
||||
" value.\n",
|
||||
exynos4_machines[board_type].name,
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
static const int sector_len = 128 * 1024;
|
||||
|
||||
@ -58,7 +59,7 @@ static void connex_init(QEMUMachineInitArgs *args)
|
||||
cpu = pxa255_init(address_space_mem, connex_ram);
|
||||
|
||||
dinfo = drive_get(IF_PFLASH, 0, 0);
|
||||
if (!dinfo) {
|
||||
if (!dinfo && !qtest_enabled()) {
|
||||
fprintf(stderr, "A flash image must be given with the "
|
||||
"'pflash' parameter\n");
|
||||
exit(1);
|
||||
@ -70,7 +71,8 @@ static void connex_init(QEMUMachineInitArgs *args)
|
||||
be = 0;
|
||||
#endif
|
||||
if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
|
||||
dinfo->bdrv, sector_len, connex_rom / sector_len,
|
||||
dinfo ? dinfo->bdrv : NULL,
|
||||
sector_len, connex_rom / sector_len,
|
||||
2, 0, 0, 0, 0, be)) {
|
||||
fprintf(stderr, "qemu: Error registering flash memory.\n");
|
||||
exit(1);
|
||||
@ -95,7 +97,7 @@ static void verdex_init(QEMUMachineInitArgs *args)
|
||||
cpu = pxa270_init(address_space_mem, verdex_ram, cpu_model ?: "pxa270-c0");
|
||||
|
||||
dinfo = drive_get(IF_PFLASH, 0, 0);
|
||||
if (!dinfo) {
|
||||
if (!dinfo && !qtest_enabled()) {
|
||||
fprintf(stderr, "A flash image must be given with the "
|
||||
"'pflash' parameter\n");
|
||||
exit(1);
|
||||
@ -107,7 +109,8 @@ static void verdex_init(QEMUMachineInitArgs *args)
|
||||
be = 0;
|
||||
#endif
|
||||
if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
|
||||
dinfo->bdrv, sector_len, verdex_rom / sector_len,
|
||||
dinfo ? dinfo->bdrv : NULL,
|
||||
sector_len, verdex_rom / sector_len,
|
||||
2, 0, 0, 0, 0, be)) {
|
||||
fprintf(stderr, "qemu: Error registering flash memory.\n");
|
||||
exit(1);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
/* Device addresses */
|
||||
#define MST_FPGA_PHYS 0x08000000
|
||||
@ -127,6 +128,9 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
|
||||
for (i = 0; i < 2; i ++) {
|
||||
dinfo = drive_get(IF_PFLASH, 0, i);
|
||||
if (!dinfo) {
|
||||
if (qtest_enabled()) {
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "Two flash images must be given with the "
|
||||
"'pflash' parameter\n");
|
||||
exit(1);
|
||||
@ -147,7 +151,6 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
|
||||
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 */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/block/flash.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -188,7 +189,7 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version)
|
||||
OMAP_CS1_BASE, &cs[1]);
|
||||
}
|
||||
|
||||
if (!args->kernel_filename && !fl_idx) {
|
||||
if (!args->kernel_filename && !fl_idx && !qtest_enabled()) {
|
||||
fprintf(stderr, "Kernel or Flash image must be specified\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "hw/hw.h"
|
||||
#include "audio/audio.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "ui/console.h"
|
||||
#include "hw/arm/omap.h"
|
||||
#include "hw/boards.h"
|
||||
@ -255,7 +256,7 @@ static void palmte_init(QEMUMachineInitArgs *args)
|
||||
}
|
||||
}
|
||||
|
||||
if (!rom_loaded && !kernel_filename) {
|
||||
if (!rom_loaded && !kernel_filename && !qtest_enabled()) {
|
||||
fprintf(stderr, "Kernel or ROM image must be specified\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "ui/console.h"
|
||||
#include "audio/audio.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
#ifdef DEBUG_Z2
|
||||
#define DPRINTF(fmt, ...) \
|
||||
@ -323,7 +324,7 @@ static void z2_init(QEMUMachineInitArgs *args)
|
||||
be = 0;
|
||||
#endif
|
||||
dinfo = drive_get(IF_PFLASH, 0, 0);
|
||||
if (!dinfo) {
|
||||
if (!dinfo && !qtest_enabled()) {
|
||||
fprintf(stderr, "Flash image must be given with the "
|
||||
"'pflash' parameter\n");
|
||||
exit(1);
|
||||
@ -331,7 +332,7 @@ static void z2_init(QEMUMachineInitArgs *args)
|
||||
|
||||
if (!pflash_cfi01_register(Z2_FLASH_BASE,
|
||||
NULL, "z2.flash0", Z2_FLASH_SIZE,
|
||||
dinfo->bdrv, sector_len,
|
||||
dinfo ? dinfo->bdrv : NULL, sector_len,
|
||||
Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
|
||||
be)) {
|
||||
fprintf(stderr, "qemu: Error registering flash memory.\n");
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sh4/sh.h"
|
||||
#include "hw/loader.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#define CE1 0x0100
|
||||
#define CE2 0x0200
|
||||
@ -36,10 +38,10 @@ static void init_dev(tc58128_dev * dev, const char *filename)
|
||||
/* Load flash image skipping the first block */
|
||||
ret = load_image(filename, dev->flash_contents + 528 * 32);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "ret=%d\n", ret);
|
||||
fprintf(stderr, "qemu: could not load flash image %s\n",
|
||||
filename);
|
||||
exit(1);
|
||||
if (!qtest_enabled()) {
|
||||
error_report("Could not load flash image %s", filename);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
/* Build first block with number of blocks */
|
||||
blocks = (ret + 528 * 32 - 1) / (528 * 32);
|
||||
|
@ -195,22 +195,26 @@ static void milkymist_uart_reset(DeviceState *d)
|
||||
s->regs[R_STAT] = STAT_THRE;
|
||||
}
|
||||
|
||||
static int milkymist_uart_init(SysBusDevice *dev)
|
||||
static void milkymist_uart_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MilkymistUartState *s = MILKYMIST_UART(dev);
|
||||
|
||||
sysbus_init_irq(dev, &s->irq);
|
||||
|
||||
memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
|
||||
"milkymist-uart", R_MAX * 4);
|
||||
sysbus_init_mmio(dev, &s->regs_region);
|
||||
|
||||
s->chr = qemu_char_get_next_serial();
|
||||
if (s->chr) {
|
||||
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
static void milkymist_uart_init(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
MilkymistUartState *s = MILKYMIST_UART(obj);
|
||||
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
|
||||
memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
|
||||
"milkymist-uart", R_MAX * 4);
|
||||
sysbus_init_mmio(sbd, &s->regs_region);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_milkymist_uart = {
|
||||
@ -227,9 +231,8 @@ static const VMStateDescription vmstate_milkymist_uart = {
|
||||
static void milkymist_uart_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = milkymist_uart_init;
|
||||
dc->realize = milkymist_uart_realize;
|
||||
dc->reset = milkymist_uart_reset;
|
||||
dc->vmsd = &vmstate_milkymist_uart;
|
||||
}
|
||||
@ -238,6 +241,7 @@ static const TypeInfo milkymist_uart_info = {
|
||||
.name = TYPE_MILKYMIST_UART,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(MilkymistUartState),
|
||||
.instance_init = milkymist_uart_init,
|
||||
.class_init = milkymist_uart_class_init,
|
||||
};
|
||||
|
||||
|
@ -164,7 +164,7 @@ int qdev_init(DeviceState *dev)
|
||||
if (local_err != NULL) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
qdev_free(dev);
|
||||
object_unparent(OBJECT(dev));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -258,7 +258,7 @@ void qbus_reset_all_fn(void *opaque)
|
||||
int qdev_simple_unplug_cb(DeviceState *dev)
|
||||
{
|
||||
/* just zap it */
|
||||
qdev_free(dev);
|
||||
object_unparent(OBJECT(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -280,12 +280,6 @@ void qdev_init_nofail(DeviceState *dev)
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlink device from bus and free the structure. */
|
||||
void qdev_free(DeviceState *dev)
|
||||
{
|
||||
object_unparent(OBJECT(dev));
|
||||
}
|
||||
|
||||
void qdev_machine_creation_done(void)
|
||||
{
|
||||
/*
|
||||
@ -458,7 +452,7 @@ static void bus_unparent(Object *obj)
|
||||
|
||||
while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
|
||||
DeviceState *dev = kid->child;
|
||||
qdev_free(dev);
|
||||
object_unparent(OBJECT(dev));
|
||||
}
|
||||
if (bus->parent) {
|
||||
QLIST_REMOVE(bus, sibling);
|
||||
|
@ -1,4 +1,5 @@
|
||||
obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
|
||||
obj-$(CONFIG_REALVIEW) += realview_mpcore.o
|
||||
obj-$(CONFIG_A9MPCORE) += a9mpcore.o
|
||||
obj-$(CONFIG_A15MPCORE) += a15mpcore.o
|
||||
obj-$(CONFIG_ICC_BUS) += icc_bus.o
|
||||
|
@ -18,55 +18,60 @@
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/cpu/a15mpcore.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
/* A15MP private memory region. */
|
||||
|
||||
#define TYPE_A15MPCORE_PRIV "a15mpcore_priv"
|
||||
#define A15MPCORE_PRIV(obj) \
|
||||
OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV)
|
||||
|
||||
typedef struct A15MPPrivState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
uint32_t num_cpu;
|
||||
uint32_t num_irq;
|
||||
MemoryRegion container;
|
||||
DeviceState *gic;
|
||||
} A15MPPrivState;
|
||||
|
||||
static void a15mp_priv_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
A15MPPrivState *s = (A15MPPrivState *)opaque;
|
||||
qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
|
||||
|
||||
qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
|
||||
}
|
||||
|
||||
static int a15mp_priv_init(SysBusDevice *dev)
|
||||
static void a15mp_priv_initfn(Object *obj)
|
||||
{
|
||||
A15MPPrivState *s = A15MPCORE_PRIV(dev);
|
||||
SysBusDevice *busdev;
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
A15MPPrivState *s = A15MPCORE_PRIV(obj);
|
||||
DeviceState *gicdev;
|
||||
const char *gictype = "arm_gic";
|
||||
int i;
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
gictype = "kvm-arm-gic";
|
||||
}
|
||||
|
||||
s->gic = qdev_create(NULL, gictype);
|
||||
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
|
||||
qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
|
||||
qdev_prop_set_uint32(s->gic, "revision", 2);
|
||||
qdev_init_nofail(s->gic);
|
||||
busdev = SYS_BUS_DEVICE(s->gic);
|
||||
memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000);
|
||||
sysbus_init_mmio(sbd, &s->container);
|
||||
|
||||
object_initialize(&s->gic, sizeof(s->gic), gictype);
|
||||
gicdev = DEVICE(&s->gic);
|
||||
qdev_set_parent_bus(gicdev, sysbus_get_default());
|
||||
qdev_prop_set_uint32(gicdev, "revision", 2);
|
||||
}
|
||||
|
||||
static void a15mp_priv_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
A15MPPrivState *s = A15MPCORE_PRIV(dev);
|
||||
DeviceState *gicdev;
|
||||
SysBusDevice *busdev;
|
||||
int i;
|
||||
Error *err = NULL;
|
||||
|
||||
gicdev = DEVICE(&s->gic);
|
||||
qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
|
||||
qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
|
||||
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
busdev = SYS_BUS_DEVICE(&s->gic);
|
||||
|
||||
/* Pass through outbound IRQ lines from the GIC */
|
||||
sysbus_pass_irq(dev, busdev);
|
||||
sysbus_pass_irq(sbd, busdev);
|
||||
|
||||
/* Pass through inbound GPIO lines to the GIC */
|
||||
qdev_init_gpio_in(DEVICE(dev), a15mp_priv_set_irq, s->num_irq - 32);
|
||||
qdev_init_gpio_in(dev, a15mp_priv_set_irq, s->num_irq - 32);
|
||||
|
||||
/* Wire the outputs from each CPU's generic timer to the
|
||||
* appropriate GIC PPI inputs
|
||||
@ -78,10 +83,10 @@ static int a15mp_priv_init(SysBusDevice *dev)
|
||||
* since a real A15 always has TrustZone but QEMU doesn't.
|
||||
*/
|
||||
qdev_connect_gpio_out(cpudev, 0,
|
||||
qdev_get_gpio_in(s->gic, ppibase + 30));
|
||||
qdev_get_gpio_in(gicdev, ppibase + 30));
|
||||
/* virtual timer */
|
||||
qdev_connect_gpio_out(cpudev, 1,
|
||||
qdev_get_gpio_in(s->gic, ppibase + 27));
|
||||
qdev_get_gpio_in(gicdev, ppibase + 27));
|
||||
}
|
||||
|
||||
/* Memory map (addresses are offsets from PERIPHBASE):
|
||||
@ -92,15 +97,10 @@ static int a15mp_priv_init(SysBusDevice *dev)
|
||||
* 0x5000-0x5fff -- GIC virtual interface control (not modelled)
|
||||
* 0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
|
||||
*/
|
||||
memory_region_init(&s->container, OBJECT(s),
|
||||
"a15mp-priv-container", 0x8000);
|
||||
memory_region_add_subregion(&s->container, 0x1000,
|
||||
sysbus_mmio_get_region(busdev, 0));
|
||||
memory_region_add_subregion(&s->container, 0x2000,
|
||||
sysbus_mmio_get_region(busdev, 1));
|
||||
|
||||
sysbus_init_mmio(dev, &s->container);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Property a15mp_priv_properties[] = {
|
||||
@ -118,8 +118,8 @@ static Property a15mp_priv_properties[] = {
|
||||
static void a15mp_priv_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
k->init = a15mp_priv_init;
|
||||
|
||||
dc->realize = a15mp_priv_realize;
|
||||
dc->props = a15mp_priv_properties;
|
||||
/* We currently have no savable state */
|
||||
}
|
||||
@ -128,6 +128,7 @@ static const TypeInfo a15mp_priv_info = {
|
||||
.name = TYPE_A15MPCORE_PRIV,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(A15MPPrivState),
|
||||
.instance_init = a15mp_priv_initfn,
|
||||
.class_init = a15mp_priv_class_init,
|
||||
};
|
||||
|
||||
|
@ -8,64 +8,86 @@
|
||||
* This code is licensed under the GPL.
|
||||
*/
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
|
||||
#define A9MPCORE_PRIV(obj) \
|
||||
OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV)
|
||||
|
||||
typedef struct A9MPPrivState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
uint32_t num_cpu;
|
||||
MemoryRegion container;
|
||||
DeviceState *mptimer;
|
||||
DeviceState *wdt;
|
||||
DeviceState *gic;
|
||||
DeviceState *scu;
|
||||
uint32_t num_irq;
|
||||
} A9MPPrivState;
|
||||
#include "hw/cpu/a9mpcore.h"
|
||||
|
||||
static void a9mp_priv_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
A9MPPrivState *s = (A9MPPrivState *)opaque;
|
||||
qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
|
||||
|
||||
qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
|
||||
}
|
||||
|
||||
static int a9mp_priv_init(SysBusDevice *dev)
|
||||
static void a9mp_priv_initfn(Object *obj)
|
||||
{
|
||||
A9MPPrivState *s = A9MPCORE_PRIV(obj);
|
||||
|
||||
memory_region_init(&s->container, obj, "a9mp-priv-container", 0x2000);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->container);
|
||||
|
||||
object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
|
||||
qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
|
||||
|
||||
object_initialize(&s->scu, sizeof(s->scu), TYPE_A9_SCU);
|
||||
qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
|
||||
|
||||
object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER);
|
||||
qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default());
|
||||
|
||||
object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ARM_MPTIMER);
|
||||
qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default());
|
||||
}
|
||||
|
||||
static void a9mp_priv_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
A9MPPrivState *s = A9MPCORE_PRIV(dev);
|
||||
DeviceState *gicdev, *scudev, *mptimerdev, *wdtdev;
|
||||
SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev;
|
||||
Error *err = NULL;
|
||||
int i;
|
||||
|
||||
s->gic = qdev_create(NULL, "arm_gic");
|
||||
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
|
||||
qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
|
||||
qdev_init_nofail(s->gic);
|
||||
gicbusdev = SYS_BUS_DEVICE(s->gic);
|
||||
gicdev = DEVICE(&s->gic);
|
||||
qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
|
||||
qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
|
||||
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
gicbusdev = SYS_BUS_DEVICE(&s->gic);
|
||||
|
||||
/* Pass through outbound IRQ lines from the GIC */
|
||||
sysbus_pass_irq(dev, gicbusdev);
|
||||
sysbus_pass_irq(sbd, gicbusdev);
|
||||
|
||||
/* Pass through inbound GPIO lines to the GIC */
|
||||
qdev_init_gpio_in(DEVICE(dev), a9mp_priv_set_irq, s->num_irq - 32);
|
||||
qdev_init_gpio_in(dev, a9mp_priv_set_irq, s->num_irq - 32);
|
||||
|
||||
s->scu = qdev_create(NULL, "a9-scu");
|
||||
qdev_prop_set_uint32(s->scu, "num-cpu", s->num_cpu);
|
||||
qdev_init_nofail(s->scu);
|
||||
scubusdev = SYS_BUS_DEVICE(s->scu);
|
||||
scudev = DEVICE(&s->scu);
|
||||
qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
|
||||
object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
scubusdev = SYS_BUS_DEVICE(&s->scu);
|
||||
|
||||
s->mptimer = qdev_create(NULL, "arm_mptimer");
|
||||
qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
|
||||
qdev_init_nofail(s->mptimer);
|
||||
timerbusdev = SYS_BUS_DEVICE(s->mptimer);
|
||||
mptimerdev = DEVICE(&s->mptimer);
|
||||
qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu);
|
||||
object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
timerbusdev = SYS_BUS_DEVICE(&s->mptimer);
|
||||
|
||||
s->wdt = qdev_create(NULL, "arm_mptimer");
|
||||
qdev_prop_set_uint32(s->wdt, "num-cpu", s->num_cpu);
|
||||
qdev_init_nofail(s->wdt);
|
||||
wdtbusdev = SYS_BUS_DEVICE(s->wdt);
|
||||
wdtdev = DEVICE(&s->wdt);
|
||||
qdev_prop_set_uint32(wdtdev, "num-cpu", s->num_cpu);
|
||||
object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
wdtbusdev = SYS_BUS_DEVICE(&s->wdt);
|
||||
|
||||
/* Memory map (addresses are offsets from PERIPHBASE):
|
||||
* 0x0000-0x00ff -- Snoop Control Unit
|
||||
@ -78,7 +100,6 @@ static int a9mp_priv_init(SysBusDevice *dev)
|
||||
*
|
||||
* We should implement the global timer but don't currently do so.
|
||||
*/
|
||||
memory_region_init(&s->container, OBJECT(s), "a9mp-priv-container", 0x2000);
|
||||
memory_region_add_subregion(&s->container, 0,
|
||||
sysbus_mmio_get_region(scubusdev, 0));
|
||||
/* GIC CPU interface */
|
||||
@ -94,19 +115,16 @@ static int a9mp_priv_init(SysBusDevice *dev)
|
||||
memory_region_add_subregion(&s->container, 0x1000,
|
||||
sysbus_mmio_get_region(gicbusdev, 0));
|
||||
|
||||
sysbus_init_mmio(dev, &s->container);
|
||||
|
||||
/* Wire up the interrupt from each watchdog and timer.
|
||||
* For each core the timer is PPI 29 and the watchdog PPI 30.
|
||||
*/
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
int ppibase = (s->num_irq - 32) + i * 32;
|
||||
sysbus_connect_irq(timerbusdev, i,
|
||||
qdev_get_gpio_in(s->gic, ppibase + 29));
|
||||
qdev_get_gpio_in(gicdev, ppibase + 29));
|
||||
sysbus_connect_irq(wdtbusdev, i,
|
||||
qdev_get_gpio_in(s->gic, ppibase + 30));
|
||||
qdev_get_gpio_in(gicdev, ppibase + 30));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Property a9mp_priv_properties[] = {
|
||||
@ -124,9 +142,8 @@ static Property a9mp_priv_properties[] = {
|
||||
static void a9mp_priv_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = a9mp_priv_init;
|
||||
dc->realize = a9mp_priv_realize;
|
||||
dc->props = a9mp_priv_properties;
|
||||
}
|
||||
|
||||
@ -134,6 +151,7 @@ static const TypeInfo a9mp_priv_info = {
|
||||
.name = TYPE_A9MPCORE_PRIV,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(A9MPPrivState),
|
||||
.instance_init = a9mp_priv_initfn,
|
||||
.class_init = a9mp_priv_class_init,
|
||||
};
|
||||
|
||||
|
@ -7,96 +7,28 @@
|
||||
* This code is licensed under the GPL.
|
||||
*/
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/cpu/arm11mpcore.h"
|
||||
#include "hw/intc/realview_gic.h"
|
||||
|
||||
/* MPCore private memory region. */
|
||||
|
||||
#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv"
|
||||
#define ARM11MPCORE_PRIV(obj) \
|
||||
OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV)
|
||||
|
||||
typedef struct ARM11MPCorePriveState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
uint32_t scu_control;
|
||||
int iomemtype;
|
||||
uint32_t old_timer_status[8];
|
||||
uint32_t num_cpu;
|
||||
MemoryRegion iomem;
|
||||
MemoryRegion container;
|
||||
DeviceState *mptimer;
|
||||
DeviceState *wdtimer;
|
||||
DeviceState *gic;
|
||||
uint32_t num_irq;
|
||||
} ARM11MPCorePriveState;
|
||||
|
||||
/* Per-CPU private memory mapped IO. */
|
||||
|
||||
static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
|
||||
int id;
|
||||
/* SCU */
|
||||
switch (offset) {
|
||||
case 0x00: /* Control. */
|
||||
return s->scu_control;
|
||||
case 0x04: /* Configuration. */
|
||||
id = ((1 << s->num_cpu) - 1) << 4;
|
||||
return id | (s->num_cpu - 1);
|
||||
case 0x08: /* CPU status. */
|
||||
return 0;
|
||||
case 0x0c: /* Invalidate all. */
|
||||
return 0;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"mpcore_priv_read: Bad offset %x\n", (int)offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void mpcore_scu_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
|
||||
/* SCU */
|
||||
switch (offset) {
|
||||
case 0: /* Control register. */
|
||||
s->scu_control = value & 1;
|
||||
break;
|
||||
case 0x0c: /* Invalidate all. */
|
||||
/* This is a no-op as cache is not emulated. */
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"mpcore_priv_read: Bad offset %x\n", (int)offset);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps mpcore_scu_ops = {
|
||||
.read = mpcore_scu_read,
|
||||
.write = mpcore_scu_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void mpcore_priv_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
|
||||
qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
|
||||
|
||||
qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
|
||||
}
|
||||
|
||||
static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
|
||||
{
|
||||
int i;
|
||||
SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic);
|
||||
SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer);
|
||||
SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer);
|
||||
memory_region_init(&s->container, OBJECT(s),
|
||||
"mpcode-priv-container", 0x2000);
|
||||
memory_region_init_io(&s->iomem, OBJECT(s),
|
||||
&mpcore_scu_ops, s, "mpcore-scu", 0x100);
|
||||
memory_region_add_subregion(&s->container, 0, &s->iomem);
|
||||
SysBusDevice *scubusdev = SYS_BUS_DEVICE(&s->scu);
|
||||
DeviceState *gicdev = DEVICE(&s->gic);
|
||||
SysBusDevice *gicbusdev = SYS_BUS_DEVICE(&s->gic);
|
||||
SysBusDevice *timerbusdev = SYS_BUS_DEVICE(&s->mptimer);
|
||||
SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(&s->wdtimer);
|
||||
|
||||
memory_region_add_subregion(&s->container, 0,
|
||||
sysbus_mmio_get_region(scubusdev, 0));
|
||||
/* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
|
||||
* at 0x200, 0x300...
|
||||
*/
|
||||
@ -124,134 +56,84 @@ static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
int ppibase = (s->num_irq - 32) + i * 32;
|
||||
sysbus_connect_irq(timerbusdev, i,
|
||||
qdev_get_gpio_in(s->gic, ppibase + 29));
|
||||
qdev_get_gpio_in(gicdev, ppibase + 29));
|
||||
sysbus_connect_irq(wdtbusdev, i,
|
||||
qdev_get_gpio_in(s->gic, ppibase + 30));
|
||||
qdev_get_gpio_in(gicdev, ppibase + 30));
|
||||
}
|
||||
}
|
||||
|
||||
static int mpcore_priv_init(SysBusDevice *sbd)
|
||||
static void mpcore_priv_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(sbd);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(dev);
|
||||
DeviceState *scudev = DEVICE(&s->scu);
|
||||
DeviceState *gicdev = DEVICE(&s->gic);
|
||||
DeviceState *mptimerdev = DEVICE(&s->mptimer);
|
||||
DeviceState *wdtimerdev = DEVICE(&s->wdtimer);
|
||||
Error *err = NULL;
|
||||
|
||||
s->gic = qdev_create(NULL, "arm_gic");
|
||||
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
|
||||
qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
|
||||
/* Request the legacy 11MPCore GIC behaviour: */
|
||||
qdev_prop_set_uint32(s->gic, "revision", 0);
|
||||
qdev_init_nofail(s->gic);
|
||||
qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
|
||||
object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
|
||||
qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
|
||||
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Pass through outbound IRQ lines from the GIC */
|
||||
sysbus_pass_irq(sbd, SYS_BUS_DEVICE(s->gic));
|
||||
sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->gic));
|
||||
|
||||
/* Pass through inbound GPIO lines to the GIC */
|
||||
qdev_init_gpio_in(dev, mpcore_priv_set_irq, s->num_irq - 32);
|
||||
|
||||
s->mptimer = qdev_create(NULL, "arm_mptimer");
|
||||
qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
|
||||
qdev_init_nofail(s->mptimer);
|
||||
qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu);
|
||||
object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
s->wdtimer = qdev_create(NULL, "arm_mptimer");
|
||||
qdev_prop_set_uint32(s->wdtimer, "num-cpu", s->num_cpu);
|
||||
qdev_init_nofail(s->wdtimer);
|
||||
qdev_prop_set_uint32(wdtimerdev, "num-cpu", s->num_cpu);
|
||||
object_property_set_bool(OBJECT(&s->wdtimer), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
mpcore_priv_map_setup(s);
|
||||
}
|
||||
|
||||
static void mpcore_priv_initfn(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(obj);
|
||||
|
||||
memory_region_init(&s->container, OBJECT(s),
|
||||
"mpcore-priv-container", 0x2000);
|
||||
sysbus_init_mmio(sbd, &s->container);
|
||||
return 0;
|
||||
|
||||
object_initialize(&s->scu, sizeof(s->scu), TYPE_ARM11_SCU);
|
||||
qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
|
||||
|
||||
object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
|
||||
qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
|
||||
/* Request the legacy 11MPCore GIC behaviour: */
|
||||
qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 0);
|
||||
|
||||
object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER);
|
||||
qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default());
|
||||
|
||||
object_initialize(&s->wdtimer, sizeof(s->wdtimer), TYPE_ARM_MPTIMER);
|
||||
qdev_set_parent_bus(DEVICE(&s->wdtimer), sysbus_get_default());
|
||||
}
|
||||
|
||||
#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
|
||||
#define REALVIEW_MPCORE_RIRQ(obj) \
|
||||
OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ)
|
||||
|
||||
/* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ
|
||||
controllers. The output of these, plus some of the raw input lines
|
||||
are fed into a single SMP-aware interrupt controller on the CPU. */
|
||||
typedef struct {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
SysBusDevice *priv;
|
||||
qemu_irq cpuic[32];
|
||||
qemu_irq rvic[4][64];
|
||||
uint32_t num_cpu;
|
||||
} mpcore_rirq_state;
|
||||
|
||||
/* Map baseboard IRQs onto CPU IRQ lines. */
|
||||
static const int mpcore_irq_map[32] = {
|
||||
-1, -1, -1, -1, 1, 2, -1, -1,
|
||||
-1, -1, 6, -1, 4, 5, -1, -1,
|
||||
-1, 14, 15, 0, 7, 8, -1, -1,
|
||||
-1, -1, -1, -1, 9, 3, -1, -1,
|
||||
};
|
||||
|
||||
static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
qemu_set_irq(s->rvic[i][irq], level);
|
||||
}
|
||||
if (irq < 32) {
|
||||
irq = mpcore_irq_map[irq];
|
||||
if (irq >= 0) {
|
||||
qemu_set_irq(s->cpuic[irq], level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int realview_mpcore_init(SysBusDevice *sbd)
|
||||
{
|
||||
DeviceState *dev = DEVICE(sbd);
|
||||
mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev);
|
||||
DeviceState *gic;
|
||||
DeviceState *priv;
|
||||
int n;
|
||||
int i;
|
||||
|
||||
priv = qdev_create(NULL, TYPE_ARM11MPCORE_PRIV);
|
||||
qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
|
||||
qdev_init_nofail(priv);
|
||||
s->priv = SYS_BUS_DEVICE(priv);
|
||||
sysbus_pass_irq(sbd, s->priv);
|
||||
for (i = 0; i < 32; i++) {
|
||||
s->cpuic[i] = qdev_get_gpio_in(priv, i);
|
||||
}
|
||||
/* ??? IRQ routing is hardcoded to "normal" mode. */
|
||||
for (n = 0; n < 4; n++) {
|
||||
gic = sysbus_create_simple("realview_gic", 0x10040000 + n * 0x10000,
|
||||
s->cpuic[10 + n]);
|
||||
for (i = 0; i < 64; i++) {
|
||||
s->rvic[n][i] = qdev_get_gpio_in(gic, i);
|
||||
}
|
||||
}
|
||||
qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64);
|
||||
sysbus_init_mmio(sbd, sysbus_mmio_get_region(s->priv, 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Property mpcore_rirq_properties[] = {
|
||||
DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = realview_mpcore_init;
|
||||
dc->props = mpcore_rirq_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo mpcore_rirq_info = {
|
||||
.name = TYPE_REALVIEW_MPCORE_RIRQ,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(mpcore_rirq_state),
|
||||
.class_init = mpcore_rirq_class_init,
|
||||
};
|
||||
|
||||
static Property mpcore_priv_properties[] = {
|
||||
DEFINE_PROP_UINT32("num-cpu", ARM11MPCorePriveState, num_cpu, 1),
|
||||
/* The ARM11 MPCORE TRM says the on-chip controller may have
|
||||
@ -269,9 +151,8 @@ static Property mpcore_priv_properties[] = {
|
||||
static void mpcore_priv_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = mpcore_priv_init;
|
||||
dc->realize = mpcore_priv_realize;
|
||||
dc->props = mpcore_priv_properties;
|
||||
}
|
||||
|
||||
@ -279,12 +160,12 @@ static const TypeInfo mpcore_priv_info = {
|
||||
.name = TYPE_ARM11MPCORE_PRIV,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ARM11MPCorePriveState),
|
||||
.instance_init = mpcore_priv_initfn,
|
||||
.class_init = mpcore_priv_class_init,
|
||||
};
|
||||
|
||||
static void arm11mpcore_register_types(void)
|
||||
{
|
||||
type_register_static(&mpcore_rirq_info);
|
||||
type_register_static(&mpcore_priv_info);
|
||||
}
|
||||
|
||||
|
139
hw/cpu/realview_mpcore.c
Normal file
139
hw/cpu/realview_mpcore.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* RealView ARM11MPCore internal peripheral emulation
|
||||
*
|
||||
* Copyright (c) 2006-2007 CodeSourcery.
|
||||
* Copyright (c) 2013 SUSE LINUX Products GmbH
|
||||
* Written by Paul Brook and Andreas Färber
|
||||
*
|
||||
* This code is licensed under the GPL.
|
||||
*/
|
||||
|
||||
#include "hw/cpu/arm11mpcore.h"
|
||||
#include "hw/intc/realview_gic.h"
|
||||
|
||||
#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
|
||||
#define REALVIEW_MPCORE_RIRQ(obj) \
|
||||
OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ)
|
||||
|
||||
/* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ
|
||||
controllers. The output of these, plus some of the raw input lines
|
||||
are fed into a single SMP-aware interrupt controller on the CPU. */
|
||||
typedef struct {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
qemu_irq cpuic[32];
|
||||
qemu_irq rvic[4][64];
|
||||
uint32_t num_cpu;
|
||||
|
||||
ARM11MPCorePriveState priv;
|
||||
RealViewGICState gic[4];
|
||||
} mpcore_rirq_state;
|
||||
|
||||
/* Map baseboard IRQs onto CPU IRQ lines. */
|
||||
static const int mpcore_irq_map[32] = {
|
||||
-1, -1, -1, -1, 1, 2, -1, -1,
|
||||
-1, -1, 6, -1, 4, 5, -1, -1,
|
||||
-1, 14, 15, 0, 7, 8, -1, -1,
|
||||
-1, -1, -1, -1, 9, 3, -1, -1,
|
||||
};
|
||||
|
||||
static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
qemu_set_irq(s->rvic[i][irq], level);
|
||||
}
|
||||
if (irq < 32) {
|
||||
irq = mpcore_irq_map[irq];
|
||||
if (irq >= 0) {
|
||||
qemu_set_irq(s->cpuic[irq], level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void realview_mpcore_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev);
|
||||
DeviceState *priv = DEVICE(&s->priv);
|
||||
DeviceState *gic;
|
||||
SysBusDevice *gicbusdev;
|
||||
Error *err = NULL;
|
||||
int n;
|
||||
int i;
|
||||
|
||||
qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
|
||||
object_property_set_bool(OBJECT(&s->priv), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->priv));
|
||||
for (i = 0; i < 32; i++) {
|
||||
s->cpuic[i] = qdev_get_gpio_in(priv, i);
|
||||
}
|
||||
/* ??? IRQ routing is hardcoded to "normal" mode. */
|
||||
for (n = 0; n < 4; n++) {
|
||||
object_property_set_bool(OBJECT(&s->gic[n]), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
gic = DEVICE(&s->gic[n]);
|
||||
gicbusdev = SYS_BUS_DEVICE(&s->gic[n]);
|
||||
sysbus_mmio_map(gicbusdev, 0, 0x10040000 + n * 0x10000);
|
||||
sysbus_connect_irq(gicbusdev, 0, s->cpuic[10 + n]);
|
||||
for (i = 0; i < 64; i++) {
|
||||
s->rvic[n][i] = qdev_get_gpio_in(gic, i);
|
||||
}
|
||||
}
|
||||
qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64);
|
||||
}
|
||||
|
||||
static void mpcore_rirq_init(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(obj);
|
||||
SysBusDevice *privbusdev;
|
||||
int i;
|
||||
|
||||
object_initialize(&s->priv, sizeof(s->priv), TYPE_ARM11MPCORE_PRIV);
|
||||
qdev_set_parent_bus(DEVICE(&s->priv), sysbus_get_default());
|
||||
privbusdev = SYS_BUS_DEVICE(&s->priv);
|
||||
sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
object_initialize(&s->gic[i], sizeof(s->gic[i]), TYPE_REALVIEW_GIC);
|
||||
qdev_set_parent_bus(DEVICE(&s->gic[i]), sysbus_get_default());
|
||||
}
|
||||
}
|
||||
|
||||
static Property mpcore_rirq_properties[] = {
|
||||
DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = realview_mpcore_realize;
|
||||
dc->props = mpcore_rirq_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo mpcore_rirq_info = {
|
||||
.name = TYPE_REALVIEW_MPCORE_RIRQ,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(mpcore_rirq_state),
|
||||
.instance_init = mpcore_rirq_init,
|
||||
.class_init = mpcore_rirq_class_init,
|
||||
};
|
||||
|
||||
static void realview_mpcore_register_types(void)
|
||||
{
|
||||
type_register_static(&mpcore_rirq_info);
|
||||
}
|
||||
|
||||
type_init(realview_mpcore_register_types)
|
@ -32,6 +32,7 @@
|
||||
#include "boot.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
#define D(x)
|
||||
#define DNAND(x)
|
||||
@ -340,14 +341,14 @@ void axisdev88_init(QEMUMachineInitArgs *args)
|
||||
irq[0x14 + i]);
|
||||
}
|
||||
|
||||
if (!kernel_filename) {
|
||||
if (kernel_filename) {
|
||||
li.image_filename = kernel_filename;
|
||||
li.cmdline = kernel_cmdline;
|
||||
cris_load_image(cpu, &li);
|
||||
} else if (!qtest_enabled()) {
|
||||
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 = {
|
||||
|
@ -2215,55 +2215,6 @@ void ide_init2(IDEBus *bus, qemu_irq irq)
|
||||
bus->dma = &ide_dma_nop;
|
||||
}
|
||||
|
||||
/* TODO convert users to qdev and remove */
|
||||
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
|
||||
DriveInfo *hd1, qemu_irq irq)
|
||||
{
|
||||
int i, trans;
|
||||
DriveInfo *dinfo;
|
||||
uint32_t cyls, heads, secs;
|
||||
|
||||
for(i = 0; i < 2; i++) {
|
||||
dinfo = i == 0 ? hd0 : hd1;
|
||||
ide_init1(bus, i);
|
||||
if (dinfo) {
|
||||
cyls = dinfo->cyls;
|
||||
heads = dinfo->heads;
|
||||
secs = dinfo->secs;
|
||||
trans = dinfo->trans;
|
||||
if (!cyls && !heads && !secs) {
|
||||
hd_geometry_guess(dinfo->bdrv, &cyls, &heads, &secs, &trans);
|
||||
} else if (trans == BIOS_ATA_TRANSLATION_AUTO) {
|
||||
trans = hd_bios_chs_auto_trans(cyls, heads, secs);
|
||||
}
|
||||
if (cyls < 1 || cyls > 65535) {
|
||||
error_report("cyls must be between 1 and 65535");
|
||||
exit(1);
|
||||
}
|
||||
if (heads < 1 || heads > 16) {
|
||||
error_report("heads must be between 1 and 16");
|
||||
exit(1);
|
||||
}
|
||||
if (secs < 1 || secs > 255) {
|
||||
error_report("secs must be between 1 and 255");
|
||||
exit(1);
|
||||
}
|
||||
if (ide_init_drive(&bus->ifs[i], dinfo->bdrv,
|
||||
dinfo->media_cd ? IDE_CD : IDE_HD,
|
||||
NULL, dinfo->serial, NULL, 0,
|
||||
cyls, heads, secs, trans) < 0) {
|
||||
error_report("Can't set up IDE drive %s", dinfo->id);
|
||||
exit(1);
|
||||
}
|
||||
bdrv_attach_dev_nofail(dinfo->bdrv, &bus->ifs[i]);
|
||||
} else {
|
||||
ide_reset(&bus->ifs[i]);
|
||||
}
|
||||
}
|
||||
bus->irq = irq;
|
||||
bus->dma = &ide_dma_nop;
|
||||
}
|
||||
|
||||
static const MemoryRegionPortio ide_portio_list[] = {
|
||||
{ 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write },
|
||||
{ 0, 2, 2, .read = ide_data_readw, .write = ide_data_writew },
|
||||
|
@ -553,8 +553,6 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
|
||||
uint32_t cylinders, uint32_t heads, uint32_t secs,
|
||||
int chs_trans);
|
||||
void ide_init2(IDEBus *bus, qemu_irq irq);
|
||||
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
|
||||
DriveInfo *hd1, qemu_irq irq);
|
||||
void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
|
||||
|
||||
void ide_exec_cmd(IDEBus *bus, uint32_t val);
|
||||
|
@ -30,15 +30,22 @@
|
||||
|
||||
#include <hw/ide/internal.h>
|
||||
|
||||
#define TYPE_MICRODRIVE "microdrive"
|
||||
#define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE)
|
||||
|
||||
/***********************************************************/
|
||||
/* CF-ATA Microdrive */
|
||||
|
||||
#define METADATA_SIZE 0x20
|
||||
|
||||
/* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface. */
|
||||
typedef struct {
|
||||
|
||||
typedef struct MicroDriveState {
|
||||
/*< private >*/
|
||||
PCMCIACardState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
IDEBus bus;
|
||||
PCMCIACardState card;
|
||||
uint32_t attr_base;
|
||||
uint32_t io_base;
|
||||
|
||||
@ -81,10 +88,13 @@ enum md_ctrl {
|
||||
|
||||
static inline void md_interrupt_update(MicroDriveState *s)
|
||||
{
|
||||
if (!s->card.slot)
|
||||
return;
|
||||
PCMCIACardState *card = PCMCIA_CARD(s);
|
||||
|
||||
qemu_set_irq(s->card.slot->irq,
|
||||
if (card->slot == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_set_irq(card->slot->irq,
|
||||
!(s->stat & STAT_INT) && /* Inverted */
|
||||
!(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
|
||||
!(s->opt & OPT_SRESET));
|
||||
@ -93,16 +103,20 @@ static inline void md_interrupt_update(MicroDriveState *s)
|
||||
static void md_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
MicroDriveState *s = opaque;
|
||||
if (level)
|
||||
|
||||
if (level) {
|
||||
s->stat |= STAT_INT;
|
||||
else
|
||||
} else {
|
||||
s->stat &= ~STAT_INT;
|
||||
}
|
||||
|
||||
md_interrupt_update(s);
|
||||
}
|
||||
|
||||
static void md_reset(MicroDriveState *s)
|
||||
static void md_reset(DeviceState *dev)
|
||||
{
|
||||
MicroDriveState *s = MICRODRIVE(dev);
|
||||
|
||||
s->opt = OPT_MODE_MMAP;
|
||||
s->stat = 0;
|
||||
s->pins = 0;
|
||||
@ -111,14 +125,17 @@ static void md_reset(MicroDriveState *s)
|
||||
ide_bus_reset(&s->bus);
|
||||
}
|
||||
|
||||
static uint8_t md_attr_read(void *opaque, uint32_t at)
|
||||
static uint8_t md_attr_read(PCMCIACardState *card, uint32_t at)
|
||||
{
|
||||
MicroDriveState *s = opaque;
|
||||
MicroDriveState *s = MICRODRIVE(card);
|
||||
PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card);
|
||||
|
||||
if (at < s->attr_base) {
|
||||
if (at < s->card.cis_len)
|
||||
return s->card.cis[at];
|
||||
else
|
||||
if (at < pcc->cis_len) {
|
||||
return pcc->cis[at];
|
||||
} else {
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
at -= s->attr_base;
|
||||
@ -127,10 +144,11 @@ static uint8_t md_attr_read(void *opaque, uint32_t at)
|
||||
case 0x00: /* Configuration Option Register */
|
||||
return s->opt;
|
||||
case 0x02: /* Card Configuration Status Register */
|
||||
if (s->ctrl & CTRL_IEN)
|
||||
if (s->ctrl & CTRL_IEN) {
|
||||
return s->stat & ~STAT_INT;
|
||||
else
|
||||
} else {
|
||||
return s->stat;
|
||||
}
|
||||
case 0x04: /* Pin Replacement Register */
|
||||
return (s->pins & PINS_CRDY) | 0x0c;
|
||||
case 0x06: /* Socket and Copy Register */
|
||||
@ -144,21 +162,24 @@ static uint8_t md_attr_read(void *opaque, uint32_t at)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void md_attr_write(void *opaque, uint32_t at, uint8_t value)
|
||||
static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
|
||||
{
|
||||
MicroDriveState *s = opaque;
|
||||
MicroDriveState *s = MICRODRIVE(card);
|
||||
|
||||
at -= s->attr_base;
|
||||
|
||||
switch (at) {
|
||||
case 0x00: /* Configuration Option Register */
|
||||
s->opt = value & 0xcf;
|
||||
if (value & OPT_SRESET)
|
||||
md_reset(s);
|
||||
if (value & OPT_SRESET) {
|
||||
device_reset(DEVICE(s));
|
||||
}
|
||||
md_interrupt_update(s);
|
||||
break;
|
||||
case 0x02: /* Card Configuration Status Register */
|
||||
if ((s->stat ^ value) & STAT_PWRDWN)
|
||||
if ((s->stat ^ value) & STAT_PWRDWN) {
|
||||
s->pins |= PINS_CRDY;
|
||||
}
|
||||
s->stat &= 0x82;
|
||||
s->stat |= value & 0x74;
|
||||
md_interrupt_update(s);
|
||||
@ -175,32 +196,35 @@ static void md_attr_write(void *opaque, uint32_t at, uint8_t value)
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t md_common_read(void *opaque, uint32_t at)
|
||||
static uint16_t md_common_read(PCMCIACardState *card, uint32_t at)
|
||||
{
|
||||
MicroDriveState *s = opaque;
|
||||
MicroDriveState *s = MICRODRIVE(card);
|
||||
IDEState *ifs;
|
||||
uint16_t ret;
|
||||
at -= s->io_base;
|
||||
|
||||
switch (s->opt & OPT_MODE) {
|
||||
case OPT_MODE_MMAP:
|
||||
if ((at & ~0x3ff) == 0x400)
|
||||
if ((at & ~0x3ff) == 0x400) {
|
||||
at = 0;
|
||||
}
|
||||
break;
|
||||
case OPT_MODE_IOMAP16:
|
||||
at &= 0xf;
|
||||
break;
|
||||
case OPT_MODE_IOMAP1:
|
||||
if ((at & ~0xf) == 0x3f0)
|
||||
if ((at & ~0xf) == 0x3f0) {
|
||||
at -= 0x3e8;
|
||||
else if ((at & ~0xf) == 0x1f0)
|
||||
} else if ((at & ~0xf) == 0x1f0) {
|
||||
at -= 0x1f0;
|
||||
}
|
||||
break;
|
||||
case OPT_MODE_IOMAP2:
|
||||
if ((at & ~0xf) == 0x370)
|
||||
if ((at & ~0xf) == 0x370) {
|
||||
at -= 0x368;
|
||||
else if ((at & ~0xf) == 0x170)
|
||||
} else if ((at & ~0xf) == 0x170) {
|
||||
at -= 0x170;
|
||||
}
|
||||
}
|
||||
|
||||
switch (at) {
|
||||
@ -209,9 +233,9 @@ static uint16_t md_common_read(void *opaque, uint32_t at)
|
||||
return ide_data_readw(&s->bus, 0);
|
||||
|
||||
/* TODO: 8-bit accesses */
|
||||
if (s->cycle)
|
||||
if (s->cycle) {
|
||||
ret = s->io >> 8;
|
||||
else {
|
||||
} else {
|
||||
s->io = ide_data_readw(&s->bus, 0);
|
||||
ret = s->io & 0xff;
|
||||
}
|
||||
@ -223,10 +247,11 @@ static uint16_t md_common_read(void *opaque, uint32_t at)
|
||||
return ide_ioport_read(&s->bus, 0x1);
|
||||
case 0xe: /* Alternate Status */
|
||||
ifs = idebus_active_if(&s->bus);
|
||||
if (ifs->bs)
|
||||
if (ifs->bs) {
|
||||
return ifs->status;
|
||||
else
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
case 0xf: /* Device Address */
|
||||
ifs = idebus_active_if(&s->bus);
|
||||
return 0xc2 | ((~ifs->select << 2) & 0x3c);
|
||||
@ -237,30 +262,33 @@ static uint16_t md_common_read(void *opaque, uint32_t at)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void md_common_write(void *opaque, uint32_t at, uint16_t value)
|
||||
static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
|
||||
{
|
||||
MicroDriveState *s = opaque;
|
||||
MicroDriveState *s = MICRODRIVE(card);
|
||||
at -= s->io_base;
|
||||
|
||||
switch (s->opt & OPT_MODE) {
|
||||
case OPT_MODE_MMAP:
|
||||
if ((at & ~0x3ff) == 0x400)
|
||||
if ((at & ~0x3ff) == 0x400) {
|
||||
at = 0;
|
||||
}
|
||||
break;
|
||||
case OPT_MODE_IOMAP16:
|
||||
at &= 0xf;
|
||||
break;
|
||||
case OPT_MODE_IOMAP1:
|
||||
if ((at & ~0xf) == 0x3f0)
|
||||
if ((at & ~0xf) == 0x3f0) {
|
||||
at -= 0x3e8;
|
||||
else if ((at & ~0xf) == 0x1f0)
|
||||
} else if ((at & ~0xf) == 0x1f0) {
|
||||
at -= 0x1f0;
|
||||
}
|
||||
break;
|
||||
case OPT_MODE_IOMAP2:
|
||||
if ((at & ~0xf) == 0x370)
|
||||
if ((at & ~0xf) == 0x370) {
|
||||
at -= 0x368;
|
||||
else if ((at & ~0xf) == 0x170)
|
||||
} else if ((at & ~0xf) == 0x170) {
|
||||
at -= 0x170;
|
||||
}
|
||||
}
|
||||
|
||||
switch (at) {
|
||||
@ -270,10 +298,11 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value)
|
||||
break;
|
||||
|
||||
/* TODO: 8-bit accesses */
|
||||
if (s->cycle)
|
||||
if (s->cycle) {
|
||||
ide_data_writew(&s->bus, 0, s->io | (value << 8));
|
||||
else
|
||||
} else {
|
||||
s->io = value & 0xff;
|
||||
}
|
||||
s->cycle = !s->cycle;
|
||||
break;
|
||||
case 0x9:
|
||||
@ -285,8 +314,9 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value)
|
||||
break;
|
||||
case 0xe: /* Device Control */
|
||||
s->ctrl = value;
|
||||
if (value & CTRL_SRST)
|
||||
md_reset(s);
|
||||
if (value & CTRL_SRST) {
|
||||
device_reset(DEVICE(s));
|
||||
}
|
||||
md_interrupt_update(s);
|
||||
break;
|
||||
default:
|
||||
@ -501,49 +531,109 @@ static const uint8_t dscm1xxxx_cis[0x14a] = {
|
||||
[0x146] = CISTPL_END, /* Tuple End */
|
||||
};
|
||||
|
||||
static int dscm1xxxx_attach(void *opaque)
|
||||
{
|
||||
MicroDriveState *md = opaque;
|
||||
md->card.attr_read = md_attr_read;
|
||||
md->card.attr_write = md_attr_write;
|
||||
md->card.common_read = md_common_read;
|
||||
md->card.common_write = md_common_write;
|
||||
md->card.io_read = md_common_read;
|
||||
md->card.io_write = md_common_write;
|
||||
#define TYPE_DSCM1XXXX "dscm1xxxx"
|
||||
|
||||
md->attr_base = md->card.cis[0x74] | (md->card.cis[0x76] << 8);
|
||||
static int dscm1xxxx_attach(PCMCIACardState *card)
|
||||
{
|
||||
MicroDriveState *md = MICRODRIVE(card);
|
||||
PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card);
|
||||
|
||||
md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
|
||||
md->io_base = 0x0;
|
||||
|
||||
md_reset(md);
|
||||
device_reset(DEVICE(md));
|
||||
md_interrupt_update(md);
|
||||
|
||||
md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
|
||||
card->slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dscm1xxxx_detach(void *opaque)
|
||||
static int dscm1xxxx_detach(PCMCIACardState *card)
|
||||
{
|
||||
MicroDriveState *md = opaque;
|
||||
md_reset(md);
|
||||
MicroDriveState *md = MICRODRIVE(card);
|
||||
|
||||
device_reset(DEVICE(md));
|
||||
return 0;
|
||||
}
|
||||
|
||||
PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv)
|
||||
PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo)
|
||||
{
|
||||
MicroDriveState *md = (MicroDriveState *) g_malloc0(sizeof(MicroDriveState));
|
||||
md->card.state = md;
|
||||
md->card.attach = dscm1xxxx_attach;
|
||||
md->card.detach = dscm1xxxx_detach;
|
||||
md->card.cis = dscm1xxxx_cis;
|
||||
md->card.cis_len = sizeof(dscm1xxxx_cis);
|
||||
MicroDriveState *md;
|
||||
|
||||
ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL,
|
||||
qemu_allocate_irqs(md_set_irq, md, 1)[0]);
|
||||
md = MICRODRIVE(object_new(TYPE_DSCM1XXXX));
|
||||
qdev_init_nofail(DEVICE(md));
|
||||
|
||||
if (dinfo != NULL) {
|
||||
ide_create_drive(&md->bus, 0, dinfo);
|
||||
}
|
||||
md->bus.ifs[0].drive_kind = IDE_CFATA;
|
||||
md->bus.ifs[0].mdata_size = METADATA_SIZE;
|
||||
md->bus.ifs[0].mdata_storage = (uint8_t *) g_malloc0(METADATA_SIZE);
|
||||
|
||||
vmstate_register(NULL, -1, &vmstate_microdrive, md);
|
||||
|
||||
return &md->card;
|
||||
return PCMCIA_CARD(md);
|
||||
}
|
||||
|
||||
static void dscm1xxxx_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
|
||||
|
||||
pcc->cis = dscm1xxxx_cis;
|
||||
pcc->cis_len = sizeof(dscm1xxxx_cis);
|
||||
|
||||
pcc->attach = dscm1xxxx_attach;
|
||||
pcc->detach = dscm1xxxx_detach;
|
||||
}
|
||||
|
||||
static const TypeInfo dscm1xxxx_type_info = {
|
||||
.name = TYPE_DSCM1XXXX,
|
||||
.parent = TYPE_MICRODRIVE,
|
||||
.class_init = dscm1xxxx_class_init,
|
||||
};
|
||||
|
||||
static void microdrive_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MicroDriveState *md = MICRODRIVE(dev);
|
||||
|
||||
ide_init2(&md->bus, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
|
||||
}
|
||||
|
||||
static void microdrive_init(Object *obj)
|
||||
{
|
||||
MicroDriveState *md = MICRODRIVE(obj);
|
||||
|
||||
ide_bus_new(&md->bus, sizeof(md->bus), DEVICE(obj), 0, 1);
|
||||
}
|
||||
|
||||
static void microdrive_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
|
||||
|
||||
pcc->attr_read = md_attr_read;
|
||||
pcc->attr_write = md_attr_write;
|
||||
pcc->common_read = md_common_read;
|
||||
pcc->common_write = md_common_write;
|
||||
pcc->io_read = md_common_read;
|
||||
pcc->io_write = md_common_write;
|
||||
|
||||
dc->realize = microdrive_realize;
|
||||
dc->reset = md_reset;
|
||||
dc->vmsd = &vmstate_microdrive;
|
||||
}
|
||||
|
||||
static const TypeInfo microdrive_type_info = {
|
||||
.name = TYPE_MICRODRIVE,
|
||||
.parent = TYPE_PCMCIA_CARD,
|
||||
.instance_size = sizeof(MicroDriveState),
|
||||
.instance_init = microdrive_init,
|
||||
.abstract = true,
|
||||
.class_init = microdrive_class_init,
|
||||
};
|
||||
|
||||
static void microdrive_register_types(void)
|
||||
{
|
||||
type_register_static(µdrive_type_info);
|
||||
type_register_static(&dscm1xxxx_type_info);
|
||||
}
|
||||
|
||||
type_init(microdrive_register_types)
|
||||
|
@ -64,17 +64,17 @@ static const VMStateDescription vmstate_gic = {
|
||||
.post_load = gic_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_BOOL(enabled, GICState),
|
||||
VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, NCPU),
|
||||
VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, GIC_NCPU),
|
||||
VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1,
|
||||
vmstate_gic_irq_state, gic_irq_state),
|
||||
VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ),
|
||||
VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, NCPU),
|
||||
VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU),
|
||||
VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
|
||||
VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU),
|
||||
VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU),
|
||||
VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU),
|
||||
VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU),
|
||||
VMSTATE_UINT16_ARRAY(current_pending, GICState, NCPU),
|
||||
VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, GIC_NCPU),
|
||||
VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU),
|
||||
VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU),
|
||||
VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU),
|
||||
VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
@ -84,9 +84,9 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
|
||||
GICState *s = ARM_GIC_COMMON(dev);
|
||||
int num_irq = s->num_irq;
|
||||
|
||||
if (s->num_cpu > NCPU) {
|
||||
if (s->num_cpu > GIC_NCPU) {
|
||||
error_setg(errp, "requested %u CPUs exceeds GIC maximum %d",
|
||||
s->num_cpu, NCPU);
|
||||
s->num_cpu, GIC_NCPU);
|
||||
return;
|
||||
}
|
||||
s->num_irq += GIC_BASE_IRQ;
|
||||
|
@ -21,16 +21,9 @@
|
||||
#ifndef QEMU_ARM_GIC_INTERNAL_H
|
||||
#define QEMU_ARM_GIC_INTERNAL_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/intc/arm_gic.h"
|
||||
|
||||
/* Maximum number of possible interrupts, determined by the GIC architecture */
|
||||
#define GIC_MAXIRQ 1020
|
||||
/* First 32 are private to each CPU (SGIs and PPIs). */
|
||||
#define GIC_INTERNAL 32
|
||||
/* Maximum number of possible CPU interfaces, determined by GIC architecture */
|
||||
#define NCPU 8
|
||||
|
||||
#define ALL_CPU_MASK ((unsigned)(((1 << NCPU) - 1)))
|
||||
#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
|
||||
|
||||
/* The NVIC has 16 internal vectors. However these are not exposed
|
||||
through the normal GIC interface. */
|
||||
@ -59,48 +52,6 @@
|
||||
s->priority2[(irq) - GIC_INTERNAL])
|
||||
#define GIC_TARGET(irq) s->irq_target[irq]
|
||||
|
||||
typedef struct gic_irq_state {
|
||||
/* The enable bits are only banked for per-cpu interrupts. */
|
||||
uint8_t enabled;
|
||||
uint8_t pending;
|
||||
uint8_t active;
|
||||
uint8_t level;
|
||||
bool model; /* 0 = N:N, 1 = 1:N */
|
||||
bool trigger; /* nonzero = edge triggered. */
|
||||
} gic_irq_state;
|
||||
|
||||
typedef struct GICState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
qemu_irq parent_irq[NCPU];
|
||||
bool enabled;
|
||||
bool cpu_enabled[NCPU];
|
||||
|
||||
gic_irq_state irq_state[GIC_MAXIRQ];
|
||||
uint8_t irq_target[GIC_MAXIRQ];
|
||||
uint8_t priority1[GIC_INTERNAL][NCPU];
|
||||
uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
|
||||
uint16_t last_active[GIC_MAXIRQ][NCPU];
|
||||
|
||||
uint16_t priority_mask[NCPU];
|
||||
uint16_t running_irq[NCPU];
|
||||
uint16_t running_priority[NCPU];
|
||||
uint16_t current_pending[NCPU];
|
||||
|
||||
uint32_t num_cpu;
|
||||
|
||||
MemoryRegion iomem; /* Distributor */
|
||||
/* This is just so we can have an opaque pointer which identifies
|
||||
* both this GIC and which CPU interface we should be accessing.
|
||||
*/
|
||||
struct GICState *backref[NCPU];
|
||||
MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
|
||||
uint32_t num_irq;
|
||||
uint32_t revision;
|
||||
} GICState;
|
||||
|
||||
/* The special cases for the revision property: */
|
||||
#define REV_11MPCORE 0
|
||||
#define REV_NVIC 0xffffffff
|
||||
@ -111,31 +62,4 @@ void gic_complete_irq(GICState *s, int cpu, int irq);
|
||||
void gic_update(GICState *s);
|
||||
void gic_init_irqs_and_distributor(GICState *s, int num_irq);
|
||||
|
||||
#define TYPE_ARM_GIC_COMMON "arm_gic_common"
|
||||
#define ARM_GIC_COMMON(obj) \
|
||||
OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON)
|
||||
#define ARM_GIC_COMMON_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON)
|
||||
#define ARM_GIC_COMMON_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON)
|
||||
|
||||
typedef struct ARMGICCommonClass {
|
||||
SysBusDeviceClass parent_class;
|
||||
void (*pre_save)(GICState *s);
|
||||
void (*post_load)(GICState *s);
|
||||
} ARMGICCommonClass;
|
||||
|
||||
#define TYPE_ARM_GIC "arm_gic"
|
||||
#define ARM_GIC(obj) \
|
||||
OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC)
|
||||
#define ARM_GIC_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC)
|
||||
#define ARM_GIC_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC)
|
||||
|
||||
typedef struct ARMGICClass {
|
||||
ARMGICCommonClass parent_class;
|
||||
DeviceRealize parent_realize;
|
||||
} ARMGICClass;
|
||||
|
||||
#endif /* !QEMU_ARM_GIC_INTERNAL_H */
|
||||
|
@ -7,41 +7,34 @@
|
||||
* This code is licensed under the GPL.
|
||||
*/
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_REALVIEW_GIC "realview_gic"
|
||||
#define REALVIEW_GIC(obj) \
|
||||
OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC)
|
||||
|
||||
typedef struct {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
DeviceState *gic;
|
||||
MemoryRegion container;
|
||||
} RealViewGICState;
|
||||
#include "hw/intc/realview_gic.h"
|
||||
|
||||
static void realview_gic_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
RealViewGICState *s = (RealViewGICState *)opaque;
|
||||
qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
|
||||
|
||||
qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
|
||||
}
|
||||
|
||||
static int realview_gic_init(SysBusDevice *sbd)
|
||||
static void realview_gic_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(sbd);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
RealViewGICState *s = REALVIEW_GIC(dev);
|
||||
SysBusDevice *busdev;
|
||||
Error *err = NULL;
|
||||
/* The GICs on the RealView boards have a fixed nonconfigurable
|
||||
* number of interrupt lines, so we don't need to expose this as
|
||||
* a qdev property.
|
||||
*/
|
||||
int numirq = 96;
|
||||
|
||||
s->gic = qdev_create(NULL, "arm_gic");
|
||||
qdev_prop_set_uint32(s->gic, "num-cpu", 1);
|
||||
qdev_prop_set_uint32(s->gic, "num-irq", numirq);
|
||||
qdev_init_nofail(s->gic);
|
||||
busdev = SYS_BUS_DEVICE(s->gic);
|
||||
qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", numirq);
|
||||
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
busdev = SYS_BUS_DEVICE(&s->gic);
|
||||
|
||||
/* Pass through outbound IRQ lines from the GIC */
|
||||
sysbus_pass_irq(sbd, busdev);
|
||||
@ -49,27 +42,40 @@ static int realview_gic_init(SysBusDevice *sbd)
|
||||
/* Pass through inbound GPIO lines to the GIC */
|
||||
qdev_init_gpio_in(dev, realview_gic_set_irq, numirq - 32);
|
||||
|
||||
memory_region_init(&s->container, OBJECT(s),
|
||||
"realview-gic-container", 0x2000);
|
||||
memory_region_add_subregion(&s->container, 0,
|
||||
sysbus_mmio_get_region(busdev, 1));
|
||||
memory_region_add_subregion(&s->container, 0x1000,
|
||||
sysbus_mmio_get_region(busdev, 0));
|
||||
sysbus_init_mmio(sbd, &s->container);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void realview_gic_class_init(ObjectClass *klass, void *data)
|
||||
static void realview_gic_init(Object *obj)
|
||||
{
|
||||
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
RealViewGICState *s = REALVIEW_GIC(obj);
|
||||
DeviceState *gicdev;
|
||||
|
||||
sdc->init = realview_gic_init;
|
||||
memory_region_init(&s->container, OBJECT(s),
|
||||
"realview-gic-container", 0x2000);
|
||||
sysbus_init_mmio(sbd, &s->container);
|
||||
|
||||
object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
|
||||
gicdev = DEVICE(&s->gic);
|
||||
qdev_set_parent_bus(gicdev, sysbus_get_default());
|
||||
qdev_prop_set_uint32(gicdev, "num-cpu", 1);
|
||||
}
|
||||
|
||||
static void realview_gic_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = realview_gic_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo realview_gic_info = {
|
||||
.name = TYPE_REALVIEW_GIC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(RealViewGICState),
|
||||
.instance_init = realview_gic_init,
|
||||
.class_init = realview_gic_class_init,
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "hw/hw.h"
|
||||
#include "hw/block/flash.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/devices.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
@ -143,7 +144,7 @@ milkymist_init(QEMUMachineInitArgs *args)
|
||||
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) {
|
||||
if (!kernel_filename && !dinfo && !bios_filename && !qtest_enabled()) {
|
||||
fprintf(stderr, "qemu: could not load Milkymist One bios '%s'\n",
|
||||
bios_name);
|
||||
exit(1);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "hw/loader.h"
|
||||
#include "elf.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
#define KERNEL_LOAD_ADDR 0x10000
|
||||
#define AN5206_MBAR_ADDR 0x10000000
|
||||
@ -62,6 +63,9 @@ static void an5206_init(QEMUMachineInitArgs *args)
|
||||
|
||||
/* Load kernel. */
|
||||
if (!kernel_filename) {
|
||||
if (qtest_enabled()) {
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "Kernel image must be specified\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/ptimer.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
@ -267,6 +268,9 @@ static void mcf5208evb_init(QEMUMachineInitArgs *args)
|
||||
|
||||
/* Load kernel. */
|
||||
if (!kernel_filename) {
|
||||
if (qtest_enabled()) {
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "Kernel image must be specified\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "hw/sysbus.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
static struct _loaderparams {
|
||||
int ram_size;
|
||||
@ -190,7 +191,8 @@ mips_mipssim_init(QEMUMachineInitArgs *args)
|
||||
} else {
|
||||
bios_size = -1;
|
||||
}
|
||||
if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
|
||||
if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
|
||||
!kernel_filename && !qtest_enabled()) {
|
||||
/* Bail out if we have neither a kernel image nor boot vector code. */
|
||||
error_report("Could not load MIPS bios '%s', and no "
|
||||
"-kernel argument was specified", filename);
|
||||
|
@ -11,6 +11,8 @@ obj-$(CONFIG_VMPORT) += vmport.o
|
||||
# ARM devices
|
||||
common-obj-$(CONFIG_PL310) += arm_l2x0.o
|
||||
common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o
|
||||
common-obj-$(CONFIG_A9SCU) += a9scu.o
|
||||
common-obj-$(CONFIG_ARM11SCU) += arm11scu.o
|
||||
|
||||
# PKUnity SoC devices
|
||||
common-obj-$(CONFIG_PUV3) += puv3_pm.o
|
||||
@ -23,7 +25,6 @@ obj-$(CONFIG_LINUX) += vfio.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_REALVIEW) += arm_sysctl.o
|
||||
obj-$(CONFIG_A9SCU) += a9scu.o
|
||||
obj-$(CONFIG_NSERIES) += cbus.o
|
||||
obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
|
||||
obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
|
||||
@ -37,7 +38,6 @@ obj-$(CONFIG_OMAP) += omap_gpmc.o
|
||||
obj-$(CONFIG_OMAP) += omap_l4.o
|
||||
obj-$(CONFIG_OMAP) += omap_sdrc.o
|
||||
obj-$(CONFIG_OMAP) += omap_tap.o
|
||||
obj-$(CONFIG_PXA2XX) += pxa2xx_pcmcia.o
|
||||
obj-$(CONFIG_SLAVIO) += slavio_misc.o
|
||||
obj-$(CONFIG_ZYNQ) += zynq_slcr.o
|
||||
|
||||
|
@ -8,20 +8,7 @@
|
||||
* This code is licensed under the GPL.
|
||||
*/
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
/* A9MP private memory region. */
|
||||
|
||||
typedef struct A9SCUState {
|
||||
SysBusDevice busdev;
|
||||
MemoryRegion iomem;
|
||||
uint32_t control;
|
||||
uint32_t status;
|
||||
uint32_t num_cpu;
|
||||
} A9SCUState;
|
||||
|
||||
#define TYPE_A9_SCU "a9-scu"
|
||||
#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU)
|
||||
#include "hw/misc/a9scu.h"
|
||||
|
||||
static uint64_t a9_scu_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
@ -114,12 +101,12 @@ static void a9_scu_reset(DeviceState *dev)
|
||||
s->control = 0;
|
||||
}
|
||||
|
||||
static void a9_scu_realize(DeviceState *dev, Error ** errp)
|
||||
static void a9_scu_init(Object *obj)
|
||||
{
|
||||
A9SCUState *s = A9_SCU(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
A9SCUState *s = A9_SCU(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(dev), &a9_scu_ops, s,
|
||||
memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s,
|
||||
"a9-scu", 0x100);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
@ -144,7 +131,6 @@ static void a9_scu_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = a9_scu_realize;
|
||||
dc->props = a9_scu_properties;
|
||||
dc->vmsd = &vmstate_a9_scu;
|
||||
dc->reset = a9_scu_reset;
|
||||
@ -154,6 +140,7 @@ static const TypeInfo a9_scu_info = {
|
||||
.name = TYPE_A9_SCU,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(A9SCUState),
|
||||
.instance_init = a9_scu_init,
|
||||
.class_init = a9_scu_class_init,
|
||||
};
|
||||
|
||||
|
100
hw/misc/arm11scu.c
Normal file
100
hw/misc/arm11scu.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* ARM11MPCore Snoop Control Unit (SCU) emulation
|
||||
*
|
||||
* Copyright (c) 2006-2007 CodeSourcery.
|
||||
* Copyright (c) 2013 SUSE LINUX Products GmbH
|
||||
* Written by Paul Brook and Andreas Färber
|
||||
*
|
||||
* This code is licensed under the GPL.
|
||||
*/
|
||||
|
||||
#include "hw/misc/arm11scu.h"
|
||||
|
||||
static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
ARM11SCUState *s = (ARM11SCUState *)opaque;
|
||||
int id;
|
||||
/* SCU */
|
||||
switch (offset) {
|
||||
case 0x00: /* Control. */
|
||||
return s->control;
|
||||
case 0x04: /* Configuration. */
|
||||
id = ((1 << s->num_cpu) - 1) << 4;
|
||||
return id | (s->num_cpu - 1);
|
||||
case 0x08: /* CPU status. */
|
||||
return 0;
|
||||
case 0x0c: /* Invalidate all. */
|
||||
return 0;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"mpcore_priv_read: Bad offset %x\n", (int)offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void mpcore_scu_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
ARM11SCUState *s = (ARM11SCUState *)opaque;
|
||||
/* SCU */
|
||||
switch (offset) {
|
||||
case 0: /* Control register. */
|
||||
s->control = value & 1;
|
||||
break;
|
||||
case 0x0c: /* Invalidate all. */
|
||||
/* This is a no-op as cache is not emulated. */
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"mpcore_priv_read: Bad offset %x\n", (int)offset);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps mpcore_scu_ops = {
|
||||
.read = mpcore_scu_read,
|
||||
.write = mpcore_scu_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void arm11_scu_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
}
|
||||
|
||||
static void arm11_scu_init(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
ARM11SCUState *s = ARM11_SCU(obj);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s),
|
||||
&mpcore_scu_ops, s, "mpcore-scu", 0x100);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static Property arm11_scu_properties[] = {
|
||||
DEFINE_PROP_UINT32("num-cpu", ARM11SCUState, num_cpu, 1),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
static void arm11_scu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = arm11_scu_realize;
|
||||
dc->props = arm11_scu_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo arm11_scu_type_info = {
|
||||
.name = TYPE_ARM11_SCU,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ARM11SCUState),
|
||||
.instance_init = arm11_scu_init,
|
||||
.class_init = arm11_scu_class_init,
|
||||
};
|
||||
|
||||
static void arm11_scu_register_types(void)
|
||||
{
|
||||
type_register_static(&arm11_scu_type_info);
|
||||
}
|
||||
|
||||
type_init(arm11_scu_register_types)
|
@ -248,7 +248,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
|
||||
}
|
||||
dev = pci_create(bus, devfn, "virtio-blk-pci");
|
||||
if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
|
||||
qdev_free(&dev->qdev);
|
||||
object_unparent(OBJECT(dev));
|
||||
dev = NULL;
|
||||
break;
|
||||
}
|
||||
|
@ -391,7 +391,7 @@ void pci_bridge_exitfn(PCIDevice *pci_dev)
|
||||
pci_bridge_region_cleanup(s, s->windows);
|
||||
memory_region_destroy(&s->address_space_mem);
|
||||
memory_region_destroy(&s->address_space_io);
|
||||
/* qbus_free() is called automatically by qdev_free() */
|
||||
/* qbus_free() is called automatically during device deletion */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -251,7 +251,7 @@ static int pcie_cap_slot_hotplug(DeviceState *qdev,
|
||||
PCI_EXP_SLTSTA_PDS);
|
||||
pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
|
||||
} else {
|
||||
qdev_free(&pci_dev->qdev);
|
||||
object_unparent(OBJECT(pci_dev));
|
||||
pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
|
||||
PCI_EXP_SLTSTA_PDS);
|
||||
pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
|
||||
|
@ -254,7 +254,7 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
|
||||
++devfn) {
|
||||
PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
|
||||
if (affected_dev) {
|
||||
qdev_free(&affected_dev->qdev);
|
||||
object_unparent(OBJECT(affected_dev));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
hw/pcmcia/Makefile.objs
Normal file
2
hw/pcmcia/Makefile.objs
Normal file
@ -0,0 +1,2 @@
|
||||
common-obj-y += pcmcia.o
|
||||
obj-$(CONFIG_PXA2XX) += pxa2xx.o
|
24
hw/pcmcia/pcmcia.c
Normal file
24
hw/pcmcia/pcmcia.c
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* PCMCIA emulation
|
||||
*
|
||||
* Copyright 2013 SUSE LINUX Products GmbH
|
||||
*/
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/pcmcia.h"
|
||||
|
||||
static const TypeInfo pcmcia_card_type_info = {
|
||||
.name = TYPE_PCMCIA_CARD,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(PCMCIACardState),
|
||||
.abstract = true,
|
||||
.class_size = sizeof(PCMCIACardClass),
|
||||
};
|
||||
|
||||
static void pcmcia_register_types(void)
|
||||
{
|
||||
type_register_static(&pcmcia_card_type_info);
|
||||
}
|
||||
|
||||
type_init(pcmcia_register_types)
|
@ -11,28 +11,38 @@
|
||||
*/
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/pcmcia.h"
|
||||
#include "hw/arm/pxa.h"
|
||||
|
||||
#define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia"
|
||||
#define PXA2XX_PCMCIA(obj) \
|
||||
OBJECT_CHECK(PXA2xxPCMCIAState, obj, TYPE_PXA2XX_PCMCIA)
|
||||
|
||||
struct PXA2xxPCMCIAState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
PCMCIASocket slot;
|
||||
PCMCIACardState *card;
|
||||
MemoryRegion container_mem;
|
||||
MemoryRegion common_iomem;
|
||||
MemoryRegion attr_iomem;
|
||||
MemoryRegion iomem;
|
||||
|
||||
qemu_irq irq;
|
||||
qemu_irq cd_irq;
|
||||
|
||||
PCMCIACardState *card;
|
||||
};
|
||||
|
||||
static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
|
||||
hwaddr offset, unsigned size)
|
||||
{
|
||||
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
|
||||
PCMCIACardClass *pcc;
|
||||
|
||||
if (s->slot.attached) {
|
||||
return s->card->common_read(s->card->state, offset);
|
||||
pcc = PCMCIA_CARD_GET_CLASS(s->card);
|
||||
return pcc->common_read(s->card, offset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -42,9 +52,11 @@ static void pxa2xx_pcmcia_common_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
|
||||
PCMCIACardClass *pcc;
|
||||
|
||||
if (s->slot.attached) {
|
||||
s->card->common_write(s->card->state, offset, value);
|
||||
pcc = PCMCIA_CARD_GET_CLASS(s->card);
|
||||
pcc->common_write(s->card, offset, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,9 +64,11 @@ static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
|
||||
hwaddr offset, unsigned size)
|
||||
{
|
||||
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
|
||||
PCMCIACardClass *pcc;
|
||||
|
||||
if (s->slot.attached) {
|
||||
return s->card->attr_read(s->card->state, offset);
|
||||
pcc = PCMCIA_CARD_GET_CLASS(s->card);
|
||||
return pcc->attr_read(s->card, offset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -64,9 +78,11 @@ static void pxa2xx_pcmcia_attr_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
|
||||
PCMCIACardClass *pcc;
|
||||
|
||||
if (s->slot.attached) {
|
||||
s->card->attr_write(s->card->state, offset, value);
|
||||
pcc = PCMCIA_CARD_GET_CLASS(s->card);
|
||||
pcc->attr_write(s->card, offset, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,9 +90,11 @@ static uint64_t pxa2xx_pcmcia_io_read(void *opaque,
|
||||
hwaddr offset, unsigned size)
|
||||
{
|
||||
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
|
||||
PCMCIACardClass *pcc;
|
||||
|
||||
if (s->slot.attached) {
|
||||
return s->card->io_read(s->card->state, offset);
|
||||
pcc = PCMCIA_CARD_GET_CLASS(s->card);
|
||||
return pcc->io_read(s->card, offset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -86,9 +104,11 @@ static void pxa2xx_pcmcia_io_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
|
||||
PCMCIACardClass *pcc;
|
||||
|
||||
if (s->slot.attached) {
|
||||
s->card->io_write(s->card->state, offset, value);
|
||||
pcc = PCMCIA_CARD_GET_CLASS(s->card);
|
||||
pcc->io_write(s->card, offset, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,15 +142,43 @@ static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
|
||||
PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
|
||||
hwaddr base)
|
||||
{
|
||||
DeviceState *dev;
|
||||
PXA2xxPCMCIAState *s;
|
||||
|
||||
s = (PXA2xxPCMCIAState *)
|
||||
g_malloc0(sizeof(PXA2xxPCMCIAState));
|
||||
dev = qdev_create(NULL, TYPE_PXA2XX_PCMCIA);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
||||
s = PXA2XX_PCMCIA(dev);
|
||||
|
||||
if (base == 0x30000000) {
|
||||
s->slot.slot_string = "PXA PC Card Socket 1";
|
||||
} else {
|
||||
s->slot.slot_string = "PXA PC Card Socket 0";
|
||||
}
|
||||
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void pxa2xx_pcmcia_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PXA2xxPCMCIAState *s = PXA2XX_PCMCIA(dev);
|
||||
|
||||
pcmcia_socket_register(&s->slot);
|
||||
}
|
||||
|
||||
static void pxa2xx_pcmcia_initfn(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
PXA2xxPCMCIAState *s = PXA2XX_PCMCIA(obj);
|
||||
|
||||
memory_region_init(&s->container_mem, obj, "container", 0x10000000);
|
||||
sysbus_init_mmio(sbd, &s->container_mem);
|
||||
|
||||
/* Socket I/O Memory Space */
|
||||
memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s,
|
||||
"pxa2xx-pcmcia-io", 0x04000000);
|
||||
memory_region_add_subregion(sysmem, base | 0x00000000,
|
||||
memory_region_add_subregion(&s->container_mem, 0x00000000,
|
||||
&s->iomem);
|
||||
|
||||
/* Then next 64 MB is reserved */
|
||||
@ -138,62 +186,68 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
|
||||
/* Socket Attribute Memory Space */
|
||||
memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s,
|
||||
"pxa2xx-pcmcia-attribute", 0x04000000);
|
||||
memory_region_add_subregion(sysmem, base | 0x08000000,
|
||||
memory_region_add_subregion(&s->container_mem, 0x08000000,
|
||||
&s->attr_iomem);
|
||||
|
||||
/* Socket Common Memory Space */
|
||||
memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s,
|
||||
"pxa2xx-pcmcia-common", 0x04000000);
|
||||
memory_region_add_subregion(sysmem, base | 0x0c000000,
|
||||
memory_region_add_subregion(&s->container_mem, 0x0c000000,
|
||||
&s->common_iomem);
|
||||
|
||||
if (base == 0x30000000)
|
||||
s->slot.slot_string = "PXA PC Card Socket 1";
|
||||
else
|
||||
s->slot.slot_string = "PXA PC Card Socket 0";
|
||||
s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
|
||||
pcmcia_socket_register(&s->slot);
|
||||
|
||||
return s;
|
||||
object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
|
||||
(Object **)&s->card, NULL);
|
||||
}
|
||||
|
||||
/* Insert a new card into a slot */
|
||||
int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
|
||||
{
|
||||
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
|
||||
if (s->slot.attached)
|
||||
PCMCIACardClass *pcc;
|
||||
|
||||
if (s->slot.attached) {
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
if (s->cd_irq) {
|
||||
qemu_irq_raise(s->cd_irq);
|
||||
}
|
||||
|
||||
s->card = card;
|
||||
pcc = PCMCIA_CARD_GET_CLASS(s->card);
|
||||
|
||||
s->slot.attached = 1;
|
||||
s->slot.attached = true;
|
||||
s->card->slot = &s->slot;
|
||||
s->card->attach(s->card->state);
|
||||
pcc->attach(s->card);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Eject card from the slot */
|
||||
int pxa2xx_pcmcia_dettach(void *opaque)
|
||||
int pxa2xx_pcmcia_detach(void *opaque)
|
||||
{
|
||||
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
|
||||
if (!s->slot.attached)
|
||||
return -ENOENT;
|
||||
PCMCIACardClass *pcc;
|
||||
|
||||
s->card->detach(s->card->state);
|
||||
if (!s->slot.attached) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
pcc = PCMCIA_CARD_GET_CLASS(s->card);
|
||||
pcc->detach(s->card);
|
||||
s->card->slot = NULL;
|
||||
s->card = NULL;
|
||||
|
||||
s->slot.attached = 0;
|
||||
s->slot.attached = false;
|
||||
|
||||
if (s->irq)
|
||||
if (s->irq) {
|
||||
qemu_irq_lower(s->irq);
|
||||
if (s->cd_irq)
|
||||
}
|
||||
if (s->cd_irq) {
|
||||
qemu_irq_lower(s->cd_irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -205,3 +259,25 @@ void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
|
||||
s->irq = irq;
|
||||
s->cd_irq = cd_irq;
|
||||
}
|
||||
|
||||
static void pxa2xx_pcmcia_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = pxa2xx_pcmcia_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo pxa2xx_pcmcia_type_info = {
|
||||
.name = TYPE_PXA2XX_PCMCIA,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(PXA2xxPCMCIAState),
|
||||
.instance_init = pxa2xx_pcmcia_initfn,
|
||||
.class_init = pxa2xx_pcmcia_class_init,
|
||||
};
|
||||
|
||||
static void pxa2xx_pcmcia_register_types(void)
|
||||
{
|
||||
type_register_static(&pxa2xx_pcmcia_type_info);
|
||||
}
|
||||
|
||||
type_init(pxa2xx_pcmcia_register_types)
|
@ -1239,7 +1239,7 @@ static int virtio_ccw_busdev_unplug(DeviceState *dev)
|
||||
|
||||
css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
|
||||
|
||||
qdev_free(dev);
|
||||
object_unparent(OBJECT(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,7 @@ static int scsi_qdev_init(DeviceState *qdev)
|
||||
d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
|
||||
assert(d);
|
||||
if (d->lun == dev->lun && dev != d) {
|
||||
qdev_free(&d->qdev);
|
||||
object_unparent(OBJECT(d));
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,13 +231,13 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
|
||||
}
|
||||
if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
|
||||
error_setg(errp, "Setting drive property failed");
|
||||
qdev_free(dev);
|
||||
object_unparent(OBJECT(dev));
|
||||
return NULL;
|
||||
}
|
||||
object_property_set_bool(OBJECT(dev), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
qdev_free(dev);
|
||||
object_unparent(OBJECT(dev));
|
||||
return NULL;
|
||||
}
|
||||
return SCSI_DEVICE(dev);
|
||||
|
@ -30,9 +30,11 @@
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sh4/sh.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#define BIOS_FILENAME "shix_bios.bin"
|
||||
#define BIOS_ADDRESS 0xA0000000
|
||||
@ -50,7 +52,6 @@ static void shix_init(QEMUMachineInitArgs *args)
|
||||
if (!cpu_model)
|
||||
cpu_model = "any";
|
||||
|
||||
printf("Initializing CPU\n");
|
||||
cpu = cpu_sh4_init(cpu_model);
|
||||
if (cpu == NULL) {
|
||||
fprintf(stderr, "Unable to find CPU definition\n");
|
||||
@ -58,16 +59,13 @@ static void shix_init(QEMUMachineInitArgs *args)
|
||||
}
|
||||
|
||||
/* Allocate memory space */
|
||||
printf("Allocating ROM\n");
|
||||
memory_region_init_ram(rom, NULL, "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], NULL, "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], NULL, "shix.sdram2", 0x01000000);
|
||||
vmstate_register_ram_global(&sdram[1]);
|
||||
memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
|
||||
@ -75,20 +73,16 @@ static void shix_init(QEMUMachineInitArgs *args)
|
||||
/* 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);
|
||||
if (ret < 0 && !qtest_enabled()) {
|
||||
error_report("Could not load SHIX bios '%s'", bios_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Register peripherals */
|
||||
s = sh7750_init(cpu, sysmem);
|
||||
/* XXXXX Check success */
|
||||
tc58128_init(s, "shix_linux_nand.bin", NULL);
|
||||
fprintf(stderr, "initialization terminated\n");
|
||||
}
|
||||
|
||||
static QEMUMachine shix_machine = {
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "hw/ptimer.h"
|
||||
#include "sysemu/char.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
#include "elf.h"
|
||||
@ -178,7 +179,7 @@ static void leon3_generic_hw_init(QEMUMachineInitArgs *args)
|
||||
fprintf(stderr, "qemu: could not load prom '%s'\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
} else if (kernel_filename == NULL) {
|
||||
} else if (kernel_filename == NULL && !qtest_enabled()) {
|
||||
fprintf(stderr, "Can't read bios image %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/timer/arm_mptimer.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qom/cpu.h"
|
||||
|
||||
@ -27,34 +27,6 @@
|
||||
* which is used in both the ARM11MPCore and Cortex-A9MP.
|
||||
*/
|
||||
|
||||
#define MAX_CPUS 4
|
||||
|
||||
/* State of a single timer or watchdog block */
|
||||
typedef struct {
|
||||
uint32_t count;
|
||||
uint32_t load;
|
||||
uint32_t control;
|
||||
uint32_t status;
|
||||
int64_t tick;
|
||||
QEMUTimer *timer;
|
||||
qemu_irq irq;
|
||||
MemoryRegion iomem;
|
||||
} TimerBlock;
|
||||
|
||||
#define TYPE_ARM_MPTIMER "arm_mptimer"
|
||||
#define ARM_MPTIMER(obj) \
|
||||
OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER)
|
||||
|
||||
typedef struct {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
uint32_t num_cpu;
|
||||
TimerBlock timerblock[MAX_CPUS];
|
||||
MemoryRegion iomem;
|
||||
} ARMMPTimerState;
|
||||
|
||||
static inline int get_current_cpu(ARMMPTimerState *s)
|
||||
{
|
||||
if (current_cpu->cpu_index >= s->num_cpu) {
|
||||
@ -225,13 +197,24 @@ static void arm_mptimer_reset(DeviceState *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static int arm_mptimer_init(SysBusDevice *dev)
|
||||
static void arm_mptimer_init(Object *obj)
|
||||
{
|
||||
ARMMPTimerState *s = ARM_MPTIMER(obj);
|
||||
|
||||
memory_region_init_io(&s->iomem, obj, &arm_thistimer_ops, s,
|
||||
"arm_mptimer_timer", 0x20);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
|
||||
}
|
||||
|
||||
static void arm_mptimer_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
ARMMPTimerState *s = ARM_MPTIMER(dev);
|
||||
int i;
|
||||
|
||||
if (s->num_cpu < 1 || s->num_cpu > MAX_CPUS) {
|
||||
hw_error("%s: num-cpu must be between 1 and %d\n", __func__, MAX_CPUS);
|
||||
if (s->num_cpu < 1 || s->num_cpu > ARM_MPTIMER_MAX_CPUS) {
|
||||
hw_error("%s: num-cpu must be between 1 and %d\n",
|
||||
__func__, ARM_MPTIMER_MAX_CPUS);
|
||||
}
|
||||
/* We implement one timer block per CPU, and expose multiple MMIO regions:
|
||||
* * region 0 is "timer for this core"
|
||||
@ -243,19 +226,14 @@ static int arm_mptimer_init(SysBusDevice *dev)
|
||||
* * timer for core 1
|
||||
* and so on.
|
||||
*/
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &arm_thistimer_ops, s,
|
||||
"arm_mptimer_timer", 0x20);
|
||||
sysbus_init_mmio(dev, &s->iomem);
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
TimerBlock *tb = &s->timerblock[i];
|
||||
tb->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, timerblock_tick, tb);
|
||||
sysbus_init_irq(dev, &tb->irq);
|
||||
sysbus_init_irq(sbd, &tb->irq);
|
||||
memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
|
||||
"arm_mptimer_timerblock", 0x20);
|
||||
sysbus_init_mmio(dev, &tb->iomem);
|
||||
sysbus_init_mmio(sbd, &tb->iomem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_timerblock = {
|
||||
@ -292,9 +270,8 @@ static Property arm_mptimer_properties[] = {
|
||||
static void arm_mptimer_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
sbc->init = arm_mptimer_init;
|
||||
dc->realize = arm_mptimer_realize;
|
||||
dc->vmsd = &vmstate_arm_mptimer;
|
||||
dc->reset = arm_mptimer_reset;
|
||||
dc->no_user = 1;
|
||||
@ -305,6 +282,7 @@ static const TypeInfo arm_mptimer_info = {
|
||||
.name = TYPE_ARM_MPTIMER,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ARMMPTimerState),
|
||||
.instance_init = arm_mptimer_init,
|
||||
.class_init = arm_mptimer_class_init,
|
||||
};
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
#undef DEBUG_PUV3
|
||||
#include "hw/unicore32/puv3.h"
|
||||
@ -84,6 +85,9 @@ static void puv3_load_kernel(const char *kernel_filename)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (kernel_filename == NULL && qtest_enabled()) {
|
||||
return;
|
||||
}
|
||||
assert(kernel_filename != NULL);
|
||||
|
||||
/* only zImage format supported */
|
||||
|
@ -356,8 +356,9 @@ void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
|
||||
|
||||
void usb_unregister_port(USBBus *bus, USBPort *port)
|
||||
{
|
||||
if (port->dev)
|
||||
qdev_free(&port->dev->qdev);
|
||||
if (port->dev) {
|
||||
object_unparent(OBJECT(port->dev));
|
||||
}
|
||||
QTAILQ_REMOVE(&bus->free, port, next);
|
||||
bus->nfree--;
|
||||
}
|
||||
@ -505,7 +506,7 @@ int usb_device_delete_addr(int busnr, int addr)
|
||||
return -1;
|
||||
dev = port->dev;
|
||||
|
||||
qdev_free(&dev->qdev);
|
||||
object_unparent(OBJECT(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -703,7 +703,7 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
|
||||
return NULL;
|
||||
}
|
||||
if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
|
||||
qdev_free(&dev->qdev);
|
||||
object_unparent(OBJECT(dev));
|
||||
return NULL;
|
||||
}
|
||||
if (qdev_init(&dev->qdev) < 0)
|
||||
|
@ -132,7 +132,7 @@ USBDevice *usb_host_device_open(USBBus *bus, const char *devname)
|
||||
return dev;
|
||||
|
||||
fail:
|
||||
qdev_free(&dev->qdev);
|
||||
object_unparent(OBJECT(dev));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,6 @@ void virtio_bus_reset(VirtioBusState *bus)
|
||||
/* Destroy the VirtIODevice */
|
||||
void virtio_bus_destroy_device(VirtioBusState *bus)
|
||||
{
|
||||
DeviceState *qdev;
|
||||
BusState *qbus = BUS(bus);
|
||||
VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
|
||||
DPRINTF("%s: remove device.\n", qbus->name);
|
||||
@ -76,8 +75,7 @@ void virtio_bus_destroy_device(VirtioBusState *bus)
|
||||
if (klass->device_unplug != NULL) {
|
||||
klass->device_unplug(qbus->parent);
|
||||
}
|
||||
qdev = DEVICE(bus->vdev);
|
||||
qdev_free(qdev);
|
||||
object_unparent(OBJECT(bus->vdev));
|
||||
bus->vdev = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
|
||||
if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
|
||||
PCI_CLASS_NETWORK_ETHERNET
|
||||
&& strcmp(d->name, "xen-pci-passthrough") != 0) {
|
||||
qdev_free(DEVICE(d));
|
||||
object_unparent(OBJECT(d));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ typedef struct PXA2xxPCMCIAState PXA2xxPCMCIAState;
|
||||
PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
|
||||
hwaddr base);
|
||||
int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card);
|
||||
int pxa2xx_pcmcia_dettach(void *opaque);
|
||||
int pxa2xx_pcmcia_detach(void *opaque);
|
||||
void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq);
|
||||
|
||||
/* pxa2xx_keypad.c */
|
||||
|
44
include/hw/cpu/a15mpcore.h
Normal file
44
include/hw/cpu/a15mpcore.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Cortex-A15MPCore internal peripheral emulation.
|
||||
*
|
||||
* Copyright (c) 2012 Linaro Limited.
|
||||
* Written by Peter Maydell.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef HW_CPU_A15MPCORE_H
|
||||
#define HW_CPU_A15MPCORE_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/intc/arm_gic.h"
|
||||
|
||||
/* A15MP private memory region. */
|
||||
|
||||
#define TYPE_A15MPCORE_PRIV "a15mpcore_priv"
|
||||
#define A15MPCORE_PRIV(obj) \
|
||||
OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV)
|
||||
|
||||
typedef struct A15MPPrivState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
uint32_t num_cpu;
|
||||
uint32_t num_irq;
|
||||
MemoryRegion container;
|
||||
|
||||
GICState gic;
|
||||
} A15MPPrivState;
|
||||
|
||||
#endif
|
37
include/hw/cpu/a9mpcore.h
Normal file
37
include/hw/cpu/a9mpcore.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Cortex-A9MPCore internal peripheral emulation.
|
||||
*
|
||||
* Copyright (c) 2009 CodeSourcery.
|
||||
* Copyright (c) 2011 Linaro Limited.
|
||||
* Written by Paul Brook, Peter Maydell.
|
||||
*
|
||||
* This code is licensed under the GPL.
|
||||
*/
|
||||
#ifndef HW_CPU_A9MPCORE_H
|
||||
#define HW_CPU_A9MPCORE_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/intc/arm_gic.h"
|
||||
#include "hw/misc/a9scu.h"
|
||||
#include "hw/timer/arm_mptimer.h"
|
||||
|
||||
#define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
|
||||
#define A9MPCORE_PRIV(obj) \
|
||||
OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV)
|
||||
|
||||
typedef struct A9MPPrivState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
uint32_t num_cpu;
|
||||
MemoryRegion container;
|
||||
uint32_t num_irq;
|
||||
|
||||
GICState gic;
|
||||
A9SCUState scu;
|
||||
ARMMPTimerState mptimer;
|
||||
ARMMPTimerState wdt;
|
||||
} A9MPPrivState;
|
||||
|
||||
#endif
|
35
include/hw/cpu/arm11mpcore.h
Normal file
35
include/hw/cpu/arm11mpcore.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* ARM11MPCore internal peripheral emulation.
|
||||
*
|
||||
* Copyright (c) 2006-2007 CodeSourcery.
|
||||
* Written by Paul Brook
|
||||
*
|
||||
* This code is licensed under the GPL.
|
||||
*/
|
||||
|
||||
#ifndef HW_CPU_ARM11MPCORE_H
|
||||
#define HW_CPU_ARM11MPCORE_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/misc/arm11scu.h"
|
||||
#include "hw/intc/arm_gic.h"
|
||||
#include "hw/timer/arm_mptimer.h"
|
||||
|
||||
#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv"
|
||||
#define ARM11MPCORE_PRIV(obj) \
|
||||
OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV)
|
||||
|
||||
typedef struct ARM11MPCorePriveState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
uint32_t num_cpu;
|
||||
MemoryRegion container;
|
||||
uint32_t num_irq;
|
||||
|
||||
ARM11SCUState scu;
|
||||
GICState gic;
|
||||
ARMMPTimerState mptimer;
|
||||
ARMMPTimerState wdtimer;
|
||||
} ARM11MPCorePriveState;
|
||||
|
||||
#endif
|
42
include/hw/intc/arm_gic.h
Normal file
42
include/hw/intc/arm_gic.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* ARM GIC support
|
||||
*
|
||||
* Copyright (c) 2012 Linaro Limited
|
||||
* Written by Peter Maydell
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HW_ARM_GIC_H
|
||||
#define HW_ARM_GIC_H
|
||||
|
||||
#include "arm_gic_common.h"
|
||||
|
||||
#define TYPE_ARM_GIC "arm_gic"
|
||||
#define ARM_GIC(obj) \
|
||||
OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC)
|
||||
#define ARM_GIC_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC)
|
||||
#define ARM_GIC_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC)
|
||||
|
||||
typedef struct ARMGICClass {
|
||||
/*< private >*/
|
||||
ARMGICCommonClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
DeviceRealize parent_realize;
|
||||
} ARMGICClass;
|
||||
|
||||
#endif
|
92
include/hw/intc/arm_gic_common.h
Normal file
92
include/hw/intc/arm_gic_common.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* ARM GIC support
|
||||
*
|
||||
* Copyright (c) 2012 Linaro Limited
|
||||
* Written by Peter Maydell
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HW_ARM_GIC_COMMON_H
|
||||
#define HW_ARM_GIC_COMMON_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
/* Maximum number of possible interrupts, determined by the GIC architecture */
|
||||
#define GIC_MAXIRQ 1020
|
||||
/* First 32 are private to each CPU (SGIs and PPIs). */
|
||||
#define GIC_INTERNAL 32
|
||||
/* Maximum number of possible CPU interfaces, determined by GIC architecture */
|
||||
#define GIC_NCPU 8
|
||||
|
||||
typedef struct gic_irq_state {
|
||||
/* The enable bits are only banked for per-cpu interrupts. */
|
||||
uint8_t enabled;
|
||||
uint8_t pending;
|
||||
uint8_t active;
|
||||
uint8_t level;
|
||||
bool model; /* 0 = N:N, 1 = 1:N */
|
||||
bool trigger; /* nonzero = edge triggered. */
|
||||
} gic_irq_state;
|
||||
|
||||
typedef struct GICState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
qemu_irq parent_irq[GIC_NCPU];
|
||||
bool enabled;
|
||||
bool cpu_enabled[GIC_NCPU];
|
||||
|
||||
gic_irq_state irq_state[GIC_MAXIRQ];
|
||||
uint8_t irq_target[GIC_MAXIRQ];
|
||||
uint8_t priority1[GIC_INTERNAL][GIC_NCPU];
|
||||
uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
|
||||
uint16_t last_active[GIC_MAXIRQ][GIC_NCPU];
|
||||
|
||||
uint16_t priority_mask[GIC_NCPU];
|
||||
uint16_t running_irq[GIC_NCPU];
|
||||
uint16_t running_priority[GIC_NCPU];
|
||||
uint16_t current_pending[GIC_NCPU];
|
||||
|
||||
uint32_t num_cpu;
|
||||
|
||||
MemoryRegion iomem; /* Distributor */
|
||||
/* This is just so we can have an opaque pointer which identifies
|
||||
* both this GIC and which CPU interface we should be accessing.
|
||||
*/
|
||||
struct GICState *backref[GIC_NCPU];
|
||||
MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */
|
||||
uint32_t num_irq;
|
||||
uint32_t revision;
|
||||
} GICState;
|
||||
|
||||
#define TYPE_ARM_GIC_COMMON "arm_gic_common"
|
||||
#define ARM_GIC_COMMON(obj) \
|
||||
OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON)
|
||||
#define ARM_GIC_COMMON_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON)
|
||||
#define ARM_GIC_COMMON_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON)
|
||||
|
||||
typedef struct ARMGICCommonClass {
|
||||
/*< private >*/
|
||||
SysBusDeviceClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
void (*pre_save)(GICState *s);
|
||||
void (*post_load)(GICState *s);
|
||||
} ARMGICCommonClass;
|
||||
|
||||
#endif
|
28
include/hw/intc/realview_gic.h
Normal file
28
include/hw/intc/realview_gic.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* ARM RealView Emulation Baseboard Interrupt Controller
|
||||
*
|
||||
* Copyright (c) 2006-2007 CodeSourcery.
|
||||
* Written by Paul Brook
|
||||
*
|
||||
* This code is licensed under the GPL.
|
||||
*/
|
||||
|
||||
#ifndef HW_INTC_REALVIEW_GIC_H
|
||||
#define HW_INTC_REALVIEW_GIC_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/intc/arm_gic.h"
|
||||
|
||||
#define TYPE_REALVIEW_GIC "realview_gic"
|
||||
#define REALVIEW_GIC(obj) \
|
||||
OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC)
|
||||
|
||||
typedef struct RealViewGICState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion container;
|
||||
|
||||
GICState gic;
|
||||
} RealViewGICState;
|
||||
|
||||
#endif
|
31
include/hw/misc/a9scu.h
Normal file
31
include/hw/misc/a9scu.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Cortex-A9MPCore Snoop Control Unit (SCU) emulation.
|
||||
*
|
||||
* Copyright (c) 2009 CodeSourcery.
|
||||
* Copyright (c) 2011 Linaro Limited.
|
||||
* Written by Paul Brook, Peter Maydell.
|
||||
*
|
||||
* This code is licensed under the GPL.
|
||||
*/
|
||||
#ifndef HW_MISC_A9SCU_H
|
||||
#define HW_MISC_A9SCU_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
/* A9MP private memory region. */
|
||||
|
||||
typedef struct A9SCUState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
MemoryRegion iomem;
|
||||
uint32_t control;
|
||||
uint32_t status;
|
||||
uint32_t num_cpu;
|
||||
} A9SCUState;
|
||||
|
||||
#define TYPE_A9_SCU "a9-scu"
|
||||
#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU)
|
||||
|
||||
#endif
|
29
include/hw/misc/arm11scu.h
Normal file
29
include/hw/misc/arm11scu.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* ARM11MPCore Snoop Control Unit (SCU) emulation
|
||||
*
|
||||
* Copyright (c) 2006-2007 CodeSourcery.
|
||||
* Copyright (c) 2013 SUSE LINUX Products GmbH
|
||||
* Written by Paul Brook and Andreas Färber
|
||||
*
|
||||
* This code is licensed under the GPL.
|
||||
*/
|
||||
|
||||
#ifndef HW_MISC_ARM11SCU_H
|
||||
#define HW_MISC_ARM11SCU_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_ARM11_SCU "arm11-scu"
|
||||
#define ARM11_SCU(obj) OBJECT_CHECK(ARM11SCUState, (obj), TYPE_ARM11_SCU)
|
||||
|
||||
typedef struct ARM11SCUState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
uint32_t control;
|
||||
uint32_t num_cpu;
|
||||
MemoryRegion iomem;
|
||||
} ARM11SCUState;
|
||||
|
||||
#endif
|
@ -3,11 +3,11 @@
|
||||
|
||||
/* PCMCIA/Cardbus */
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "hw/qdev.h"
|
||||
|
||||
typedef struct {
|
||||
typedef struct PCMCIASocket {
|
||||
qemu_irq irq;
|
||||
int attached;
|
||||
bool attached;
|
||||
const char *slot_string;
|
||||
const char *card_string;
|
||||
} PCMCIASocket;
|
||||
@ -16,22 +16,42 @@ void pcmcia_socket_register(PCMCIASocket *socket);
|
||||
void pcmcia_socket_unregister(PCMCIASocket *socket);
|
||||
void pcmcia_info(Monitor *mon, const QDict *qdict);
|
||||
|
||||
#define TYPE_PCMCIA_CARD "pcmcia-card"
|
||||
#define PCMCIA_CARD(obj) \
|
||||
OBJECT_CHECK(PCMCIACardState, (obj), TYPE_PCMCIA_CARD)
|
||||
#define PCMCIA_CARD_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(PCMCIACardClass, obj, TYPE_PCMCIA_CARD)
|
||||
#define PCMCIA_CARD_CLASS(cls) \
|
||||
OBJECT_CLASS_CHECK(PCMCIACardClass, cls, TYPE_PCMCIA_CARD)
|
||||
|
||||
struct PCMCIACardState {
|
||||
void *state;
|
||||
/*< private >*/
|
||||
DeviceState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
PCMCIASocket *slot;
|
||||
int (*attach)(void *state);
|
||||
int (*detach)(void *state);
|
||||
};
|
||||
|
||||
typedef struct PCMCIACardClass {
|
||||
/*< private >*/
|
||||
DeviceClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
int (*attach)(PCMCIACardState *state);
|
||||
int (*detach)(PCMCIACardState *state);
|
||||
|
||||
const uint8_t *cis;
|
||||
int cis_len;
|
||||
|
||||
/* Only valid if attached */
|
||||
uint8_t (*attr_read)(void *state, uint32_t address);
|
||||
void (*attr_write)(void *state, uint32_t address, uint8_t value);
|
||||
uint16_t (*common_read)(void *state, uint32_t address);
|
||||
void (*common_write)(void *state, uint32_t address, uint16_t value);
|
||||
uint16_t (*io_read)(void *state, uint32_t address);
|
||||
void (*io_write)(void *state, uint32_t address, uint16_t value);
|
||||
};
|
||||
uint8_t (*attr_read)(PCMCIACardState *card, uint32_t address);
|
||||
void (*attr_write)(PCMCIACardState *card, uint32_t address, uint8_t value);
|
||||
uint16_t (*common_read)(PCMCIACardState *card, uint32_t address);
|
||||
void (*common_write)(PCMCIACardState *card,
|
||||
uint32_t address, uint16_t value);
|
||||
uint16_t (*io_read)(PCMCIACardState *card, uint32_t address);
|
||||
void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value);
|
||||
} PCMCIACardClass;
|
||||
|
||||
#define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */
|
||||
#define CISTPL_NO_LINK 0x14 /* No Link Tuple */
|
||||
|
@ -221,7 +221,6 @@ void qdev_init_nofail(DeviceState *dev);
|
||||
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
|
||||
int required_for_version);
|
||||
void qdev_unplug(DeviceState *dev, Error **errp);
|
||||
void qdev_free(DeviceState *dev);
|
||||
int qdev_simple_unplug_cb(DeviceState *dev);
|
||||
void qdev_machine_creation_done(void);
|
||||
bool qdev_machine_modified(void);
|
||||
|
54
include/hw/timer/arm_mptimer.h
Normal file
54
include/hw/timer/arm_mptimer.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Private peripheral timer/watchdog blocks for ARM 11MPCore and A9MP
|
||||
*
|
||||
* Copyright (c) 2006-2007 CodeSourcery.
|
||||
* Copyright (c) 2011 Linaro Limited
|
||||
* Written by Paul Brook, Peter Maydell
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef HW_TIMER_ARM_MPTIMER_H
|
||||
#define HW_TIMER_ARM_MPTIMER_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define ARM_MPTIMER_MAX_CPUS 4
|
||||
|
||||
/* State of a single timer or watchdog block */
|
||||
typedef struct {
|
||||
uint32_t count;
|
||||
uint32_t load;
|
||||
uint32_t control;
|
||||
uint32_t status;
|
||||
int64_t tick;
|
||||
QEMUTimer *timer;
|
||||
qemu_irq irq;
|
||||
MemoryRegion iomem;
|
||||
} TimerBlock;
|
||||
|
||||
#define TYPE_ARM_MPTIMER "arm_mptimer"
|
||||
#define ARM_MPTIMER(obj) \
|
||||
OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER)
|
||||
|
||||
typedef struct {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
uint32_t num_cpu;
|
||||
TimerBlock timerblock[ARM_MPTIMER_MAX_CPUS];
|
||||
MemoryRegion iomem;
|
||||
} ARMMPTimerState;
|
||||
|
||||
#endif
|
@ -794,27 +794,6 @@ void object_property_add(Object *obj, const char *name, const char *type,
|
||||
|
||||
void object_property_del(Object *obj, const char *name, Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_add_uint8_ptr:
|
||||
* object_property_add_uint16_ptr:
|
||||
* object_property_add_uint32_ptr:
|
||||
* object_property_add_uint64_ptr:
|
||||
* @obj: the object to add a property to
|
||||
* @name: the name of the property
|
||||
* @v: pointer to value
|
||||
*
|
||||
* Add an integer property in memory. This function will add a
|
||||
* property of the appropriate type.
|
||||
*/
|
||||
void object_property_add_uint8_ptr(Object *obj, const char *name,
|
||||
const uint8_t *v, Error **errp);
|
||||
void object_property_add_uint16_ptr(Object *obj, const char *name,
|
||||
const uint16_t *v, Error **errp);
|
||||
void object_property_add_uint32_ptr(Object *obj, const char *name,
|
||||
const uint32_t *v, Error **errp);
|
||||
void object_property_add_uint64_ptr(Object *obj, const char *name,
|
||||
const uint64_t *v, Error **Errp);
|
||||
|
||||
/**
|
||||
* object_property_find:
|
||||
* @obj: the object
|
||||
@ -1133,6 +1112,58 @@ void object_property_add_bool(Object *obj, const char *name,
|
||||
void (*set)(Object *, bool, Error **),
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_add_uint8_ptr:
|
||||
* @obj: the object to add a property to
|
||||
* @name: the name of the property
|
||||
* @v: pointer to value
|
||||
* @errp: if an error occurs, a pointer to an area to store the error
|
||||
*
|
||||
* Add an integer property in memory. This function will add a
|
||||
* property of type 'uint8'.
|
||||
*/
|
||||
void object_property_add_uint8_ptr(Object *obj, const char *name,
|
||||
const uint8_t *v, Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_add_uint16_ptr:
|
||||
* @obj: the object to add a property to
|
||||
* @name: the name of the property
|
||||
* @v: pointer to value
|
||||
* @errp: if an error occurs, a pointer to an area to store the error
|
||||
*
|
||||
* Add an integer property in memory. This function will add a
|
||||
* property of type 'uint16'.
|
||||
*/
|
||||
void object_property_add_uint16_ptr(Object *obj, const char *name,
|
||||
const uint16_t *v, Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_add_uint32_ptr:
|
||||
* @obj: the object to add a property to
|
||||
* @name: the name of the property
|
||||
* @v: pointer to value
|
||||
* @errp: if an error occurs, a pointer to an area to store the error
|
||||
*
|
||||
* Add an integer property in memory. This function will add a
|
||||
* property of type 'uint32'.
|
||||
*/
|
||||
void object_property_add_uint32_ptr(Object *obj, const char *name,
|
||||
const uint32_t *v, Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_add_uint64_ptr:
|
||||
* @obj: the object to add a property to
|
||||
* @name: the name of the property
|
||||
* @v: pointer to value
|
||||
* @errp: if an error occurs, a pointer to an area to store the error
|
||||
*
|
||||
* Add an integer property in memory. This function will add a
|
||||
* property of type 'uint64'.
|
||||
*/
|
||||
void object_property_add_uint64_ptr(Object *obj, const char *name,
|
||||
const uint64_t *v, Error **Errp);
|
||||
|
||||
/**
|
||||
* object_child_foreach:
|
||||
* @obj: the object whose children will be navigated
|
||||
|
@ -453,11 +453,12 @@ static BusState *qbus_find(const char *path)
|
||||
|
||||
DeviceState *qdev_device_add(QemuOpts *opts)
|
||||
{
|
||||
ObjectClass *obj;
|
||||
DeviceClass *k;
|
||||
ObjectClass *oc;
|
||||
DeviceClass *dc;
|
||||
const char *driver, *path, *id;
|
||||
DeviceState *qdev;
|
||||
DeviceState *dev;
|
||||
BusState *bus = NULL;
|
||||
Error *err = NULL;
|
||||
|
||||
driver = qemu_opt_get(opts, "driver");
|
||||
if (!driver) {
|
||||
@ -466,22 +467,28 @@ DeviceState *qdev_device_add(QemuOpts *opts)
|
||||
}
|
||||
|
||||
/* find driver */
|
||||
obj = object_class_by_name(driver);
|
||||
if (!obj) {
|
||||
oc = object_class_by_name(driver);
|
||||
if (!oc) {
|
||||
const char *typename = find_typename_by_alias(driver);
|
||||
|
||||
if (typename) {
|
||||
driver = typename;
|
||||
obj = object_class_by_name(driver);
|
||||
oc = object_class_by_name(driver);
|
||||
}
|
||||
}
|
||||
|
||||
if (!obj) {
|
||||
if (!oc) {
|
||||
qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
k = DEVICE_CLASS(obj);
|
||||
if (object_class_is_abstract(oc)) {
|
||||
qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver",
|
||||
"non-abstract device type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dc = DEVICE_CLASS(oc);
|
||||
|
||||
/* find bus */
|
||||
path = qemu_opt_get(opts, "bus");
|
||||
@ -490,16 +497,16 @@ DeviceState *qdev_device_add(QemuOpts *opts)
|
||||
if (!bus) {
|
||||
return NULL;
|
||||
}
|
||||
if (!object_dynamic_cast(OBJECT(bus), k->bus_type)) {
|
||||
if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
|
||||
qerror_report(QERR_BAD_BUS_FOR_DEVICE,
|
||||
driver, object_get_typename(OBJECT(bus)));
|
||||
return NULL;
|
||||
}
|
||||
} else if (k->bus_type != NULL) {
|
||||
bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type);
|
||||
} else if (dc->bus_type != NULL) {
|
||||
bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
|
||||
if (!bus) {
|
||||
qerror_report(QERR_NO_BUS_FOR_DEVICE,
|
||||
k->bus_type, driver);
|
||||
dc->bus_type, driver);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -509,36 +516,42 @@ DeviceState *qdev_device_add(QemuOpts *opts)
|
||||
}
|
||||
|
||||
/* create device, set properties */
|
||||
qdev = DEVICE(object_new(driver));
|
||||
dev = DEVICE(object_new(driver));
|
||||
|
||||
if (bus) {
|
||||
qdev_set_parent_bus(qdev, bus);
|
||||
qdev_set_parent_bus(dev, bus);
|
||||
}
|
||||
|
||||
id = qemu_opts_id(opts);
|
||||
if (id) {
|
||||
qdev->id = id;
|
||||
dev->id = id;
|
||||
}
|
||||
if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
|
||||
qdev_free(qdev);
|
||||
if (qemu_opt_foreach(opts, set_property, dev, 1) != 0) {
|
||||
object_unparent(OBJECT(dev));
|
||||
object_unref(OBJECT(dev));
|
||||
return NULL;
|
||||
}
|
||||
if (qdev->id) {
|
||||
object_property_add_child(qdev_get_peripheral(), qdev->id,
|
||||
OBJECT(qdev), NULL);
|
||||
if (dev->id) {
|
||||
object_property_add_child(qdev_get_peripheral(), dev->id,
|
||||
OBJECT(dev), 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);
|
||||
OBJECT(dev), NULL);
|
||||
g_free(name);
|
||||
}
|
||||
if (qdev_init(qdev) < 0) {
|
||||
}
|
||||
object_property_set_bool(OBJECT(dev), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
qerror_report_err(err);
|
||||
error_free(err);
|
||||
object_unparent(OBJECT(dev));
|
||||
object_unref(OBJECT(dev));
|
||||
qerror_report(QERR_DEVICE_INIT_FAILED, driver);
|
||||
return NULL;
|
||||
}
|
||||
qdev->opts = opts;
|
||||
return qdev;
|
||||
dev->opts = opts;
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,25 +67,50 @@ check-qtest-i386-y += tests/boot-order-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/rtc-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/i440fx-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-x86_64-y = $(check-qtest-i386-y)
|
||||
gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c
|
||||
gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
|
||||
check-qtest-mips-y = tests/endianness-test$(EXESUF)
|
||||
check-qtest-mips64-y = tests/endianness-test$(EXESUF)
|
||||
check-qtest-mips64el-y = tests/endianness-test$(EXESUF)
|
||||
check-qtest-mips-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-mipsel-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-mips64-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-mips64el-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-ppc-y = tests/endianness-test$(EXESUF)
|
||||
check-qtest-ppc64-y = tests/endianness-test$(EXESUF)
|
||||
check-qtest-sh4-y = tests/endianness-test$(EXESUF)
|
||||
check-qtest-sh4eb-y = tests/endianness-test$(EXESUF)
|
||||
check-qtest-sh4-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-sh4eb-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-sparc64-y = tests/endianness-test$(EXESUF)
|
||||
#check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
|
||||
#check-qtest-sparc64-y += tests/m48t59-test$(EXESUF)
|
||||
gcov-files-sparc-y += hw/m48t59.c
|
||||
gcov-files-sparc64-y += hw/m48t59.c
|
||||
check-qtest-sparc-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-sparc64-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-arm-y = tests/tmp105-test$(EXESUF)
|
||||
gcov-files-arm-y += hw/tmp105.c
|
||||
check-qtest-arm-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-ppc-y += tests/boot-order-test$(EXESUF)
|
||||
check-qtest-ppc64-y += tests/boot-order-test$(EXESUF)
|
||||
check-qtest-ppc-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-ppc64-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-ppcemb-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-alpha-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-cris-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-lm32-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-m68k-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-microblaze-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
|
||||
check-qtest-moxie-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-or32-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-s390x-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-unicore32-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-xtensa-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
|
||||
|
||||
check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
|
||||
comments.json empty.json funny-char.json indented-expr.json \
|
||||
@ -174,6 +199,7 @@ tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
|
||||
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
|
||||
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
|
||||
tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
|
||||
tests/qom-test$(EXESUF): tests/qom-test.o
|
||||
tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
|
||||
|
||||
# QTest rules
|
||||
|
253
tests/qom-test.c
Normal file
253
tests/qom-test.c
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* QTest testcase for QOM
|
||||
*
|
||||
* Copyright (c) 2013 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#include "libqtest.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
static void test_nop(gconstpointer data)
|
||||
{
|
||||
QTestState *s;
|
||||
const char *machine = data;
|
||||
char *args;
|
||||
|
||||
args = g_strdup_printf("-display none -machine %s", machine);
|
||||
s = qtest_start(args);
|
||||
if (s) {
|
||||
qtest_quit(s);
|
||||
}
|
||||
g_free(args);
|
||||
}
|
||||
|
||||
static const char *x86_machines[] = {
|
||||
"pc",
|
||||
"isapc",
|
||||
"q35",
|
||||
};
|
||||
|
||||
static const char *alpha_machines[] = {
|
||||
"clipper",
|
||||
};
|
||||
|
||||
static const char *arm_machines[] = {
|
||||
"integratorcp",
|
||||
"versatilepb",
|
||||
"versatileab",
|
||||
"lm3s811evb",
|
||||
"lm3s6965evb",
|
||||
"collie",
|
||||
"akita",
|
||||
"spitz",
|
||||
"borzoi",
|
||||
"terrier",
|
||||
"tosa",
|
||||
"cheetah",
|
||||
"sx1-v1",
|
||||
"sx1",
|
||||
"realview-eb",
|
||||
"realview-eb-mpcore",
|
||||
"realview-pb-a8",
|
||||
"realview-pbx-a9",
|
||||
"musicpal",
|
||||
"mainstone",
|
||||
"connex",
|
||||
"verdex",
|
||||
"z2",
|
||||
"n800",
|
||||
"n810",
|
||||
"kzm",
|
||||
"vexpress-a9",
|
||||
"vexpress-a15",
|
||||
"smdkc210",
|
||||
"nuri",
|
||||
"xilinx-zynq-a9",
|
||||
"highbank",
|
||||
"midway",
|
||||
};
|
||||
|
||||
static const char *cris_machines[] = {
|
||||
"axis-dev88",
|
||||
};
|
||||
|
||||
static const char *lm32_machines[] = {
|
||||
"lm32-evr",
|
||||
"lm32-uclinux",
|
||||
"milkymist",
|
||||
};
|
||||
|
||||
static const char *m68k_machines[] = {
|
||||
"mcf5208evb",
|
||||
"an5206",
|
||||
"dummy",
|
||||
};
|
||||
|
||||
static const char *microblaze_machines[] = {
|
||||
"petalogix-ml605",
|
||||
"petalogix-s3adsp1800",
|
||||
};
|
||||
|
||||
static const char *mips_machines[] = {
|
||||
"malta",
|
||||
"magnum",
|
||||
"mips",
|
||||
"mipssim",
|
||||
"pica61",
|
||||
};
|
||||
|
||||
static const char *moxie_machines[] = {
|
||||
"moxiesim",
|
||||
};
|
||||
|
||||
static const char *openrisc_machines[] = {
|
||||
"or32-sim",
|
||||
};
|
||||
|
||||
static const char *ppc_machines[] = {
|
||||
"g3beige",
|
||||
"mac99",
|
||||
"prep",
|
||||
"mpc8544ds",
|
||||
"ppce500",
|
||||
};
|
||||
|
||||
static const char *ppc64_machines[] = {
|
||||
"pseries",
|
||||
};
|
||||
|
||||
static const char *ppc405_machines[] = {
|
||||
"ref405ep",
|
||||
"taihu",
|
||||
};
|
||||
|
||||
static const char *ppc440_machines[] = {
|
||||
"bamboo",
|
||||
"virtex-ml507",
|
||||
};
|
||||
|
||||
static const char *s390_machines[] = {
|
||||
"s390-virtio",
|
||||
"s390-ccw-virtio",
|
||||
};
|
||||
|
||||
static const char *superh_machines[] = {
|
||||
"r2d",
|
||||
"shix",
|
||||
};
|
||||
|
||||
static const char *sparc_machines[] = {
|
||||
"SS-4",
|
||||
"SS-5",
|
||||
"SS-10",
|
||||
"SS-20",
|
||||
"SS-600MP",
|
||||
"LX",
|
||||
"SPARCClassic",
|
||||
"SPARCbook",
|
||||
"leon3_generic",
|
||||
};
|
||||
|
||||
static const char *sparc64_machines[] = {
|
||||
"sun4u",
|
||||
"sun4v",
|
||||
"Niagara",
|
||||
};
|
||||
|
||||
static const char *unicore32_machines[] = {
|
||||
"puv3",
|
||||
};
|
||||
|
||||
static const char *xtensa_machines[] = {
|
||||
"sim",
|
||||
"lx60",
|
||||
"lx200",
|
||||
};
|
||||
|
||||
static void add_test_cases(const char *arch, const char *machine)
|
||||
{
|
||||
char *path;
|
||||
path = g_strdup_printf("/%s/qom/%s", arch, machine);
|
||||
g_test_add_data_func(path, machine, test_nop);
|
||||
}
|
||||
|
||||
#define ADD_MACHINE_TESTS(arch, array) do { \
|
||||
int i; \
|
||||
for (i = 0; i < ARRAY_SIZE(array); i++) { \
|
||||
add_test_cases((arch), (array)[i]); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *arch = qtest_get_arch();
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
add_test_cases(arch, "none");
|
||||
|
||||
if (strcmp(arch, "i386") == 0 ||
|
||||
strcmp(arch, "x86_64") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, x86_machines);
|
||||
} else if (strcmp(arch, "alpha") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, alpha_machines);
|
||||
} else if (strcmp(arch, "arm") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, arm_machines);
|
||||
} else if (strcmp(arch, "cris") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, cris_machines);
|
||||
} else if (strcmp(arch, "lm32") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, lm32_machines);
|
||||
} else if (strcmp(arch, "m68k") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, m68k_machines);
|
||||
} else if (strcmp(arch, "microblaze") == 0 ||
|
||||
strcmp(arch, "microblazeel") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, microblaze_machines);
|
||||
} else if (strcmp(arch, "mips") == 0 ||
|
||||
strcmp(arch, "mipsel") == 0 ||
|
||||
strcmp(arch, "mips64") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, mips_machines);
|
||||
} else if (strcmp(arch, "mips64el") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, mips_machines);
|
||||
add_test_cases(arch, "fulong2e");
|
||||
} else if (strcmp(arch, "moxie") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, moxie_machines);
|
||||
} else if (strcmp(arch, "or32") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, openrisc_machines);
|
||||
} else if (strcmp(arch, "ppcemb") == 0) {
|
||||
#if 0
|
||||
/* XXX Available in ppcemb but don't work */
|
||||
ADD_MACHINE_TESTS(arch, ppc405_machines);
|
||||
#endif
|
||||
ADD_MACHINE_TESTS(arch, ppc440_machines);
|
||||
} else if (strcmp(arch, "ppc") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, ppc405_machines);
|
||||
ADD_MACHINE_TESTS(arch, ppc440_machines);
|
||||
ADD_MACHINE_TESTS(arch, ppc_machines);
|
||||
} else if (strcmp(arch, "ppc64") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, ppc405_machines);
|
||||
ADD_MACHINE_TESTS(arch, ppc440_machines);
|
||||
ADD_MACHINE_TESTS(arch, ppc_machines);
|
||||
ADD_MACHINE_TESTS(arch, ppc64_machines);
|
||||
} else if (strcmp(arch, "s390x") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, s390_machines);
|
||||
} else if (strcmp(arch, "sh4") == 0 ||
|
||||
strcmp(arch, "sh4eb") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, superh_machines);
|
||||
} else if (strcmp(arch, "sparc") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, sparc_machines);
|
||||
} else if (strcmp(arch, "sparc64") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, sparc64_machines);
|
||||
} else if (strcmp(arch, "unicore32") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, unicore32_machines);
|
||||
} else if (strcmp(arch, "xtensa") == 0 ||
|
||||
strcmp(arch, "xtensaeb") == 0) {
|
||||
ADD_MACHINE_TESTS(arch, xtensa_machines);
|
||||
}
|
||||
|
||||
return g_test_run();
|
||||
}
|
Loading…
Reference in New Issue
Block a user