diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/arm-misc.h | 2 | ||||
-rw-r--r-- | hw/arm/Makefile.objs | 2 | ||||
-rw-r--r-- | hw/arm_boot.c | 46 | ||||
-rw-r--r-- | hw/exynos4210.c | 27 | ||||
-rw-r--r-- | hw/exynos4210.h | 3 | ||||
-rw-r--r-- | hw/exynos4210_i2c.c | 334 | ||||
-rw-r--r-- | hw/exynos4210_rtc.c | 7 | ||||
-rw-r--r-- | hw/mfi.h | 92 | ||||
-rw-r--r-- | hw/pl011.c | 4 | ||||
-rw-r--r-- | hw/ppce500_spin.c | 2 | ||||
-rw-r--r-- | hw/qdev.h | 11 | ||||
-rw-r--r-- | hw/spapr_pci.c | 2 | ||||
-rw-r--r-- | hw/vexpress.c | 13 |
13 files changed, 475 insertions, 70 deletions
diff --git a/hw/arm-misc.h b/hw/arm-misc.h index 1f96229d3c..bdd8fecc99 100644 --- a/hw/arm-misc.h +++ b/hw/arm-misc.h @@ -25,7 +25,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, /* arm_boot.c */ struct arm_boot_info { - int ram_size; + uint64_t ram_size; const char *kernel_filename; const char *kernel_cmdline; const char *initrd_filename; diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 236786eb5a..c413780784 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -11,7 +11,7 @@ obj-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o obj-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o obj-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o -obj-y += exynos4210_rtc.o +obj-y += exynos4210_rtc.o exynos4210_i2c.o obj-y += arm_l2x0.o obj-y += arm_mptimer.o a15mpcore.o obj-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o diff --git a/hw/arm_boot.c b/hw/arm_boot.c index a1e6ddbc1c..a6e9143662 100644 --- a/hw/arm_boot.c +++ b/hw/arm_boot.c @@ -216,11 +216,12 @@ static void set_kernel_args_old(const struct arm_boot_info *info) static int load_dtb(target_phys_addr_t addr, const struct arm_boot_info *binfo) { #ifdef CONFIG_FDT - uint32_t mem_reg_property[] = { cpu_to_be32(binfo->loader_start), - cpu_to_be32(binfo->ram_size) }; + uint32_t *mem_reg_property; + uint32_t mem_reg_propsize; void *fdt = NULL; char *filename; int size, rc; + uint32_t acells, scells, hival; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename); if (!filename) { @@ -236,8 +237,36 @@ static int load_dtb(target_phys_addr_t addr, const struct arm_boot_info *binfo) } g_free(filename); + acells = qemu_devtree_getprop_cell(fdt, "/", "#address-cells"); + scells = qemu_devtree_getprop_cell(fdt, "/", "#size-cells"); + if (acells == 0 || scells == 0) { + fprintf(stderr, "dtb file invalid (#address-cells or #size-cells 0)\n"); + return -1; + } + + mem_reg_propsize = acells + scells; + mem_reg_property = g_new0(uint32_t, mem_reg_propsize); + mem_reg_property[acells - 1] = cpu_to_be32(binfo->loader_start); + hival = cpu_to_be32(binfo->loader_start >> 32); + if (acells > 1) { + mem_reg_property[acells - 2] = hival; + } else if (hival != 0) { + fprintf(stderr, "qemu: dtb file not compatible with " + "RAM start address > 4GB\n"); + exit(1); + } + mem_reg_property[acells + scells - 1] = cpu_to_be32(binfo->ram_size); + hival = cpu_to_be32(binfo->ram_size >> 32); + if (scells > 1) { + mem_reg_property[acells + scells - 2] = hival; + } else if (hival != 0) { + fprintf(stderr, "qemu: dtb file not compatible with " + "RAM size > 4GB\n"); + exit(1); + } + rc = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property, - sizeof(mem_reg_property)); + mem_reg_propsize * sizeof(uint32_t)); if (rc < 0) { fprintf(stderr, "couldn't set /memory/reg\n"); } @@ -357,7 +386,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) if (kernel_size < 0) { entry = info->loader_start + KERNEL_LOAD_ADDR; kernel_size = load_image_targphys(info->kernel_filename, entry, - ram_size - KERNEL_LOAD_ADDR); + info->ram_size - KERNEL_LOAD_ADDR); is_linux = 1; } if (kernel_size < 0) { @@ -371,7 +400,8 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) initrd_size = load_image_targphys(info->initrd_filename, info->loader_start + INITRD_LOAD_ADDR, - ram_size - INITRD_LOAD_ADDR); + info->ram_size + - INITRD_LOAD_ADDR); if (initrd_size < 0) { fprintf(stderr, "qemu: could not load initrd '%s'\n", info->initrd_filename); @@ -398,6 +428,12 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) bootloader[5] = dtb_start; } else { bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR; + if (info->ram_size >= (1ULL << 32)) { + fprintf(stderr, "qemu: RAM size must be less than 4GB to boot" + " Linux kernel using ATAGS (try passing a device tree" + " using -dtb)\n"); + exit(1); + } } bootloader[6] = entry; for (n = 0; n < sizeof(bootloader) / 4; n++) { diff --git a/hw/exynos4210.c b/hw/exynos4210.c index 7c58c906de..00d4db8871 100644 --- a/hw/exynos4210.c +++ b/hw/exynos4210.c @@ -39,6 +39,13 @@ /* MCT */ #define EXYNOS4210_MCT_BASE_ADDR 0x10050000 +/* I2C */ +#define EXYNOS4210_I2C_SHIFT 0x00010000 +#define EXYNOS4210_I2C_BASE_ADDR 0x13860000 +/* Interrupt Group of External Interrupt Combiner for I2C */ +#define EXYNOS4210_I2C_INTG 27 +#define EXYNOS4210_HDMI_INTG 16 + /* UART's definitions */ #define EXYNOS4210_UART0_BASE_ADDR 0x13800000 #define EXYNOS4210_UART1_BASE_ADDR 0x13810000 @@ -283,6 +290,26 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem, s->irq_table[exynos4210_get_irq(35, 3)]); sysbus_mmio_map(busdev, 0, EXYNOS4210_MCT_BASE_ADDR); + /*** I2C ***/ + for (n = 0; n < EXYNOS4210_I2C_NUMBER; n++) { + uint32_t addr = EXYNOS4210_I2C_BASE_ADDR + EXYNOS4210_I2C_SHIFT * n; + qemu_irq i2c_irq; + + if (n < 8) { + i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_I2C_INTG, n)]; + } else { + i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_HDMI_INTG, 1)]; + } + + dev = qdev_create(NULL, "exynos4210.i2c"); + qdev_init_nofail(dev); + busdev = sysbus_from_qdev(dev); + sysbus_connect_irq(busdev, 0, i2c_irq); + sysbus_mmio_map(busdev, 0, addr); + s->i2c_if[n] = (i2c_bus *)qdev_get_child_bus(dev, "i2c"); + } + + /*** UARTs ***/ exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR, EXYNOS4210_UART0_FIFO_SIZE, 0, NULL, diff --git a/hw/exynos4210.h b/hw/exynos4210.h index 9b1ae4c8b1..a43ba3aedc 100644 --- a/hw/exynos4210.h +++ b/hw/exynos4210.h @@ -74,6 +74,8 @@ #define EXYNOS4210_EXT_GIC_NIRQ (160-32) #define EXYNOS4210_INT_GIC_NIRQ 64 +#define EXYNOS4210_I2C_NUMBER 9 + typedef struct Exynos4210Irq { qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ]; qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ]; @@ -95,6 +97,7 @@ typedef struct Exynos4210State { MemoryRegion dram1_mem; MemoryRegion boot_secondary; MemoryRegion bootreg_mem; + i2c_bus *i2c_if[EXYNOS4210_I2C_NUMBER]; } Exynos4210State; void exynos4210_write_secondary(ARMCPU *cpu, diff --git a/hw/exynos4210_i2c.c b/hw/exynos4210_i2c.c new file mode 100644 index 0000000000..3f72a5c464 --- /dev/null +++ b/hw/exynos4210_i2c.c @@ -0,0 +1,334 @@ +/* + * Exynos4210 I2C Bus Serial Interface Emulation + * + * Copyright (C) 2012 Samsung Electronics Co Ltd. + * Maksim Kozlov, <m.kozlov@samsung.com> + * Igor Mitsyanko, <i.mitsyanko@samsung.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "qemu-timer.h" +#include "sysbus.h" +#include "i2c.h" + +#ifndef EXYNOS4_I2C_DEBUG +#define EXYNOS4_I2C_DEBUG 0 +#endif + +#define TYPE_EXYNOS4_I2C "exynos4210.i2c" +#define EXYNOS4_I2C(obj) \ + OBJECT_CHECK(Exynos4210I2CState, (obj), TYPE_EXYNOS4_I2C) + +/* Exynos4210 I2C memory map */ +#define EXYNOS4_I2C_MEM_SIZE 0x14 +#define I2CCON_ADDR 0x00 /* control register */ +#define I2CSTAT_ADDR 0x04 /* control/status register */ +#define I2CADD_ADDR 0x08 /* address register */ +#define I2CDS_ADDR 0x0c /* data shift register */ +#define I2CLC_ADDR 0x10 /* line control register */ + +#define I2CCON_ACK_GEN (1 << 7) +#define I2CCON_INTRS_EN (1 << 5) +#define I2CCON_INT_PEND (1 << 4) + +#define EXYNOS4_I2C_MODE(reg) (((reg) >> 6) & 3) +#define I2C_IN_MASTER_MODE(reg) (((reg) >> 6) & 2) +#define I2CMODE_MASTER_Rx 0x2 +#define I2CMODE_MASTER_Tx 0x3 +#define I2CSTAT_LAST_BIT (1 << 0) +#define I2CSTAT_OUTPUT_EN (1 << 4) +#define I2CSTAT_START_BUSY (1 << 5) + + +#if EXYNOS4_I2C_DEBUG +#define DPRINT(fmt, args...) \ + do { fprintf(stderr, "QEMU I2C: "fmt, ## args); } while (0) + +static const char *exynos4_i2c_get_regname(unsigned offset) +{ + switch (offset) { + case I2CCON_ADDR: + return "I2CCON"; + case I2CSTAT_ADDR: + return "I2CSTAT"; + case I2CADD_ADDR: + return "I2CADD"; + case I2CDS_ADDR: + return "I2CDS"; + case I2CLC_ADDR: + return "I2CLC"; + default: + return "[?]"; + } +} + +#else +#define DPRINT(fmt, args...) do { } while (0) +#endif + +typedef struct Exynos4210I2CState { + SysBusDevice busdev; + MemoryRegion iomem; + i2c_bus *bus; + qemu_irq irq; + + uint8_t i2ccon; + uint8_t i2cstat; + uint8_t i2cadd; + uint8_t i2cds; + uint8_t i2clc; + bool scl_free; +} Exynos4210I2CState; + +static inline void exynos4210_i2c_raise_interrupt(Exynos4210I2CState *s) +{ + if (s->i2ccon & I2CCON_INTRS_EN) { + s->i2ccon |= I2CCON_INT_PEND; + qemu_irq_raise(s->irq); + } +} + +static void exynos4210_i2c_data_receive(void *opaque) +{ + Exynos4210I2CState *s = (Exynos4210I2CState *)opaque; + int ret; + + s->i2cstat &= ~I2CSTAT_LAST_BIT; + s->scl_free = false; + ret = i2c_recv(s->bus); + if (ret < 0 && (s->i2ccon & I2CCON_ACK_GEN)) { + s->i2cstat |= I2CSTAT_LAST_BIT; /* Data is not acknowledged */ + } else { + s->i2cds = ret; + } + exynos4210_i2c_raise_interrupt(s); +} + +static void exynos4210_i2c_data_send(void *opaque) +{ + Exynos4210I2CState *s = (Exynos4210I2CState *)opaque; + + s->i2cstat &= ~I2CSTAT_LAST_BIT; + s->scl_free = false; + if (i2c_send(s->bus, s->i2cds) < 0 && (s->i2ccon & I2CCON_ACK_GEN)) { + s->i2cstat |= I2CSTAT_LAST_BIT; + } + exynos4210_i2c_raise_interrupt(s); +} + +static uint64_t exynos4210_i2c_read(void *opaque, target_phys_addr_t offset, + unsigned size) +{ + Exynos4210I2CState *s = (Exynos4210I2CState *)opaque; + uint8_t value; + + switch (offset) { + case I2CCON_ADDR: + value = s->i2ccon; + break; + case I2CSTAT_ADDR: + value = s->i2cstat; + break; + case I2CADD_ADDR: + value = s->i2cadd; + break; + case I2CDS_ADDR: + value = s->i2cds; + s->scl_free = true; + if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Rx && + (s->i2cstat & I2CSTAT_START_BUSY) && + !(s->i2ccon & I2CCON_INT_PEND)) { + exynos4210_i2c_data_receive(s); + } + break; + case I2CLC_ADDR: + value = s->i2clc; + break; + default: + value = 0; + DPRINT("ERROR: Bad read offset 0x%x\n", (unsigned int)offset); + break; + } + + DPRINT("read %s [0x%02x] -> 0x%02x\n", exynos4_i2c_get_regname(offset), + (unsigned int)offset, value); + return value; +} + +static void exynos4210_i2c_write(void *opaque, target_phys_addr_t offset, + uint64_t value, unsigned size) +{ + Exynos4210I2CState *s = (Exynos4210I2CState *)opaque; + uint8_t v = value & 0xff; + + DPRINT("write %s [0x%02x] <- 0x%02x\n", exynos4_i2c_get_regname(offset), + (unsigned int)offset, v); + + switch (offset) { + case I2CCON_ADDR: + s->i2ccon = (v & ~I2CCON_INT_PEND) | (s->i2ccon & I2CCON_INT_PEND); + if ((s->i2ccon & I2CCON_INT_PEND) && !(v & I2CCON_INT_PEND)) { + s->i2ccon &= ~I2CCON_INT_PEND; + qemu_irq_lower(s->irq); + if (!(s->i2ccon & I2CCON_INTRS_EN)) { + s->i2cstat &= ~I2CSTAT_START_BUSY; + } + + if (s->i2cstat & I2CSTAT_START_BUSY) { + if (s->scl_free) { + if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Tx) { + exynos4210_i2c_data_send(s); + } else if (EXYNOS4_I2C_MODE(s->i2cstat) == + I2CMODE_MASTER_Rx) { + exynos4210_i2c_data_receive(s); + } + } else { + s->i2ccon |= I2CCON_INT_PEND; + qemu_irq_raise(s->irq); + } + } + } + break; + case I2CSTAT_ADDR: + s->i2cstat = + (s->i2cstat & I2CSTAT_START_BUSY) | (v & ~I2CSTAT_START_BUSY); + + if (!(s->i2cstat & I2CSTAT_OUTPUT_EN)) { + s->i2cstat &= ~I2CSTAT_START_BUSY; + s->scl_free = true; + qemu_irq_lower(s->irq); + break; + } + + /* Nothing to do if in i2c slave mode */ + if (!I2C_IN_MASTER_MODE(s->i2cstat)) { + break; + } + + if (v & I2CSTAT_START_BUSY) { + s->i2cstat &= ~I2CSTAT_LAST_BIT; + s->i2cstat |= I2CSTAT_START_BUSY; /* Line is busy */ + s->scl_free = false; + + /* Generate start bit and send slave address */ + if (i2c_start_transfer(s->bus, s->i2cds >> 1, s->i2cds & 0x1) && + (s->i2ccon & I2CCON_ACK_GEN)) { + s->i2cstat |= I2CSTAT_LAST_BIT; + } else if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Rx) { + exynos4210_i2c_data_receive(s); + } + exynos4210_i2c_raise_interrupt(s); + } else { + i2c_end_transfer(s->bus); + if (!(s->i2ccon & I2CCON_INT_PEND)) { + s->i2cstat &= ~I2CSTAT_START_BUSY; + } + s->scl_free = true; + } + break; + case I2CADD_ADDR: + if ((s->i2cstat & I2CSTAT_OUTPUT_EN) == 0) { + s->i2cadd = v; + } + break; + case I2CDS_ADDR: + if (s->i2cstat & I2CSTAT_OUTPUT_EN) { + s->i2cds = v; + s->scl_free = true; + if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Tx && + (s->i2cstat & I2CSTAT_START_BUSY) && + !(s->i2ccon & I2CCON_INT_PEND)) { + exynos4210_i2c_data_send(s); + } + } + break; + case I2CLC_ADDR: + s->i2clc = v; + break; + default: + DPRINT("ERROR: Bad write offset 0x%x\n", (unsigned int)offset); + break; + } +} + +static const MemoryRegionOps exynos4210_i2c_ops = { + .read = exynos4210_i2c_read, + .write = exynos4210_i2c_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static const VMStateDescription exynos4210_i2c_vmstate = { + .name = TYPE_EXYNOS4_I2C, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(i2ccon, Exynos4210I2CState), + VMSTATE_UINT8(i2cstat, Exynos4210I2CState), + VMSTATE_UINT8(i2cds, Exynos4210I2CState), + VMSTATE_UINT8(i2cadd, Exynos4210I2CState), + VMSTATE_UINT8(i2clc, Exynos4210I2CState), + VMSTATE_BOOL(scl_free, Exynos4210I2CState), + VMSTATE_END_OF_LIST() + } +}; + +static void exynos4210_i2c_reset(DeviceState *d) +{ + Exynos4210I2CState *s = EXYNOS4_I2C(d); + + s->i2ccon = 0x00; + s->i2cstat = 0x00; + s->i2cds = 0xFF; + s->i2clc = 0x00; + s->i2cadd = 0xFF; + s->scl_free = true; +} + +static int exynos4210_i2c_realize(SysBusDevice *dev) +{ + Exynos4210I2CState *s = EXYNOS4_I2C(dev); + + memory_region_init_io(&s->iomem, &exynos4210_i2c_ops, s, TYPE_EXYNOS4_I2C, + EXYNOS4_I2C_MEM_SIZE); + sysbus_init_mmio(dev, &s->iomem); + sysbus_init_irq(dev, &s->irq); + s->bus = i2c_init_bus(&dev->qdev, "i2c"); + return 0; +} + +static void exynos4210_i2c_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *sbdc = SYS_BUS_DEVICE_CLASS(klass); + + dc->vmsd = &exynos4210_i2c_vmstate; + dc->reset = exynos4210_i2c_reset; + sbdc->init = exynos4210_i2c_realize; +} + +static const TypeInfo exynos4210_i2c_type_info = { + .name = TYPE_EXYNOS4_I2C, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Exynos4210I2CState), + .class_init = exynos4210_i2c_class_init, +}; + +static void exynos4210_i2c_register_types(void) +{ + type_register_static(&exynos4210_i2c_type_info); +} + +type_init(exynos4210_i2c_register_types) diff --git a/hw/exynos4210_rtc.c b/hw/exynos4210_rtc.c index f78102049b..42a4ddc327 100644 --- a/hw/exynos4210_rtc.c +++ b/hw/exynos4210_rtc.c @@ -142,7 +142,7 @@ static const VMStateDescription vmstate_exynos4210_rtc_state = { }; #define BCD3DIGITS(x) \ - ((uint32_t)to_bcd((uint8_t)x) + \ + ((uint32_t)to_bcd((uint8_t)(x % 100)) + \ ((uint32_t)to_bcd((uint8_t)((x % 1000) / 100)) << 8)) static void check_alarm_raise(Exynos4210RTCState *s) @@ -510,10 +510,7 @@ static void exynos4210_rtc_reset(DeviceState *d) { Exynos4210RTCState *s = (Exynos4210RTCState *)d; - struct tm tm; - - qemu_get_timedate(&tm, 0); - s->current_tm = tm; + qemu_get_timedate(&s->current_tm, 0); DPRINTF("Get time from host: %d-%d-%d %2d:%02d:%02d\n", s->current_tm.tm_year, s->current_tm.tm_mon, s->current_tm.tm_mday, @@ -435,24 +435,24 @@ typedef enum { struct mfi_sg32 { uint32_t addr; uint32_t len; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_sg64 { uint64_t addr; uint32_t len; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_sg_skinny { uint64_t addr; uint32_t len; uint32_t flag; -} __attribute__ ((packed)); +} QEMU_PACKED; union mfi_sgl { struct mfi_sg32 sg32[1]; struct mfi_sg64 sg64[1]; struct mfi_sg_skinny sg_skinny[1]; -} __attribute__ ((packed)); +} QEMU_PACKED; /* Message frames. All messages have a common header */ struct mfi_frame_header { @@ -468,7 +468,7 @@ struct mfi_frame_header { uint16_t flags; uint16_t timeout; uint32_t data_len; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_init_frame { struct mfi_frame_header header; @@ -487,7 +487,7 @@ struct mfi_io_frame { uint32_t lba_lo; uint32_t lba_hi; union mfi_sgl sgl; -} __attribute__ ((packed)); +} QEMU_PACKED; #define MFI_PASS_FRAME_SIZE 48 struct mfi_pass_frame { @@ -496,7 +496,7 @@ struct mfi_pass_frame { uint32_t sense_addr_hi; uint8_t cdb[16]; union mfi_sgl sgl; -} __attribute__ ((packed)); +} QEMU_PACKED; #define MFI_DCMD_FRAME_SIZE 40 struct mfi_dcmd_frame { @@ -504,7 +504,7 @@ struct mfi_dcmd_frame { uint32_t opcode; uint8_t mbox[MFI_MBOX_SIZE]; union mfi_sgl sgl; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_abort_frame { struct mfi_frame_header header; @@ -512,7 +512,7 @@ struct mfi_abort_frame { uint32_t abort_mfi_addr_lo; uint32_t abort_mfi_addr_hi; uint32_t reserved1[6]; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_smp_frame { struct mfi_frame_header header; @@ -521,7 +521,7 @@ struct mfi_smp_frame { struct mfi_sg32 sg32[2]; struct mfi_sg64 sg64[2]; } sgl; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_stp_frame { struct mfi_frame_header header; @@ -531,7 +531,7 @@ struct mfi_stp_frame { struct mfi_sg32 sg32[2]; struct mfi_sg64 sg64[2]; } sgl; -} __attribute__ ((packed)); +} QEMU_PACKED; union mfi_frame { struct mfi_frame_header header; @@ -563,7 +563,7 @@ struct mfi_init_qinfo { uint32_t pi_addr_hi; uint32_t ci_addr_lo; uint32_t ci_addr_hi; -} __attribute__ ((packed)); +} QEMU_PACKED; /* Controller properties */ struct mfi_ctrl_props { @@ -626,7 +626,7 @@ struct mfi_ctrl_props { * is spun down (0=use FW defaults) */ uint8_t reserved[24]; -} __attribute__ ((packed)); +} QEMU_PACKED; /* PCI information about the card. */ struct mfi_info_pci { @@ -635,7 +635,7 @@ struct mfi_info_pci { uint16_t subvendor; uint16_t subdevice; uint8_t reserved[24]; -} __attribute__ ((packed)); +} QEMU_PACKED; /* Host (front end) interface information */ struct mfi_info_host { @@ -647,7 +647,7 @@ struct mfi_info_host { uint8_t reserved[6]; uint8_t port_count; uint64_t port_addr[8]; -} __attribute__ ((packed)); +} QEMU_PACKED; /* Device (back end) interface information */ struct mfi_info_device { @@ -659,7 +659,7 @@ struct mfi_info_device { uint8_t reserved[6]; uint8_t port_count; uint64_t port_addr[8]; -} __attribute__ ((packed)); +} QEMU_PACKED; /* Firmware component information */ struct mfi_info_component { @@ -667,7 +667,7 @@ struct mfi_info_component { char version[32]; char build_date[16]; char build_time[16]; -} __attribute__ ((packed)); +} QEMU_PACKED; /* Controller default settings */ struct mfi_defaults { @@ -710,7 +710,7 @@ struct mfi_defaults { uint8_t fde_only; uint8_t delay_during_post; uint8_t resv[19]; -} __attribute__ ((packed)); +} QEMU_PACKED; /* Controller default settings */ struct mfi_bios_data { @@ -722,7 +722,7 @@ struct mfi_bios_data { uint8_t expose_all_drives; uint8_t reserved[56]; uint8_t check_sum; -} __attribute__ ((packed)); +} QEMU_PACKED; /* SAS (?) controller info, returned from MFI_DCMD_CTRL_GETINFO. */ struct mfi_ctrl_info { @@ -807,7 +807,7 @@ struct mfi_ctrl_info { uint8_t min; uint8_t max; uint8_t reserved[2]; - } __attribute__ ((packed)) stripe_sz_ops; + } QEMU_PACKED stripe_sz_ops; uint32_t pd_ops; #define MFI_INFO_PDOPS_FORCE_ONLINE 0x01 @@ -826,7 +826,7 @@ struct mfi_ctrl_info { struct mfi_ctrl_props properties; char package_version[0x60]; uint8_t pad[0x800 - 0x6a0]; -} __attribute__ ((packed)); +} QEMU_PACKED; /* keep track of an event. */ union mfi_evt { @@ -836,7 +836,7 @@ union mfi_evt { int8_t class; } members; uint32_t word; -} __attribute__ ((packed)); +} QEMU_PACKED; /* event log state. */ struct mfi_evt_log_state { @@ -845,24 +845,24 @@ struct mfi_evt_log_state { uint32_t clear_seq_num; uint32_t shutdown_seq_num; uint32_t boot_seq_num; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_progress { uint16_t progress; uint16_t elapsed_seconds; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_evt_ld { uint16_t target_id; uint8_t ld_index; uint8_t reserved; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_evt_pd { uint16_t device_id; uint8_t enclosure_index; uint8_t slot_number; -} __attribute__ ((packed)); +} QEMU_PACKED; /* event detail, returned from MFI_DCMD_CTRL_EVENT_WAIT. */ struct mfi_evt_detail { @@ -982,13 +982,13 @@ struct mfi_evt_detail { } args; char description[128]; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_evt_list { uint32_t count; uint32_t reserved; struct mfi_evt_detail event[1]; -} __attribute__ ((packed)); +} QEMU_PACKED; union mfi_pd_ref { struct { @@ -996,7 +996,7 @@ union mfi_pd_ref { uint16_t seq_num; } v; uint32_t ref; -} __attribute__ ((packed)); +} QEMU_PACKED; union mfi_pd_ddf_type { struct { @@ -1016,7 +1016,7 @@ union mfi_pd_ddf_type { uint32_t reserved; } non_disk; uint32_t type; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_pd_progress { uint32_t active; @@ -1027,7 +1027,7 @@ struct mfi_pd_progress { struct mfi_progress patrol; struct mfi_progress clear; struct mfi_progress reserved[4]; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_pd_info { union mfi_pd_ref ref; @@ -1062,7 +1062,7 @@ struct mfi_pd_info { uint8_t unusable_in_current_config; uint8_t vpd_page83_ext[64]; uint8_t reserved[512-358]; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_pd_address { uint16_t device_id; @@ -1072,14 +1072,14 @@ struct mfi_pd_address { uint8_t scsi_dev_type; uint8_t connect_port_bitmap; uint64_t sas_addr[2]; -} __attribute__ ((packed)); +} QEMU_PACKED; #define MFI_MAX_SYS_PDS 240 struct mfi_pd_list { uint32_t size; uint32_t count; struct mfi_pd_address addr[MFI_MAX_SYS_PDS]; -} __attribute__ ((packed)); +} QEMU_PACKED; union mfi_ld_ref { struct { @@ -1088,7 +1088,7 @@ union mfi_ld_ref { uint16_t seq; } v; uint32_t ref; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_ld_list { uint32_t ld_count; @@ -1099,7 +1099,7 @@ struct mfi_ld_list { uint8_t reserved2[3]; uint64_t size; } ld_list[MFI_MAX_LD]; -} __attribute__ ((packed)); +} QEMU_PACKED; enum mfi_ld_access { MFI_LD_ACCESS_RW = 0, @@ -1136,7 +1136,7 @@ struct mfi_ld_props { uint8_t current_cache_policy; uint8_t no_bgi; uint8_t reserved[7]; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_ld_params { uint8_t primary_raid_level; @@ -1149,7 +1149,7 @@ struct mfi_ld_params { uint8_t init_state; uint8_t is_consistent; uint8_t reserved[23]; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_ld_progress { uint32_t active; @@ -1162,21 +1162,21 @@ struct mfi_ld_progress { struct mfi_progress fgi; struct mfi_progress recon; struct mfi_progress reserved[4]; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_span { uint64_t start_block; uint64_t num_blocks; uint16_t array_ref; uint8_t reserved[6]; -} __attribute__ ((packed)); +} QEMU_PACKED; #define MFI_MAX_SPAN_DEPTH 8 struct mfi_ld_config { struct mfi_ld_props properties; struct mfi_ld_params params; struct mfi_span span[MFI_MAX_SPAN_DEPTH]; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_ld_info { struct mfi_ld_config ld_config; @@ -1187,7 +1187,7 @@ struct mfi_ld_info { uint8_t reserved1[1]; uint8_t vpd_page83[64]; uint8_t reserved2[16]; -} __attribute__ ((packed)); +} QEMU_PACKED; union mfi_spare_type { uint8_t flags; @@ -1195,7 +1195,7 @@ union mfi_spare_type { #define MFI_SPARE_IS_REVERTABLE (1 << 1) #define MFI_SPARE_IS_ENCL_AFFINITY (1 << 2) uint8_t type; -} __attribute__ ((packed)); +} QEMU_PACKED; #define MFI_MAX_ARRAYS 16 struct mfi_spare { @@ -1204,7 +1204,7 @@ struct mfi_spare { uint8_t reserved[2]; uint8_t array_count; uint16_t array_refd[MFI_MAX_ARRAYS]; -} __attribute__ ((packed)); +} QEMU_PACKED; #define MFI_MAX_ROW_SIZE 32 struct mfi_array { @@ -1221,7 +1221,7 @@ struct mfi_array { uint8_t slot; } encl; } pd[MFI_MAX_ROW_SIZE]; -} __attribute__ ((packed)); +} QEMU_PACKED; struct mfi_config_data { uint32_t size; @@ -1237,7 +1237,7 @@ struct mfi_config_data { struct mfi_ld_config ld[]; struct mfi_spare spare[]; */ -} __attribute__ ((packed)); +} QEMU_PACKED; #define MFI_SCSI_MAX_TARGETS 128 #define MFI_SCSI_MAX_LUNS 8 diff --git a/hw/pl011.c b/hw/pl011.c index 8a5a8f554a..3245702df0 100644 --- a/hw/pl011.c +++ b/hw/pl011.c @@ -78,7 +78,9 @@ static uint64_t pl011_read(void *opaque, target_phys_addr_t offset, if (s->read_count == s->read_trigger - 1) s->int_level &= ~ PL011_INT_RX; pl011_update(s); - qemu_chr_accept_input(s->chr); + if (s->chr) { + qemu_chr_accept_input(s->chr); + } return c; case 1: /* UARTCR */ return 0; diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index fddf2197a9..c5b8e051ec 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -40,7 +40,7 @@ typedef struct spin_info { uint32_t resv; uint32_t pir; uint64_t reserved; -} __attribute__ ((packed)) SpinInfo; +} QEMU_PACKED SpinInfo; typedef struct spin_state { SysBusDevice busdev; @@ -78,12 +78,6 @@ struct DeviceState { int alias_required_for_version; }; -/* - * This callback is used to create Open Firmware device path in accordance with - * OF spec http://forthworks.com/standards/of1275.pdf. Indicidual bus bindings - * can be found here http://playground.sun.com/1275/bindings/. - */ - #define TYPE_BUS "bus" #define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS) #define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS) @@ -95,6 +89,11 @@ struct BusClass { /* FIXME first arg should be BusState */ void (*print_dev)(Monitor *mon, DeviceState *dev, int indent); char *(*get_dev_path)(DeviceState *dev); + /* + * This callback is used to create Open Firmware device path in accordance + * with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus + * bindings can be found at http://playground.sun.com/1275/bindings/. + */ char *(*get_fw_dev_path)(DeviceState *dev); int (*reset)(BusState *bus); }; diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 47ba5ff770..b2e4f785ea 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -418,7 +418,7 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb, uint64_t child; uint64_t parent; uint64_t size; - } __attribute__((packed)) ranges[] = { + } QEMU_PACKED ranges[] = { { cpu_to_be32(b_ss(1)), cpu_to_be64(0), cpu_to_be64(phb->io_win_addr), diff --git a/hw/vexpress.c b/hw/vexpress.c index 8072c5ada9..b2dc8a5ab3 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -284,9 +284,16 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard, cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ]; } - if (ram_size > 0x80000000) { - fprintf(stderr, "vexpress-a15: cannot model more than 2GB RAM\n"); - exit(1); + { + /* We have to use a separate 64 bit variable here to avoid the gcc + * "comparison is always false due to limited range of data type" + * warning if we are on a host where ram_addr_t is 32 bits. + */ + uint64_t rsz = ram_size; + if (rsz > (30ULL * 1024 * 1024 * 1024)) { + fprintf(stderr, "vexpress-a15: cannot model more than 30GB RAM\n"); + exit(1); + } } memory_region_init_ram(ram, "vexpress.highmem", ram_size); |