aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--default-configs/arm-softmmu.mak1
-rw-r--r--hw/Makefile.objs1
-rw-r--r--hw/arm/musicpal.c20
-rw-r--r--hw/arm/nseries.c7
-rw-r--r--hw/arm/palm.c7
-rw-r--r--hw/arm/vexpress.c81
-rw-r--r--hw/arm/xilinx_zynq.c24
-rw-r--r--hw/arm_sysctl.c261
-rw-r--r--hw/blizzard.c37
-rw-r--r--hw/cirrus_vga.c22
-rw-r--r--hw/exynos4210_fimd.c17
-rw-r--r--hw/framebuffer.c4
-rw-r--r--hw/framebuffer.h2
-rw-r--r--hw/g364fb.c43
-rw-r--r--hw/jazz_led.c88
-rw-r--r--hw/milkymist-vgafb.c17
-rw-r--r--hw/omap_lcdc.c47
-rw-r--r--hw/pl110.c24
-rw-r--r--hw/pl330.c1654
-rw-r--r--hw/pxa2xx_lcd.c39
-rw-r--r--hw/qdev-core.h3
-rw-r--r--hw/qdev-properties.c104
-rw-r--r--hw/qdev-properties.h39
-rw-r--r--hw/qxl-render.c21
-rw-r--r--hw/qxl.c61
-rw-r--r--hw/sm501.c34
-rw-r--r--hw/ssd0303.c17
-rw-r--r--hw/ssd0323.c19
-rw-r--r--hw/tc6393xb.c28
-rw-r--r--hw/tc6393xb_template.h5
-rw-r--r--hw/tcx.c62
-rw-r--r--hw/vga-isa-mm.c5
-rw-r--r--hw/vga-isa.c4
-rw-r--r--hw/vga-pci.c4
-rw-r--r--hw/vga.c109
-rw-r--r--hw/vga_int.h2
-rw-r--r--hw/vmware_vga.c107
-rw-r--r--hw/xenfb.c57
-rw-r--r--hw/xilinx_spips.c64
-rw-r--r--include/qemu-common.h6
-rw-r--r--include/ui/console.h274
-rw-r--r--include/ui/spice-display.h9
-rw-r--r--target-mips/dsp_helper.c23
-rw-r--r--target-s390x/kvm.c3
-rw-r--r--tests/tcg/mips/mips32-dsp/extr_r_w.c23
-rw-r--r--tests/tcg/mips/mips32-dsp/extr_rs_w.c46
-rw-r--r--tests/tcg/mips/mips32-dsp/extr_w.c23
-rw-r--r--trace-events7
-rw-r--r--ui/cocoa.m57
-rw-r--r--ui/console.c470
-rw-r--r--ui/curses.c28
-rw-r--r--ui/gtk.c160
-rw-r--r--ui/sdl.c118
-rw-r--r--ui/spice-display.c81
-rw-r--r--ui/vnc-enc-tight.c7
-rw-r--r--ui/vnc-jobs.c1
-rw-r--r--ui/vnc.c143
-rw-r--r--ui/vnc.h4
-rw-r--r--util/Makefile.objs1
-rw-r--r--util/hexdump.c37
-rw-r--r--util/iov.c36
-rw-r--r--vl.c6
62 files changed, 3506 insertions, 1198 deletions
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 68b204547c..ab8703578e 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -42,6 +42,7 @@ CONFIG_PL110=y
CONFIG_PL181=y
CONFIG_PL190=y
CONFIG_PL310=y
+CONFIG_PL330=y
CONFIG_CADENCE=y
CONFIG_XGMAC=y
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index eb7eb31a19..11812c6a4e 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -98,6 +98,7 @@ common-obj-$(CONFIG_PL110) += pl110.o
common-obj-$(CONFIG_PL181) += pl181.o
common-obj-$(CONFIG_PL190) += pl190.o
common-obj-$(CONFIG_PL310) += arm_l2x0.o
+common-obj-$(CONFIG_PL330) += pl330.o
common-obj-$(CONFIG_VERSATILE_PCI) += versatile_pci.o
common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
common-obj-$(CONFIG_CADENCE) += cadence_uart.o
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index a37dbd7961..edd528255f 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -462,7 +462,7 @@ typedef struct musicpal_lcd_state {
uint32_t irqctrl;
uint32_t page;
uint32_t page_off;
- DisplayState *ds;
+ QemuConsole *con;
uint8_t video_ram[128*64/8];
} musicpal_lcd_state;
@@ -483,7 +483,8 @@ static inline void glue(set_lcd_pixel, depth) \
(musicpal_lcd_state *s, int x, int y, type col) \
{ \
int dx, dy; \
- type *pixel = &((type *) ds_get_data(s->ds))[(y * 128 * 3 + x) * 3]; \
+ DisplaySurface *surface = qemu_console_surface(s->con); \
+ type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
\
for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
for (dx = 0; dx < 3; dx++, pixel++) \
@@ -496,9 +497,10 @@ SET_LCD_PIXEL(32, uint32_t)
static void lcd_refresh(void *opaque)
{
musicpal_lcd_state *s = opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
int x, y, col;
- switch (ds_get_bits_per_pixel(s->ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 0:
return;
#define LCD_REFRESH(depth, func) \
@@ -518,14 +520,14 @@ static void lcd_refresh(void *opaque)
break;
LCD_REFRESH(8, rgb_to_pixel8)
LCD_REFRESH(16, rgb_to_pixel16)
- LCD_REFRESH(32, (is_surface_bgr(s->ds->surface) ?
+ LCD_REFRESH(32, (is_surface_bgr(surface) ?
rgb_to_pixel32bgr : rgb_to_pixel32))
default:
hw_error("unsupported colour depth %i\n",
- ds_get_bits_per_pixel(s->ds));
+ surface_bits_per_pixel(surface));
}
- dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3);
+ dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
}
static void lcd_invalidate(void *opaque)
@@ -609,9 +611,9 @@ static int musicpal_lcd_init(SysBusDevice *dev)
"musicpal-lcd", MP_LCD_SIZE);
sysbus_init_mmio(dev, &s->iomem);
- s->ds = graphic_console_init(lcd_refresh, lcd_invalidate,
- NULL, NULL, s);
- qemu_console_resize(s->ds, 128*3, 64*3);
+ s->con = graphic_console_init(lcd_refresh, lcd_invalidate,
+ NULL, NULL, s);
+ qemu_console_resize(s->con, 128*3, 64*3);
qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3);
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index c5bf9f95b3..6747c1c547 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -1290,7 +1290,6 @@ static void n8x0_init(QEMUMachineInitArgs *args,
MemoryRegion *sysmem = get_system_memory();
struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
int sdram_size = binfo->ram_size;
- DisplayState *ds;
s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model);
@@ -1370,12 +1369,6 @@ static void n8x0_init(QEMUMachineInitArgs *args,
n800_setup_nolo_tags(nolo_tags);
cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
}
- /* FIXME: We shouldn't really be doing this here. The LCD controller
- will set the size once configured, so this just sets an initial
- size until the guest activates the display. */
- ds = get_displaystate();
- ds->surface = qemu_resize_displaysurface(ds, 800, 480);
- dpy_gfx_resize(ds);
}
static struct arm_boot_info n800_binfo = {
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
index 91bc74af24..baeb585067 100644
--- a/hw/arm/palm.c
+++ b/hw/arm/palm.c
@@ -205,7 +205,6 @@ static void palmte_init(QEMUMachineInitArgs *args)
static uint32_t cs2val = 0x0000e1a0;
static uint32_t cs3val = 0xe1a0e1a0;
int rom_size, rom_loaded = 0;
- DisplayState *ds = get_displaystate();
MemoryRegion *flash = g_new(MemoryRegion, 1);
MemoryRegion *cs = g_new(MemoryRegion, 4);
@@ -268,12 +267,6 @@ static void palmte_init(QEMUMachineInitArgs *args)
palmte_binfo.initrd_filename = initrd_filename;
arm_load_kernel(mpu->cpu, &palmte_binfo);
}
-
- /* FIXME: We shouldn't really be doing this here. The LCD controller
- will set the size once configured, so this just sets an initial
- size until the guest activates the display. */
- ds->surface = qemu_resize_displaysurface(ds, 320, 320);
- dpy_gfx_resize(ds);
}
static QEMUMachine palmte_machine = {
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 02922c38b3..2e1a5d0e5b 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -147,19 +147,24 @@ typedef struct VEDBoardInfo VEDBoardInfo;
typedef void DBoardInitFn(const VEDBoardInfo *daughterboard,
ram_addr_t ram_size,
const char *cpu_model,
- qemu_irq *pic, uint32_t *proc_id);
+ qemu_irq *pic);
struct VEDBoardInfo {
const hwaddr *motherboard_map;
hwaddr loader_start;
const hwaddr gic_cpu_if_addr;
+ uint32_t proc_id;
+ uint32_t num_voltage_sensors;
+ const uint32_t *voltages;
+ uint32_t num_clocks;
+ const uint32_t *clocks;
DBoardInitFn *init;
};
static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
ram_addr_t ram_size,
const char *cpu_model,
- qemu_irq *pic, uint32_t *proc_id)
+ qemu_irq *pic)
{
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
@@ -175,8 +180,6 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
cpu_model = "cortex-a9";
}
- *proc_id = 0x0c000191;
-
for (n = 0; n < smp_cpus; n++) {
ARMCPU *cpu = cpu_arm_init(cpu_model);
if (!cpu) {
@@ -247,17 +250,41 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
sysbus_create_varargs("l2x0", 0x1e00a000, NULL);
}
+/* Voltage values for SYS_CFG_VOLT daughterboard registers;
+ * values are in microvolts.
+ */
+static const uint32_t a9_voltages[] = {
+ 1000000, /* VD10 : 1.0V : SoC internal logic voltage */
+ 1000000, /* VD10_S2 : 1.0V : PL310, L2 cache, RAM, non-PL310 logic */
+ 1000000, /* VD10_S3 : 1.0V : Cortex-A9, cores, MPEs, SCU, PL310 logic */
+ 1800000, /* VCC1V8 : 1.8V : DDR2 SDRAM, test chip DDR2 I/O supply */
+ 900000, /* DDR2VTT : 0.9V : DDR2 SDRAM VTT termination voltage */
+ 3300000, /* VCC3V3 : 3.3V : local board supply for misc external logic */
+};
+
+/* Reset values for daughterboard oscillators (in Hz) */
+static const uint32_t a9_clocks[] = {
+ 45000000, /* AMBA AXI ACLK: 45MHz */
+ 23750000, /* daughterboard CLCD clock: 23.75MHz */
+ 66670000, /* Test chip reference clock: 66.67MHz */
+};
+
static const VEDBoardInfo a9_daughterboard = {
.motherboard_map = motherboard_legacy_map,
.loader_start = 0x60000000,
.gic_cpu_if_addr = 0x1e000100,
+ .proc_id = 0x0c000191,
+ .num_voltage_sensors = ARRAY_SIZE(a9_voltages),
+ .voltages = a9_voltages,
+ .num_clocks = ARRAY_SIZE(a9_clocks),
+ .clocks = a9_clocks,
.init = a9_daughterboard_init,
};
static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
ram_addr_t ram_size,
const char *cpu_model,
- qemu_irq *pic, uint32_t *proc_id)
+ qemu_irq *pic)
{
int n;
MemoryRegion *sysmem = get_system_memory();
@@ -271,8 +298,6 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
cpu_model = "cortex-a15";
}
- *proc_id = 0x14000237;
-
for (n = 0; n < smp_cpus; n++) {
ARMCPU *cpu;
qemu_irq *irqp;
@@ -340,10 +365,31 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
/* 0x7ffd0000: PL354 static memory controller: not modelled */
}
+static const uint32_t a15_voltages[] = {
+ 900000, /* Vcore: 0.9V : CPU core voltage */
+};
+
+static const uint32_t a15_clocks[] = {
+ 60000000, /* OSCCLK0: 60MHz : CPU_CLK reference */
+ 0, /* OSCCLK1: reserved */
+ 0, /* OSCCLK2: reserved */
+ 0, /* OSCCLK3: reserved */
+ 40000000, /* OSCCLK4: 40MHz : external AXI master clock */
+ 23750000, /* OSCCLK5: 23.75MHz : HDLCD PLL reference */
+ 50000000, /* OSCCLK6: 50MHz : static memory controller clock */
+ 60000000, /* OSCCLK7: 60MHz : SYSCLK reference */
+ 40000000, /* OSCCLK8: 40MHz : DDR2 PLL reference */
+};
+
static const VEDBoardInfo a15_daughterboard = {
.motherboard_map = motherboard_aseries_map,
.loader_start = 0x80000000,
.gic_cpu_if_addr = 0x2c002000,
+ .proc_id = 0x14000237,
+ .num_voltage_sensors = ARRAY_SIZE(a15_voltages),
+ .voltages = a15_voltages,
+ .num_clocks = ARRAY_SIZE(a15_clocks),
+ .clocks = a15_clocks,
.init = a15_daughterboard_init,
};
@@ -352,7 +398,6 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
{
DeviceState *dev, *sysctl, *pl041;
qemu_irq pic[64];
- uint32_t proc_id;
uint32_t sys_id;
DriveInfo *dinfo;
ram_addr_t vram_size, sram_size;
@@ -360,9 +405,9 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
MemoryRegion *vram = g_new(MemoryRegion, 1);
MemoryRegion *sram = g_new(MemoryRegion, 1);
const hwaddr *map = daughterboard->motherboard_map;
+ int i;
- daughterboard->init(daughterboard, args->ram_size, args->cpu_model,
- pic, &proc_id);
+ daughterboard->init(daughterboard, args->ram_size, args->cpu_model, pic);
/* Motherboard peripherals: the wiring is the same but the
* addresses vary between the legacy and A-Series memory maps.
@@ -372,7 +417,21 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
sysctl = qdev_create(NULL, "realview_sysctl");
qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
- qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
+ qdev_prop_set_uint32(sysctl, "proc_id", daughterboard->proc_id);
+ qdev_prop_set_uint32(sysctl, "len-db-voltage",
+ daughterboard->num_voltage_sensors);
+ for (i = 0; i < daughterboard->num_voltage_sensors; i++) {
+ char *propname = g_strdup_printf("db-voltage[%d]", i);
+ qdev_prop_set_uint32(sysctl, propname, daughterboard->voltages[i]);
+ g_free(propname);
+ }
+ qdev_prop_set_uint32(sysctl, "len-db-clock",
+ daughterboard->num_clocks);
+ for (i = 0; i < daughterboard->num_clocks; i++) {
+ char *propname = g_strdup_printf("db-clock[%d]", i);
+ qdev_prop_set_uint32(sysctl, propname, daughterboard->clocks[i]);
+ g_free(propname);
+ }
qdev_init_nofail(sysctl);
sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]);
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index f78c47e43e..6f362865f9 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -35,6 +35,10 @@
#define IRQ_OFFSET 32 /* pic interrupts start from index 32 */
+static const int dma_irqs[8] = {
+ 46, 47, 48, 49, 72, 73, 74, 75
+};
+
static struct arm_boot_info zynq_binfo = {};
static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
@@ -196,6 +200,26 @@ static void zynq_init(QEMUMachineInitArgs *args)
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
+ dev = qdev_create(NULL, "pl330");
+ qdev_prop_set_uint8(dev, "num_chnls", 8);
+ qdev_prop_set_uint8(dev, "num_periph_req", 4);
+ qdev_prop_set_uint8(dev, "num_events", 16);
+
+ qdev_prop_set_uint8(dev, "data_width", 64);
+ qdev_prop_set_uint8(dev, "wr_cap", 8);
+ qdev_prop_set_uint8(dev, "wr_q_dep", 16);
+ qdev_prop_set_uint8(dev, "rd_cap", 8);
+ qdev_prop_set_uint8(dev, "rd_q_dep", 16);
+ qdev_prop_set_uint16(dev, "data_buffer_dep", 256);
+
+ qdev_init_nofail(dev);
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, 0xF8003000);
+ sysbus_connect_irq(busdev, 0, pic[45-IRQ_OFFSET]); /* abort irq line */
+ for (n = 0; n < 8; ++n) { /* event irqs */
+ sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]);
+ }
+
zynq_binfo.ram_size = ram_size;
zynq_binfo.kernel_filename = kernel_filename;
zynq_binfo.kernel_cmdline = kernel_cmdline;
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index a46f8d450e..25fc6eac94 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -9,6 +9,7 @@
#include "hw/hw.h"
#include "qemu/timer.h"
+#include "qemu/bitops.h"
#include "hw/sysbus.h"
#include "hw/primecell.h"
#include "sysemu/sysemu.h"
@@ -34,11 +35,17 @@ typedef struct {
uint32_t sys_cfgctrl;
uint32_t sys_cfgstat;
uint32_t sys_clcd;
+ uint32_t mb_clock[6];
+ uint32_t *db_clock;
+ uint32_t db_num_vsensors;
+ uint32_t *db_voltage;
+ uint32_t db_num_clocks;
+ uint32_t *db_clock_reset;
} arm_sysctl_state;
static const VMStateDescription vmstate_arm_sysctl = {
.name = "realview_sysctl",
- .version_id = 3,
+ .version_id = 4,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32(leds, arm_sysctl_state),
@@ -53,6 +60,9 @@ static const VMStateDescription vmstate_arm_sysctl = {
VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2),
VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2),
VMSTATE_UINT32_V(sys_clcd, arm_sysctl_state, 3),
+ VMSTATE_UINT32_ARRAY_V(mb_clock, arm_sysctl_state, 6, 4),
+ VMSTATE_VARRAY_UINT32(db_clock, arm_sysctl_state, db_num_clocks,
+ 4, vmstate_info_uint32, uint32_t),
VMSTATE_END_OF_LIST()
}
};
@@ -76,6 +86,7 @@ static int board_id(arm_sysctl_state *s)
static void arm_sysctl_reset(DeviceState *d)
{
arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, SYS_BUS_DEVICE(d));
+ int i;
s->leds = 0;
s->lockval = 0;
@@ -83,6 +94,17 @@ static void arm_sysctl_reset(DeviceState *d)
s->cfgdata2 = 0;
s->flags = 0;
s->resetlevel = 0;
+ /* Motherboard oscillators (in Hz) */
+ s->mb_clock[0] = 50000000; /* Static memory clock: 50MHz */
+ s->mb_clock[1] = 23750000; /* motherboard CLCD clock: 23.75MHz */
+ s->mb_clock[2] = 24000000; /* IO FPGA peripheral clock: 24MHz */
+ s->mb_clock[3] = 24000000; /* IO FPGA reserved clock: 24MHz */
+ s->mb_clock[4] = 24000000; /* System bus global clock: 24MHz */
+ s->mb_clock[5] = 24000000; /* IO FPGA reserved clock: 24MHz */
+ /* Daughterboard oscillators: reset from property values */
+ for (i = 0; i < s->db_num_clocks; i++) {
+ s->db_clock[i] = s->db_clock_reset[i];
+ }
if (board_id(s) == BOARD_ID_VEXPRESS) {
/* On VExpress this register will RAZ/WI */
s->sys_clcd = 0;
@@ -191,6 +213,166 @@ static uint64_t arm_sysctl_read(void *opaque, hwaddr offset,
}
}
+/* SYS_CFGCTRL functions */
+#define SYS_CFG_OSC 1
+#define SYS_CFG_VOLT 2
+#define SYS_CFG_AMP 3
+#define SYS_CFG_TEMP 4
+#define SYS_CFG_RESET 5
+#define SYS_CFG_SCC 6
+#define SYS_CFG_MUXFPGA 7
+#define SYS_CFG_SHUTDOWN 8
+#define SYS_CFG_REBOOT 9
+#define SYS_CFG_DVIMODE 11
+#define SYS_CFG_POWER 12
+#define SYS_CFG_ENERGY 13
+
+/* SYS_CFGCTRL site field values */
+#define SYS_CFG_SITE_MB 0
+#define SYS_CFG_SITE_DB1 1
+#define SYS_CFG_SITE_DB2 2
+
+/**
+ * vexpress_cfgctrl_read:
+ * @s: arm_sysctl_state pointer
+ * @dcc, @function, @site, @position, @device: split out values from
+ * SYS_CFGCTRL register
+ * @val: pointer to where to put the read data on success
+ *
+ * Handle a VExpress SYS_CFGCTRL register read. On success, return true and
+ * write the read value to *val. On failure, return false (and val may
+ * or may not be written to).
+ */
+static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc,
+ unsigned int function, unsigned int site,
+ unsigned int position, unsigned int device,
+ uint32_t *val)
+{
+ /* We don't support anything other than DCC 0, board stack position 0
+ * or sites other than motherboard/daughterboard:
+ */
+ if (dcc != 0 || position != 0 ||
+ (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) {
+ goto cfgctrl_unimp;
+ }
+
+ switch (function) {
+ case SYS_CFG_VOLT:
+ if (site == SYS_CFG_SITE_DB1 && device < s->db_num_vsensors) {
+ *val = s->db_voltage[device];
+ return true;
+ }
+ if (site == SYS_CFG_SITE_MB && device == 0) {
+ /* There is only one motherboard voltage sensor:
+ * VIO : 3.3V : bus voltage between mother and daughterboard
+ */
+ *val = 3300000;
+ return true;
+ }
+ break;
+ case SYS_CFG_OSC:
+ if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) {
+ /* motherboard clock */
+ *val = s->mb_clock[device];
+ return true;
+ }
+ if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) {
+ /* daughterboard clock */
+ *val = s->db_clock[device];
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+
+cfgctrl_unimp:
+ qemu_log_mask(LOG_UNIMP,
+ "arm_sysctl: Unimplemented SYS_CFGCTRL read of function "
+ "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n",
+ function, dcc, site, position, device);
+ return false;
+}
+
+/**
+ * vexpress_cfgctrl_write:
+ * @s: arm_sysctl_state pointer
+ * @dcc, @function, @site, @position, @device: split out values from
+ * SYS_CFGCTRL register
+ * @val: data to write
+ *
+ * Handle a VExpress SYS_CFGCTRL register write. On success, return true.
+ * On failure, return false.
+ */
+static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc,
+ unsigned int function, unsigned int site,
+ unsigned int position, unsigned int device,
+ uint32_t val)
+{
+ /* We don't support anything other than DCC 0, board stack position 0
+ * or sites other than motherboard/daughterboard:
+ */
+ if (dcc != 0 || position != 0 ||
+ (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) {
+ goto cfgctrl_unimp;
+ }
+
+ switch (function) {
+ case SYS_CFG_OSC:
+ if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) {
+ /* motherboard clock */
+ s->mb_clock[device] = val;
+ return true;
+ }
+ if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) {
+ /* daughterboard clock */
+ s->db_clock[device] = val;
+ return true;
+ }
+ break;
+ case SYS_CFG_MUXFPGA:
+ if (site == SYS_CFG_SITE_MB && device == 0) {
+ /* Select whether video output comes from motherboard
+ * or daughterboard: log and ignore as QEMU doesn't
+ * support this.
+ */
+ qemu_log_mask(LOG_UNIMP, "arm_sysctl: selection of video output "
+ "not supported, ignoring\n");
+ return true;
+ }
+ break;
+ case SYS_CFG_SHUTDOWN:
+ if (site == SYS_CFG_SITE_MB && device == 0) {
+ qemu_system_shutdown_request();
+ return true;
+ }
+ break;
+ case SYS_CFG_REBOOT:
+ if (site == SYS_CFG_SITE_MB && device == 0) {
+ qemu_system_reset_request();
+ return true;
+ }
+ break;
+ case SYS_CFG_DVIMODE:
+ if (site == SYS_CFG_SITE_MB && device == 0) {
+ /* Selecting DVI mode is meaningless for QEMU: we will
+ * always display the output correctly according to the
+ * pixel height/width programmed into the CLCD controller.
+ */
+ return true;
+ }
+ default:
+ break;
+ }
+
+cfgctrl_unimp:
+ qemu_log_mask(LOG_UNIMP,
+ "arm_sysctl: Unimplemented SYS_CFGCTRL write of function "
+ "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n",
+ function, dcc, site, position, device);
+ return false;
+}
+
static void arm_sysctl_write(void *opaque, hwaddr offset,
uint64_t val, unsigned size)
{
@@ -322,17 +504,33 @@ static void arm_sysctl_write(void *opaque, hwaddr offset,
if (board_id(s) != BOARD_ID_VEXPRESS) {
goto bad_reg;
}
- s->sys_cfgctrl = val & ~(3 << 18);
- s->sys_cfgstat = 1; /* complete */
- switch (s->sys_cfgctrl) {
- case 0xc0800000: /* SYS_CFG_SHUTDOWN to motherboard */
- qemu_system_shutdown_request();
- break;
- case 0xc0900000: /* SYS_CFG_REBOOT to motherboard */
- qemu_system_reset_request();
- break;
- default:
- s->sys_cfgstat |= 2; /* error */
+ /* Undefined bits [19:18] are RAZ/WI, and writing to
+ * the start bit just triggers the action; it always reads
+ * as zero.
+ */
+ s->sys_cfgctrl = val & ~((3 << 18) | (1 << 31));
+ if (val & (1 << 31)) {
+ /* Start bit set -- actually do something */
+ unsigned int dcc = extract32(s->sys_cfgctrl, 26, 4);
+ unsigned int function = extract32(s->sys_cfgctrl, 20, 6);
+ unsigned int site = extract32(s->sys_cfgctrl, 16, 2);
+ unsigned int position = extract32(s->sys_cfgctrl, 12, 4);
+ unsigned int device = extract32(s->sys_cfgctrl, 0, 12);
+ s->sys_cfgstat = 1; /* complete */
+ if (s->sys_cfgctrl & (1 << 30)) {
+ if (!vexpress_cfgctrl_write(s, dcc, function, site, position,
+ device, s->sys_cfgdata)) {
+ s->sys_cfgstat |= 2; /* error */
+ }
+ } else {
+ uint32_t val;
+ if (!vexpress_cfgctrl_read(s, dcc, function, site, position,
+ device, &val)) {
+ s->sys_cfgstat |= 2; /* error */
+ } else {
+ s->sys_cfgdata = val;
+ }
+ }
}
s->sys_cfgctrl &= ~(1 << 31);
return;
@@ -385,29 +583,50 @@ static void arm_sysctl_gpio_set(void *opaque, int line, int level)
}
}
-static int arm_sysctl_init(SysBusDevice *dev)
+static void arm_sysctl_init(Object *obj)
{
- arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
+ DeviceState *dev = DEVICE(obj);
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+ arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sd);
memory_region_init_io(&s->iomem, &arm_sysctl_ops, s, "arm-sysctl", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- qdev_init_gpio_in(&s->busdev.qdev, arm_sysctl_gpio_set, 2);
- qdev_init_gpio_out(&s->busdev.qdev, &s->pl110_mux_ctrl, 1);
- return 0;
+ sysbus_init_mmio(sd, &s->iomem);
+ qdev_init_gpio_in(dev, arm_sysctl_gpio_set, 2);
+ qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1);
+}
+
+static void arm_sysctl_realize(DeviceState *d, Error **errp)
+{
+ arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, SYS_BUS_DEVICE(d));
+ s->db_clock = g_new0(uint32_t, s->db_num_clocks);
+}
+
+static void arm_sysctl_finalize(Object *obj)
+{
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
+ g_free(s->db_voltage);
+ g_free(s->db_clock);
+ g_free(s->db_clock_reset);
}
static Property arm_sysctl_properties[] = {
DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0),
+ /* Daughterboard power supply voltages (as reported via SYS_CFG) */
+ DEFINE_PROP_ARRAY("db-voltage", arm_sysctl_state, db_num_vsensors,
+ db_voltage, qdev_prop_uint32, uint32_t),
+ /* Daughterboard clock reset values (as reported via SYS_CFG) */
+ DEFINE_PROP_ARRAY("db-clock", arm_sysctl_state, db_num_clocks,
+ db_clock_reset, qdev_prop_uint32, uint32_t),
DEFINE_PROP_END_OF_LIST(),
};
static void arm_sysctl_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = arm_sysctl_init;
+ dc->realize = arm_sysctl_realize;
dc->reset = arm_sysctl_reset;
dc->vmsd = &vmstate_arm_sysctl;
dc->props = arm_sysctl_properties;
@@ -417,6 +636,8 @@ static const TypeInfo arm_sysctl_info = {
.name = "realview_sysctl",
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(arm_sysctl_state),
+ .instance_init = arm_sysctl_init,
+ .instance_finalize = arm_sysctl_finalize,
.class_init = arm_sysctl_class_init,
};
diff --git a/hw/blizzard.c b/hw/blizzard.c
index 805f4d5558..020d3de431 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -69,7 +69,7 @@ typedef struct {
uint8_t effect;
uint8_t iformat;
uint8_t source;
- DisplayState *state;
+ QemuConsole *con;
blizzard_fn_t *line_fn_tab[2];
void *fb;
@@ -144,6 +144,7 @@ static inline void blizzard_rgb2yuv(int r, int g, int b,
static void blizzard_window(BlizzardState *s)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
uint8_t *src, *dst;
int bypp[2];
int bypl[3];
@@ -162,7 +163,7 @@ static void blizzard_window(BlizzardState *s)
s->my[1] = s->data.y + s->data.dy;
bypp[0] = s->bpp;
- bypp[1] = (ds_get_bits_per_pixel(s->state) + 7) >> 3;
+ bypp[1] = surface_bytes_per_pixel(surface);
bypl[0] = bypp[0] * s->data.pitch;
bypl[1] = bypp[1] * s->x;
bypl[2] = bypp[0] * s->data.dx;
@@ -883,23 +884,25 @@ void s1d13745_write_block(void *opaque, int dc,
static void blizzard_update_display(void *opaque)
{
BlizzardState *s = (BlizzardState *) opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
int y, bypp, bypl, bwidth;
uint8_t *src, *dst;
if (!s->enable)
return;
- if (s->x != ds_get_width(s->state) || s->y != ds_get_height(s->state)) {
+ if (s->x != surface_width(surface) || s->y != surface_height(surface)) {
s->invalidate = 1;
- qemu_console_resize(s->state, s->x, s->y);
+ qemu_console_resize(s->con, s->x, s->y);
+ surface = qemu_console_surface(s->con);
}
if (s->invalidate) {
s->invalidate = 0;
if (s->blank) {
- bypp = (ds_get_bits_per_pixel(s->state) + 7) >> 3;
- memset(ds_get_data(s->state), 0, bypp * s->x * s->y);
+ bypp = surface_bytes_per_pixel(surface);
+ memset(surface_data(surface), 0, bypp * s->x * s->y);
return;
}
@@ -912,16 +915,16 @@ static void blizzard_update_display(void *opaque)
if (s->mx[1] <= s->mx[0])
return;
- bypp = (ds_get_bits_per_pixel(s->state) + 7) >> 3;
+ bypp = surface_bytes_per_pixel(surface);
bypl = bypp * s->x;
bwidth = bypp * (s->mx[1] - s->mx[0]);
y = s->my[0];
src = s->fb + bypl * y + bypp * s->mx[0];
- dst = ds_get_data(s->state) + bypl * y + bypp * s->mx[0];
+ dst = surface_data(surface) + bypl * y + bypp * s->mx[0];
for (; y < s->my[1]; y ++, src += bypl, dst += bypl)
memcpy(dst, src, bwidth);
- dpy_gfx_update(s->state, s->mx[0], s->my[0],
+ dpy_gfx_update(s->con, s->mx[0], s->my[0],
s->mx[1] - s->mx[0], y - s->my[0]);
s->mx[0] = s->x;
@@ -934,10 +937,12 @@ static void blizzard_screen_dump(void *opaque, const char *filename,
bool cswitch, Error **errp)
{
BlizzardState *s = (BlizzardState *) opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
blizzard_update_display(opaque);
- if (s && ds_get_data(s->state))
- ppm_save(filename, s->state->surface, errp);
+ if (s && surface_data(surface)) {
+ ppm_save(filename, surface, errp);
+ }
}
#define DEPTH 8
@@ -954,14 +959,16 @@ static void blizzard_screen_dump(void *opaque, const char *filename,
void *s1d13745_init(qemu_irq gpio_int)
{
BlizzardState *s = (BlizzardState *) g_malloc0(sizeof(*s));
+ DisplaySurface *surface;
s->fb = g_malloc(0x180000);
- s->state = graphic_console_init(blizzard_update_display,
- blizzard_invalidate_display,
- blizzard_screen_dump, NULL, s);
+ s->con = graphic_console_init(blizzard_update_display,
+ blizzard_invalidate_display,
+ blizzard_screen_dump, NULL, s);
+ surface = qemu_console_surface(s->con);
- switch (ds_get_bits_per_pixel(s->state)) {
+ switch (surface_bits_per_pixel(surface)) {
case 0:
s->line_fn_tab[0] = s->line_fn_tab[1] =
g_malloc0(sizeof(blizzard_fn_t) * 0x10);
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 7babcb67c8..7a4d63436e 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -729,11 +729,12 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
s->cirrus_blt_width, s->cirrus_blt_height);
- if (notify)
- qemu_console_copy(s->vga.ds,
+ if (notify) {
+ qemu_console_copy(s->vga.con,
sx, sy, dx, dy,
s->cirrus_blt_width / depth,
s->cirrus_blt_height);
+ }
/* we don't have to notify the display that this portion has
changed since qemu_console_copy implies this */
@@ -2176,6 +2177,7 @@ static void cirrus_cursor_invalidate(VGACommonState *s1)
static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
{
CirrusVGAState *s = container_of(s1, CirrusVGAState, vga);
+ DisplaySurface *surface = qemu_console_surface(s->vga.con);
int w, h, bpp, x1, x2, poffset;
unsigned int color0, color1;
const uint8_t *palette, *src;
@@ -2228,9 +2230,9 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
color1 = s->vga.rgb_to_pixel(c6_to_8(palette[0xf * 3]),
c6_to_8(palette[0xf * 3 + 1]),
c6_to_8(palette[0xf * 3 + 2]));
- bpp = ((ds_get_bits_per_pixel(s->vga.ds) + 7) >> 3);
+ bpp = surface_bytes_per_pixel(surface);
d1 += x1 * bpp;
- switch(ds_get_bits_per_pixel(s->vga.ds)) {
+ switch (surface_bits_per_pixel(surface)) {
default:
break;
case 8:
@@ -2908,9 +2910,9 @@ static int vga_initfn(ISADevice *dev)
vga_common_init(s);
cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0,
isa_address_space(dev), isa_address_space_io(dev));
- s->ds = graphic_console_init(s->update, s->invalidate,
- s->screen_dump, s->text_update,
- s);
+ s->con = graphic_console_init(s->update, s->invalidate,
+ s->screen_dump, s->text_update,
+ s);
rom_add_vga(VGABIOS_CIRRUS_FILENAME);
/* XXX ISA-LFB support */
/* FIXME not qdev yet */
@@ -2957,9 +2959,9 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
vga_common_init(&s->vga);
cirrus_init_common(s, device_id, 1, pci_address_space(dev),
pci_address_space_io(dev));
- s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
- s->vga.screen_dump, s->vga.text_update,
- &s->vga);
+ s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate,
+ s->vga.screen_dump, s->vga.text_update,
+ &s->vga);
/* setup PCI */
diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c
index 6b31ae33b6..bf316c62ab 100644
--- a/hw/exynos4210_fimd.c
+++ b/hw/exynos4210_fimd.c
@@ -296,7 +296,7 @@ struct Exynos4210fimdWindow {
typedef struct {
SysBusDevice busdev;
MemoryRegion iomem;
- DisplayState *console;
+ QemuConsole *console;
qemu_irq irq[3];
uint32_t vidcon[4]; /* Video main control registers 0-3 */
@@ -1221,16 +1221,18 @@ static void exynos4210_fimd_invalidate(void *opaque)
static void exynos4210_update_resolution(Exynos4210fimdState *s)
{
+ DisplaySurface *surface = qemu_console_surface(s->console);
+
/* LCD resolution is stored in VIDEO TIME CONTROL REGISTER 2 */
uint32_t width = ((s->vidtcon[2] >> FIMD_VIDTCON2_HOR_SHIFT) &
FIMD_VIDTCON2_SIZE_MASK) + 1;
uint32_t height = ((s->vidtcon[2] >> FIMD_VIDTCON2_VER_SHIFT) &
FIMD_VIDTCON2_SIZE_MASK) + 1;
- if (s->ifb == NULL || ds_get_width(s->console) != width ||
- ds_get_height(s->console) != height) {
+ if (s->ifb == NULL || surface_width(surface) != width ||
+ surface_height(surface) != height) {
DPRINT_L1("Resolution changed from %ux%u to %ux%u\n",
- ds_get_width(s->console), ds_get_height(s->console), width, height);
+ surface_width(surface), surface_height(surface), width, height);
qemu_console_resize(s->console, width, height);
s->ifb = g_realloc(s->ifb, width * height * RGBA_SIZE + 1);
memset(s->ifb, 0, width * height * RGBA_SIZE + 1);
@@ -1241,6 +1243,7 @@ static void exynos4210_update_resolution(Exynos4210fimdState *s)
static void exynos4210_fimd_update(void *opaque)
{
Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;
+ DisplaySurface *surface = qemu_console_surface(s->console);
Exynos4210fimdWindow *w;
int i, line;
hwaddr fb_line_addr, inc_size;
@@ -1253,7 +1256,7 @@ static void exynos4210_fimd_update(void *opaque)
const int global_height = ((s->vidtcon[2] >> FIMD_VIDTCON2_VER_SHIFT) &
FIMD_VIDTCON2_SIZE_MASK) + 1;
- if (!s || !s->console || !ds_get_bits_per_pixel(s->console) ||
+ if (!s || !s->console || !surface_bits_per_pixel(surface) ||
!s->enabled) {
return;
}
@@ -1299,10 +1302,10 @@ static void exynos4210_fimd_update(void *opaque)
uint8_t *d;
int bpp;
- bpp = ds_get_bits_per_pixel(s->console);
+ bpp = surface_bits_per_pixel(surface);
fimd_update_putpix_qemu(bpp);
bpp = (bpp + 1) >> 3;
- d = ds_get_data(s->console);
+ d = surface_data(surface);
for (line = first_line; line <= last_line; line++) {
fimd_copy_line_toqemu(global_width, s->ifb + global_width * line *
RGBA_SIZE, d + global_width * line * bpp);
diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index d341aa0c6b..7326a98a41 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -24,7 +24,7 @@
/* Render an image from a shared memory framebuffer. */
void framebuffer_update_display(
- DisplayState *ds,
+ DisplaySurface *ds,
MemoryRegion *address_space,
hwaddr base,
int cols, /* Width in pixels. */
@@ -73,7 +73,7 @@ void framebuffer_update_display(
return;
}
src = src_base;
- dest = ds_get_data(ds);
+ dest = surface_data(ds);
if (dest_col_pitch < 0)
dest -= dest_col_pitch * (cols - 1);
if (dest_row_pitch < 0) {
diff --git a/hw/framebuffer.h b/hw/framebuffer.h
index 11f53edec0..6eae035b7d 100644
--- a/hw/framebuffer.h
+++ b/hw/framebuffer.h
@@ -8,7 +8,7 @@
typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int);
void framebuffer_update_display(
- DisplayState *ds,
+ DisplaySurface *ds,
MemoryRegion *address_space,
hwaddr base,
int cols,
diff --git a/hw/g364fb.c b/hw/g364fb.c
index 7b69815bc9..f7014e9dd8 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -39,7 +39,7 @@ typedef struct G364State {
uint32_t top_of_screen;
uint32_t width, height; /* in pixels */
/* display refresh support */
- DisplayState *ds;
+ QemuConsole *con;
int depth;
int blanked;
} G364State;
@@ -77,6 +77,7 @@ static inline void reset_dirty(G364State *s,
static void g364fb_draw_graphic8(G364State *s)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int i, w;
uint8_t *vram;
uint8_t *data_display, *dd;
@@ -87,7 +88,7 @@ static void g364fb_draw_graphic8(G364State *s)
int xcursor, ycursor;
unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned int b);
- switch (ds_get_bits_per_pixel(s->ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 8:
rgb_to_pixel = rgb_to_pixel8;
w = 1;
@@ -106,7 +107,7 @@ static void g364fb_draw_graphic8(G364State *s)
break;
default:
hw_error("g364: unknown host depth %d",
- ds_get_bits_per_pixel(s->ds));
+ surface_bits_per_pixel(surface));
return;
}
@@ -129,7 +130,7 @@ static void g364fb_draw_graphic8(G364State *s)
vram = s->vram + s->top_of_screen;
/* XXX: out of range in vram? */
- data_display = dd = ds_get_data(s->ds);
+ data_display = dd = surface_data(surface);
while (y < s->height) {
if (check_dirty(s, page)) {
if (y < ymin)
@@ -182,7 +183,7 @@ static void g364fb_draw_graphic8(G364State *s)
ymax = s->height - 1;
goto done;
}
- data_display = dd = data_display + ds_get_linesize(s->ds);
+ data_display = dd = data_display + surface_stride(surface);
xmin = 0;
x = 0;
}
@@ -197,7 +198,7 @@ static void g364fb_draw_graphic8(G364State *s)
reset_dirty(s, page_min, page_max);
page_min = (ram_addr_t)-1;
page_max = 0;
- dpy_gfx_update(s->ds, xmin, ymin,
+ dpy_gfx_update(s->con, xmin, ymin,
xmax - xmin + 1, ymax - ymin + 1);
xmin = s->width;
xmax = 0;
@@ -209,7 +210,7 @@ static void g364fb_draw_graphic8(G364State *s)
x = x % s->width;
y += dy;
vram += G364_PAGE_SIZE;
- data_display += dy * ds_get_linesize(s->ds);
+ data_display += dy * surface_stride(surface);
dd = data_display + x * w;
}
page += G364_PAGE_SIZE;
@@ -217,13 +218,14 @@ static void g364fb_draw_graphic8(G364State *s)
done:
if (page_min != (ram_addr_t)-1) {
- dpy_gfx_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
+ dpy_gfx_update(s->con, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
reset_dirty(s, page_min, page_max);
}
}
static void g364fb_draw_blank(G364State *s)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int i, w;
uint8_t *d;
@@ -232,28 +234,30 @@ static void g364fb_draw_blank(G364State *s)
return;
}
- w = s->width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
- d = ds_get_data(s->ds);
+ w = s->width * surface_bytes_per_pixel(surface);
+ d = surface_data(surface);
for (i = 0; i < s->height; i++) {
memset(d, 0, w);
- d += ds_get_linesize(s->ds);
+ d += surface_stride(surface);
}
- dpy_gfx_update(s->ds, 0, 0, s->width, s->height);
+ dpy_gfx_update(s->con, 0, 0, s->width, s->height);
s->blanked = 1;
}
static void g364fb_update_display(void *opaque)
{
G364State *s = opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
qemu_flush_coalesced_mmio_buffer();
if (s->width == 0 || s->height == 0)
return;
- if (s->width != ds_get_width(s->ds) || s->height != ds_get_height(s->ds)) {
- qemu_console_resize(s->ds, s->width, s->height);
+ if (s->width != surface_width(surface) ||
+ s->height != surface_height(surface)) {
+ qemu_console_resize(s->con, s->width, s->height);
}
if (s->ctla & CTLA_FORCE_BLANK) {
@@ -413,13 +417,14 @@ static void g364fb_update_depth(G364State *s)
static void g364_invalidate_cursor_position(G364State *s)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int ymin, ymax, start, end;
/* invalidate only near the cursor */
ymin = s->cursor_position & 0xfff;
ymax = MIN(s->height, ymin + 64);
- start = ymin * ds_get_linesize(s->ds);
- end = (ymax + 1) * ds_get_linesize(s->ds);
+ start = ymin * surface_stride(surface);
+ end = (ymax + 1) * surface_stride(surface);
memory_region_set_dirty(&s->mem_vram, start, end - start);
}
@@ -545,9 +550,9 @@ static void g364fb_init(DeviceState *dev, G364State *s)
{
s->vram = g_malloc0(s->vram_size);
- s->ds = graphic_console_init(g364fb_update_display,
- g364fb_invalidate_display,
- g364fb_screen_dump, NULL, s);
+ s->con = graphic_console_init(g364fb_update_display,
+ g364fb_invalidate_display,
+ g364fb_screen_dump, NULL, s);
memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000);
memory_region_init_ram_ptr(&s->mem_vram, "vram",
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index a418a7d1b6..05528c7c81 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -36,7 +36,7 @@ typedef struct LedState {
SysBusDevice busdev;
MemoryRegion iomem;
uint8_t segments;
- DisplayState *ds;
+ QemuConsole *con;
screen_state_t state;
} LedState;
@@ -75,13 +75,15 @@ static const MemoryRegionOps led_ops = {
/***********************************************************/
/* jazz_led display */
-static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx2, uint32_t color)
+static void draw_horizontal_line(DisplaySurface *ds,
+ int posy, int posx1, int posx2,
+ uint32_t color)
{
uint8_t *d;
int x, bpp;
- bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
- d = ds_get_data(ds) + ds_get_linesize(ds) * posy + bpp * posx1;
+ bpp = (surface_bits_per_pixel(ds) + 7) >> 3;
+ d = surface_data(ds) + surface_stride(ds) * posy + bpp * posx1;
switch(bpp) {
case 1:
for (x = posx1; x <= posx2; x++) {
@@ -104,30 +106,32 @@ static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx
}
}
-static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2, uint32_t color)
+static void draw_vertical_line(DisplaySurface *ds,
+ int posx, int posy1, int posy2,
+ uint32_t color)
{
uint8_t *d;
int y, bpp;
- bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
- d = ds_get_data(ds) + ds_get_linesize(ds) * posy1 + bpp * posx;
+ bpp = (surface_bits_per_pixel(ds) + 7) >> 3;
+ d = surface_data(ds) + surface_stride(ds) * posy1 + bpp * posx;
switch(bpp) {
case 1:
for (y = posy1; y <= posy2; y++) {
*((uint8_t *)d) = color;
- d += ds_get_linesize(ds);
+ d += surface_stride(ds);
}
break;
case 2:
for (y = posy1; y <= posy2; y++) {
*((uint16_t *)d) = color;
- d += ds_get_linesize(ds);
+ d += surface_stride(ds);
}
break;
case 4:
for (y = posy1; y <= posy2; y++) {
*((uint32_t *)d) = color;
- d += ds_get_linesize(ds);
+ d += surface_stride(ds);
}
break;
}
@@ -136,24 +140,24 @@ static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2,
static void jazz_led_update_display(void *opaque)
{
LedState *s = opaque;
- DisplayState *ds = s->ds;
+ DisplaySurface *surface = qemu_console_surface(s->con);
uint8_t *d1;
uint32_t color_segment, color_led;
int y, bpp;
if (s->state & REDRAW_BACKGROUND) {
/* clear screen */
- bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
- d1 = ds_get_data(ds);
- for (y = 0; y < ds_get_height(ds); y++) {
- memset(d1, 0x00, ds_get_width(ds) * bpp);
- d1 += ds_get_linesize(ds);
+ bpp = (surface_bits_per_pixel(surface) + 7) >> 3;
+ d1 = surface_data(surface);
+ for (y = 0; y < surface_height(surface); y++) {
+ memset(d1, 0x00, surface_width(surface) * bpp);
+ d1 += surface_stride(surface);
}
}
if (s->state & REDRAW_SEGMENTS) {
/* set colors according to bpp */
- switch (ds_get_bits_per_pixel(ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 8:
color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa);
color_led = rgb_to_pixel8(0x00, 0xff, 0x00);
@@ -178,26 +182,34 @@ static void jazz_led_update_display(void *opaque)
}
/* display segments */
- draw_horizontal_line(ds, 40, 10, 40, (s->segments & 0x02) ? color_segment : 0);
- draw_vertical_line(ds, 10, 10, 40, (s->segments & 0x04) ? color_segment : 0);
- draw_vertical_line(ds, 10, 40, 70, (s->segments & 0x08) ? color_segment : 0);
- draw_horizontal_line(ds, 70, 10, 40, (s->segments & 0x10) ? color_segment : 0);
- draw_vertical_line(ds, 40, 40, 70, (s->segments & 0x20) ? color_segment : 0);
- draw_vertical_line(ds, 40, 10, 40, (s->segments & 0x40) ? color_segment : 0);
- draw_horizontal_line(ds, 10, 10, 40, (s->segments & 0x80) ? color_segment : 0);
+ draw_horizontal_line(surface, 40, 10, 40,
+ (s->segments & 0x02) ? color_segment : 0);
+ draw_vertical_line(surface, 10, 10, 40,
+ (s->segments & 0x04) ? color_segment : 0);
+ draw_vertical_line(surface, 10, 40, 70,
+ (s->segments & 0x08) ? color_segment : 0);
+ draw_horizontal_line(surface, 70, 10, 40,
+ (s->segments & 0x10) ? color_segment : 0);
+ draw_vertical_line(surface, 40, 40, 70,
+ (s->segments & 0x20) ? color_segment : 0);
+ draw_vertical_line(surface, 40, 10, 40,
+ (s->segments & 0x40) ? color_segment : 0);
+ draw_horizontal_line(surface, 10, 10, 40,
+ (s->segments & 0x80) ? color_segment : 0);
/* display led */
if (!(s->segments & 0x01))
color_led = 0; /* black */
- draw_horizontal_line(ds, 68, 50, 50, color_led);
- draw_horizontal_line(ds, 69, 49, 51, color_led);
- draw_horizontal_line(ds, 70, 48, 52, color_led);
- draw_horizontal_line(ds, 71, 49, 51, color_led);
- draw_horizontal_line(ds, 72, 50, 50, color_led);
+ draw_horizontal_line(surface, 68, 50, 50, color_led);
+ draw_horizontal_line(surface, 69, 49, 51, color_led);
+ draw_horizontal_line(surface, 70, 48, 52, color_led);
+ draw_horizontal_line(surface, 71, 49, 51, color_led);
+ draw_horizontal_line(surface, 72, 50, 50, color_led);
}
s->state = REDRAW_NONE;
- dpy_gfx_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
+ dpy_gfx_update(s->con, 0, 0,
+ surface_width(surface), surface_height(surface));
}
static void jazz_led_invalidate_display(void *opaque)
@@ -211,15 +223,15 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
LedState *s = opaque;
char buf[2];
- dpy_text_cursor(s->ds, -1, -1);
- qemu_console_resize(s->ds, 2, 1);
+ dpy_text_cursor(s->con, -1, -1);
+ qemu_console_resize(s->con, 2, 1);
/* TODO: draw the segments */
snprintf(buf, 2, "%02hhx\n", s->segments);
console_write_ch(chardata++, 0x00200100 | buf[0]);
console_write_ch(chardata++, 0x00200100 | buf[1]);
- dpy_text_update(s->ds, 0, 0, 2, 1);
+ dpy_text_update(s->con, 0, 0, 2, 1);
}
static int jazz_led_post_load(void *opaque, int version_id)
@@ -249,10 +261,10 @@ static int jazz_led_init(SysBusDevice *dev)
memory_region_init_io(&s->iomem, &led_ops, s, "led", 1);
sysbus_init_mmio(dev, &s->iomem);
- s->ds = graphic_console_init(jazz_led_update_display,
- jazz_led_invalidate_display,
- NULL,
- jazz_led_text_update, s);
+ s->con = graphic_console_init(jazz_led_update_display,
+ jazz_led_invalidate_display,
+ NULL,
+ jazz_led_text_update, s);
return 0;
}
@@ -263,7 +275,7 @@ static void jazz_led_reset(DeviceState *d)
s->segments = 0;
s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
- qemu_console_resize(s->ds, 60, 80);
+ qemu_console_resize(s->con, 60, 80);
}
static void jazz_led_class_init(ObjectClass *klass, void *data)
diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 85ebb851bd..98762ecd21 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -66,7 +66,7 @@ enum {
struct MilkymistVgafbState {
SysBusDevice busdev;
MemoryRegion regs_region;
- DisplayState *ds;
+ QemuConsole *con;
int invalidate;
uint32_t fb_offset;
@@ -84,6 +84,7 @@ static int vgafb_enabled(MilkymistVgafbState *s)
static void vgafb_update_display(void *opaque)
{
MilkymistVgafbState *s = opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
int first = 0;
int last = 0;
drawfn fn;
@@ -94,7 +95,7 @@ static void vgafb_update_display(void *opaque)
int dest_width = s->regs[R_HRES];
- switch (ds_get_bits_per_pixel(s->ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 0:
return;
case 8:
@@ -121,7 +122,7 @@ static void vgafb_update_display(void *opaque)
break;
}
- framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev),
+ framebuffer_update_display(surface, sysbus_address_space(&s->busdev),
s->regs[R_BASEADDRESS] + s->fb_offset,
s->regs[R_HRES],
s->regs[R_VRES],
@@ -134,7 +135,7 @@ static void vgafb_update_display(void *opaque)
&first, &last);
if (first >= 0) {
- dpy_gfx_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
+ dpy_gfx_update(s->con, 0, first, s->regs[R_HRES], last - first + 1);
}
s->invalidate = 0;
}
@@ -151,7 +152,7 @@ static void vgafb_resize(MilkymistVgafbState *s)
return;
}
- qemu_console_resize(s->ds, s->regs[R_HRES], s->regs[R_VRES]);
+ qemu_console_resize(s->con, s->regs[R_HRES], s->regs[R_VRES]);
s->invalidate = 1;
}
@@ -277,9 +278,9 @@ static int milkymist_vgafb_init(SysBusDevice *dev)
"milkymist-vgafb", R_MAX * 4);
sysbus_init_mmio(dev, &s->regs_region);
- s->ds = graphic_console_init(vgafb_update_display,
- vgafb_invalidate_display,
- NULL, NULL, s);
+ s->con = graphic_console_init(vgafb_update_display,
+ vgafb_invalidate_display,
+ NULL, NULL, s);
return 0;
}
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index c426f3a13a..4f5b0947cf 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -26,7 +26,7 @@ struct omap_lcd_panel_s {
MemoryRegion *sysmem;
MemoryRegion iomem;
qemu_irq irq;
- DisplayState *state;
+ QemuConsole *con;
int plm;
int tft;
@@ -113,14 +113,16 @@ static draw_line_func draw_line_table2[33] = {
static void omap_update_display(void *opaque)
{
struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
+ DisplaySurface *surface = qemu_console_surface(omap_lcd->con);
draw_line_func draw_line;
int size, height, first, last;
int width, linesize, step, bpp, frame_offset;
hwaddr frame_base;
- if (!omap_lcd || omap_lcd->plm == 1 ||
- !omap_lcd->enable || !ds_get_bits_per_pixel(omap_lcd->state))
+ if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable ||
+ !surface_bits_per_pixel(surface)) {
return;
+ }
frame_offset = 0;
if (omap_lcd->plm != 2) {
@@ -139,25 +141,25 @@ static void omap_update_display(void *opaque)
/* Colour depth */
switch ((omap_lcd->palette[0] >> 12) & 7) {
case 1:
- draw_line = draw_line_table2[ds_get_bits_per_pixel(omap_lcd->state)];
+ draw_line = draw_line_table2[surface_bits_per_pixel(surface)];
bpp = 2;
break;
case 2:
- draw_line = draw_line_table4[ds_get_bits_per_pixel(omap_lcd->state)];
+ draw_line = draw_line_table4[surface_bits_per_pixel(surface)];
bpp = 4;
break;
case 3:
- draw_line = draw_line_table8[ds_get_bits_per_pixel(omap_lcd->state)];
+ draw_line = draw_line_table8[surface_bits_per_pixel(surface)];
bpp = 8;
break;
case 4 ... 7:
if (!omap_lcd->tft)
- draw_line = draw_line_table12[ds_get_bits_per_pixel(omap_lcd->state)];
+ draw_line = draw_line_table12[surface_bits_per_pixel(surface)];
else
- draw_line = draw_line_table16[ds_get_bits_per_pixel(omap_lcd->state)];
+ draw_line = draw_line_table16[surface_bits_per_pixel(surface)];
bpp = 16;
break;
@@ -168,10 +170,11 @@ static void omap_update_display(void *opaque)
/* Resolution */
width = omap_lcd->width;
- if (width != ds_get_width(omap_lcd->state) ||
- omap_lcd->height != ds_get_height(omap_lcd->state)) {
- qemu_console_resize(omap_lcd->state,
+ if (width != surface_width(surface) ||
+ omap_lcd->height != surface_height(surface)) {
+ qemu_console_resize(omap_lcd->con,
omap_lcd->width, omap_lcd->height);
+ surface = qemu_console_surface(omap_lcd->con);
omap_lcd->invalidate = 1;
}
@@ -196,8 +199,9 @@ static void omap_update_display(void *opaque)
if (omap_lcd->dma->dual)
omap_lcd->dma->current_frame ^= 1;
- if (!ds_get_bits_per_pixel(omap_lcd->state))
+ if (!surface_bits_per_pixel(surface)) {
return;
+ }
first = 0;
height = omap_lcd->height;
@@ -210,15 +214,15 @@ static void omap_update_display(void *opaque)
}
step = width * bpp >> 3;
- linesize = ds_get_linesize(omap_lcd->state);
- framebuffer_update_display(omap_lcd->state, omap_lcd->sysmem,
+ linesize = surface_stride(surface);
+ framebuffer_update_display(surface, omap_lcd->sysmem,
frame_base, width, height,
step, linesize, 0,
omap_lcd->invalidate,
draw_line, omap_lcd->palette,
&first, &last);
if (first >= 0) {
- dpy_gfx_update(omap_lcd->state, 0, first, width, last - first + 1);
+ dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1);
}
omap_lcd->invalidate = 0;
}
@@ -298,12 +302,13 @@ static void omap_screen_dump(void *opaque, const char *filename, bool cswitch,
Error **errp)
{
struct omap_lcd_panel_s *omap_lcd = opaque;
+ DisplaySurface *surface = qemu_console_surface(omap_lcd->con);
omap_update_display(opaque);
- if (omap_lcd && ds_get_data(omap_lcd->state))
- omap_ppm_save(filename, ds_get_data(omap_lcd->state),
+ if (omap_lcd && surface_data(surface))
+ omap_ppm_save(filename, surface_data(surface),
omap_lcd->width, omap_lcd->height,
- ds_get_linesize(omap_lcd->state), errp);
+ surface_stride(surface), errp);
}
static void omap_invalidate_display(void *opaque) {
@@ -480,9 +485,9 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
memory_region_init_io(&s->iomem, &omap_lcdc_ops, s, "omap.lcdc", 0x100);
memory_region_add_subregion(sysmem, base, &s->iomem);
- s->state = graphic_console_init(omap_update_display,
- omap_invalidate_display,
- omap_screen_dump, NULL, s);
+ s->con = graphic_console_init(omap_update_display,
+ omap_invalidate_display,
+ omap_screen_dump, NULL, s);
return s;
}
diff --git a/hw/pl110.c b/hw/pl110.c
index 924642d697..fbef675f9c 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -42,7 +42,7 @@ enum pl110_version
typedef struct {
SysBusDevice busdev;
MemoryRegion iomem;
- DisplayState *ds;
+ QemuConsole *con;
int version;
uint32_t timing[4];
@@ -129,6 +129,7 @@ static int pl110_enabled(pl110_state *s)
static void pl110_update_display(void *opaque)
{
pl110_state *s = (pl110_state *)opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
drawfn* fntable;
drawfn fn;
int dest_width;
@@ -140,7 +141,7 @@ static void pl110_update_display(void *opaque)
if (!pl110_enabled(s))
return;
- switch (ds_get_bits_per_pixel(s->ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 0:
return;
case 8:
@@ -231,14 +232,14 @@ static void pl110_update_display(void *opaque)
}
dest_width *= s->cols;
first = 0;
- framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev),
+ framebuffer_update_display(surface, sysbus_address_space(&s->busdev),
s->upbase, s->cols, s->rows,
src_width, dest_width, 0,
s->invalidate,
fn, s->palette,
&first, &last);
if (first >= 0) {
- dpy_gfx_update(s->ds, 0, first, s->cols, last - first + 1);
+ dpy_gfx_update(s->con, 0, first, s->cols, last - first + 1);
}
s->invalidate = 0;
}
@@ -248,12 +249,13 @@ static void pl110_invalidate_display(void * opaque)
pl110_state *s = (pl110_state *)opaque;
s->invalidate = 1;
if (pl110_enabled(s)) {
- qemu_console_resize(s->ds, s->cols, s->rows);
+ qemu_console_resize(s->con, s->cols, s->rows);
}
}
static void pl110_update_palette(pl110_state *s, int n)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int i;
uint32_t raw;
unsigned int r, g, b;
@@ -268,7 +270,7 @@ static void pl110_update_palette(pl110_state *s, int n)
b = (raw & 0x1f) << 3;
/* The I bit is ignored. */
raw >>= 6;
- switch (ds_get_bits_per_pixel(s->ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 8:
s->palette[n] = rgb_to_pixel8(r, g, b);
break;
@@ -291,7 +293,7 @@ static void pl110_resize(pl110_state *s, int width, int height)
{
if (width != s->cols || height != s->rows) {
if (pl110_enabled(s)) {
- qemu_console_resize(s->ds, width, height);
+ qemu_console_resize(s->con, width, height);
}
}
s->cols = width;
@@ -409,7 +411,7 @@ static void pl110_write(void *opaque, hwaddr offset,
s->cr = val;
s->bpp = (val >> 1) & 7;
if (pl110_enabled(s)) {
- qemu_console_resize(s->ds, s->cols, s->rows);
+ qemu_console_resize(s->con, s->cols, s->rows);
}
break;
case 10: /* LCDICR */
@@ -450,9 +452,9 @@ static int pl110_init(SysBusDevice *dev)
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1);
- s->ds = graphic_console_init(pl110_update_display,
- pl110_invalidate_display,
- NULL, NULL, s);
+ s->con = graphic_console_init(pl110_update_display,
+ pl110_invalidate_display,
+ NULL, NULL, s);
return 0;
}
diff --git a/hw/pl330.c b/hw/pl330.c
new file mode 100644
index 0000000000..1a04773a71
--- /dev/null
+++ b/hw/pl330.c
@@ -0,0 +1,1654 @@
+/*
+ * ARM PrimeCell PL330 DMA Controller
+ *
+ * Copyright (c) 2009 Samsung Electronics.
+ * Contributed by Kirill Batuzov <batuzovk@ispras.ru>
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
+ *
+ * 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; version 2 or later.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysbus.h"
+#include "qemu/timer.h"
+#include "sysemu/dma.h"
+
+#ifndef PL330_ERR_DEBUG
+#define PL330_ERR_DEBUG 0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do {\
+ if (PL330_ERR_DEBUG >= lvl) {\
+ fprintf(stderr, "PL330: %s:" fmt, __func__, ## args);\
+ } \
+} while (0);
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+#define PL330_PERIPH_NUM 32
+#define PL330_MAX_BURST_LEN 128
+#define PL330_INSN_MAXSIZE 6
+
+#define PL330_FIFO_OK 0
+#define PL330_FIFO_STALL 1
+#define PL330_FIFO_ERR (-1)
+
+#define PL330_FAULT_UNDEF_INSTR (1 << 0)
+#define PL330_FAULT_OPERAND_INVALID (1 << 1)
+#define PL330_FAULT_DMAGO_ERR (1 << 4)
+#define PL330_FAULT_EVENT_ERR (1 << 5)
+#define PL330_FAULT_CH_PERIPH_ERR (1 << 6)
+#define PL330_FAULT_CH_RDWR_ERR (1 << 7)
+#define PL330_FAULT_ST_DATA_UNAVAILABLE (1 << 12)
+#define PL330_FAULT_FIFOEMPTY_ERR (1 << 13)
+#define PL330_FAULT_INSTR_FETCH_ERR (1 << 16)
+#define PL330_FAULT_DATA_WRITE_ERR (1 << 17)
+#define PL330_FAULT_DATA_READ_ERR (1 << 18)
+#define PL330_FAULT_DBG_INSTR (1 << 30)
+#define PL330_FAULT_LOCKUP_ERR (1 << 31)
+
+#define PL330_UNTAGGED 0xff
+
+#define PL330_SINGLE 0x0
+#define PL330_BURST 0x1
+
+#define PL330_WATCHDOG_LIMIT 1024
+
+/* IOMEM mapped registers */
+#define PL330_REG_DSR 0x000
+#define PL330_REG_DPC 0x004
+#define PL330_REG_INTEN 0x020
+#define PL330_REG_INT_EVENT_RIS 0x024
+#define PL330_REG_INTMIS 0x028
+#define PL330_REG_INTCLR 0x02C
+#define PL330_REG_FSRD 0x030
+#define PL330_REG_FSRC 0x034
+#define PL330_REG_FTRD 0x038
+#define PL330_REG_FTR_BASE 0x040
+#define PL330_REG_CSR_BASE 0x100
+#define PL330_REG_CPC_BASE 0x104
+#define PL330_REG_CHANCTRL 0x400
+#define PL330_REG_DBGSTATUS 0xD00
+#define PL330_REG_DBGCMD 0xD04
+#define PL330_REG_DBGINST0 0xD08
+#define PL330_REG_DBGINST1 0xD0C
+#define PL330_REG_CR0_BASE 0xE00
+#define PL330_REG_PERIPH_ID 0xFE0
+
+#define PL330_IOMEM_SIZE 0x1000
+
+#define CFG_BOOT_ADDR 2
+#define CFG_INS 3
+#define CFG_PNS 4
+#define CFG_CRD 5
+
+static const uint32_t pl330_id[] = {
+ 0x30, 0x13, 0x24, 0x00, 0x0D, 0xF0, 0x05, 0xB1
+};
+
+/* DMA channel states as they are described in PL330 Technical Reference Manual
+ * Most of them will not be used in emulation.
+ */
+typedef enum {
+ pl330_chan_stopped = 0,
+ pl330_chan_executing = 1,
+ pl330_chan_cache_miss = 2,
+ pl330_chan_updating_pc = 3,
+ pl330_chan_waiting_event = 4,
+ pl330_chan_at_barrier = 5,
+ pl330_chan_queue_busy = 6,
+ pl330_chan_waiting_periph = 7,
+ pl330_chan_killing = 8,
+ pl330_chan_completing = 9,
+ pl330_chan_fault_completing = 14,
+ pl330_chan_fault = 15,
+} PL330ChanState;
+
+typedef struct PL330State PL330State;
+
+typedef struct PL330Chan {
+ uint32_t src;
+ uint32_t dst;
+ uint32_t pc;
+ uint32_t control;
+ uint32_t status;
+ uint32_t lc[2];
+ uint32_t fault_type;
+ uint32_t watchdog_timer;
+
+ bool ns;
+ uint8_t request_flag;
+ uint8_t wakeup;
+ uint8_t wfp_sbp;
+
+ uint8_t state;
+ uint8_t stall;
+
+ bool is_manager;
+ PL330State *parent;
+ uint8_t tag;
+} PL330Chan;
+
+static const VMStateDescription vmstate_pl330_chan = {
+ .name = "pl330_chan",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(src, PL330Chan),
+ VMSTATE_UINT32(dst, PL330Chan),
+ VMSTATE_UINT32(pc, PL330Chan),
+ VMSTATE_UINT32(control, PL330Chan),
+ VMSTATE_UINT32(status, PL330Chan),
+ VMSTATE_UINT32_ARRAY(lc, PL330Chan, 2),
+ VMSTATE_UINT32(fault_type, PL330Chan),
+ VMSTATE_UINT32(watchdog_timer, PL330Chan),
+ VMSTATE_BOOL(ns, PL330Chan),
+ VMSTATE_UINT8(request_flag, PL330Chan),
+ VMSTATE_UINT8(wakeup, PL330Chan),
+ VMSTATE_UINT8(wfp_sbp, PL330Chan),
+ VMSTATE_UINT8(state, PL330Chan),
+ VMSTATE_UINT8(stall, PL330Chan),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+typedef struct PL330Fifo {
+ uint8_t *buf;
+ uint8_t *tag;
+ uint32_t head;
+ uint32_t num;
+ uint32_t buf_size;
+} PL330Fifo;
+
+static const VMStateDescription vmstate_pl330_fifo = {
+ .name = "pl330_chan",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_VBUFFER_UINT32(buf, PL330Fifo, 1, NULL, 0, buf_size),
+ VMSTATE_VBUFFER_UINT32(tag, PL330Fifo, 1, NULL, 0, buf_size),
+ VMSTATE_UINT32(head, PL330Fifo),
+ VMSTATE_UINT32(num, PL330Fifo),
+ VMSTATE_UINT32(buf_size, PL330Fifo),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+typedef struct PL330QueueEntry {
+ uint32_t addr;
+ uint32_t len;
+ uint8_t n;
+ bool inc;
+ bool z;
+ uint8_t tag;
+ uint8_t seqn;
+} PL330QueueEntry;
+
+static const VMStateDescription vmstate_pl330_queue_entry = {
+ .name = "pl330_queue_entry",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(addr, PL330QueueEntry),
+ VMSTATE_UINT32(len, PL330QueueEntry),
+ VMSTATE_UINT8(n, PL330QueueEntry),
+ VMSTATE_BOOL(inc, PL330QueueEntry),
+ VMSTATE_BOOL(z, PL330QueueEntry),
+ VMSTATE_UINT8(tag, PL330QueueEntry),
+ VMSTATE_UINT8(seqn, PL330QueueEntry),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+typedef struct PL330Queue {
+ PL330State *parent;
+ PL330QueueEntry *queue;
+ uint32_t queue_size;
+} PL330Queue;
+
+static const VMStateDescription vmstate_pl330_queue = {
+ .name = "pl330_queue",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT_VARRAY_UINT32(queue, PL330Queue, queue_size, 1,
+ vmstate_pl330_queue_entry, PL330QueueEntry),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+struct PL330State {
+ SysBusDevice busdev;
+ MemoryRegion iomem;
+ qemu_irq irq_abort;
+ qemu_irq *irq;
+
+ /* Config registers. cfg[5] = CfgDn. */
+ uint32_t cfg[6];
+#define EVENT_SEC_STATE 3
+#define PERIPH_SEC_STATE 4
+ /* cfg 0 bits and pieces */
+ uint32_t num_chnls;
+ uint8_t num_periph_req;
+ uint8_t num_events;
+ uint8_t mgr_ns_at_rst;
+ /* cfg 1 bits and pieces */
+ uint8_t i_cache_len;
+ uint8_t num_i_cache_lines;
+ /* CRD bits and pieces */
+ uint8_t data_width;
+ uint8_t wr_cap;
+ uint8_t wr_q_dep;
+ uint8_t rd_cap;
+ uint8_t rd_q_dep;
+ uint16_t data_buffer_dep;
+
+ PL330Chan manager;
+ PL330Chan *chan;
+ PL330Fifo fifo;
+ PL330Queue read_queue;
+ PL330Queue write_queue;
+ uint8_t *lo_seqn;
+ uint8_t *hi_seqn;
+ QEMUTimer *timer; /* is used for restore dma. */
+
+ uint32_t inten;
+ uint32_t int_status;
+ uint32_t ev_status;
+ uint32_t dbg[2];
+ uint8_t debug_status;
+ uint8_t num_faulting;
+ uint8_t periph_busy[PL330_PERIPH_NUM];
+
+};
+
+#define TYPE_PL330 "pl330"
+#define PL330(obj) OBJECT_CHECK(PL330State, (obj), TYPE_PL330)
+
+static const VMStateDescription vmstate_pl330 = {
+ .name = "pl330",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT(manager, PL330State, 0, vmstate_pl330_chan, PL330Chan),
+ VMSTATE_STRUCT_VARRAY_UINT32(chan, PL330State, num_chnls, 0,
+ vmstate_pl330_chan, PL330Chan),
+ VMSTATE_VBUFFER_UINT32(lo_seqn, PL330State, 1, NULL, 0, num_chnls),
+ VMSTATE_VBUFFER_UINT32(hi_seqn, PL330State, 1, NULL, 0, num_chnls),
+ VMSTATE_STRUCT(fifo, PL330State, 0, vmstate_pl330_fifo, PL330Fifo),
+ VMSTATE_STRUCT(read_queue, PL330State, 0, vmstate_pl330_queue,
+ PL330Queue),
+ VMSTATE_STRUCT(write_queue, PL330State, 0, vmstate_pl330_queue,
+ PL330Queue),
+ VMSTATE_TIMER(timer, PL330State),
+ VMSTATE_UINT32(inten, PL330State),
+ VMSTATE_UINT32(int_status, PL330State),
+ VMSTATE_UINT32(ev_status, PL330State),
+ VMSTATE_UINT32_ARRAY(dbg, PL330State, 2),
+ VMSTATE_UINT8(debug_status, PL330State),
+ VMSTATE_UINT8(num_faulting, PL330State),
+ VMSTATE_UINT8_ARRAY(periph_busy, PL330State, PL330_PERIPH_NUM),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+typedef struct PL330InsnDesc {
+ /* OPCODE of the instruction */
+ uint8_t opcode;
+ /* Mask so we can select several sibling instructions, such as
+ DMALD, DMALDS and DMALDB */
+ uint8_t opmask;
+ /* Size of instruction in bytes */
+ uint8_t size;
+ /* Interpreter */
+ void (*exec)(PL330Chan *, uint8_t opcode, uint8_t *args, int len);
+} PL330InsnDesc;
+
+
+/* MFIFO Implementation
+ *
+ * MFIFO is implemented as a cyclic buffer of BUF_SIZE size. Tagged bytes are
+ * stored in this buffer. Data is stored in BUF field, tags - in the
+ * corresponding array elements of TAG field.
+ */
+
+/* Initialize queue. */
+
+static void pl330_fifo_init(PL330Fifo *s, uint32_t size)
+{
+ s->buf = g_malloc0(size);
+ s->tag = g_malloc0(size);
+ s->buf_size = size;
+}
+
+/* Cyclic increment */
+
+static inline int pl330_fifo_inc(PL330Fifo *s, int x)
+{
+ return (x + 1) % s->buf_size;
+}
+
+/* Number of empty bytes in MFIFO */
+
+static inline int pl330_fifo_num_free(PL330Fifo *s)
+{
+ return s->buf_size - s->num;
+}
+
+/* Push LEN bytes of data stored in BUF to MFIFO and tag it with TAG.
+ * Zero returned on success, PL330_FIFO_STALL if there is no enough free
+ * space in MFIFO to store requested amount of data. If push was unsuccessful
+ * no data is stored to MFIFO.
+ */
+
+static int pl330_fifo_push(PL330Fifo *s, uint8_t *buf, int len, uint8_t tag)
+{
+ int i;
+
+ if (s->buf_size - s->num < len) {
+ return PL330_FIFO_STALL;
+ }
+ for (i = 0; i < len; i++) {
+ int push_idx = (s->head + s->num + i) % s->buf_size;
+ s->buf[push_idx] = buf[i];
+ s->tag[push_idx] = tag;
+ }
+ s->num += len;
+ return PL330_FIFO_OK;
+}
+
+/* Get LEN bytes of data from MFIFO and store it to BUF. Tag value of each
+ * byte is verified. Zero returned on success, PL330_FIFO_ERR on tag mismatch
+ * and PL330_FIFO_STALL if there is no enough data in MFIFO. If get was
+ * unsuccessful no data is removed from MFIFO.
+ */
+
+static int pl330_fifo_get(PL330Fifo *s, uint8_t *buf, int len, uint8_t tag)
+{
+ int i;
+
+ if (s->num < len) {
+ return PL330_FIFO_STALL;
+ }
+ for (i = 0; i < len; i++) {
+ if (s->tag[s->head] == tag) {
+ int get_idx = (s->head + i) % s->buf_size;
+ buf[i] = s->buf[get_idx];
+ } else { /* Tag mismatch - Rollback transaction */
+ return PL330_FIFO_ERR;
+ }
+ }
+ s->head = (s->head + len) % s->buf_size;
+ s->num -= len;
+ return PL330_FIFO_OK;
+}
+
+/* Reset MFIFO. This completely erases all data in it. */
+
+static inline void pl330_fifo_reset(PL330Fifo *s)
+{
+ s->head = 0;
+ s->num = 0;
+}
+
+/* Return tag of the first byte stored in MFIFO. If MFIFO is empty
+ * PL330_UNTAGGED is returned.
+ */
+
+static inline uint8_t pl330_fifo_tag(PL330Fifo *s)
+{
+ return (!s->num) ? PL330_UNTAGGED : s->tag[s->head];
+}
+
+/* Returns non-zero if tag TAG is present in fifo or zero otherwise */
+
+static int pl330_fifo_has_tag(PL330Fifo *s, uint8_t tag)
+{
+ int i, n;
+
+ i = s->head;
+ for (n = 0; n < s->num; n++) {
+ if (s->tag[i] == tag) {
+ return 1;
+ }
+ i = pl330_fifo_inc(s, i);
+ }
+ return 0;
+}
+
+/* Remove all entry tagged with TAG from MFIFO */
+
+static void pl330_fifo_tagged_remove(PL330Fifo *s, uint8_t tag)
+{
+ int i, t, n;
+
+ t = i = s->head;
+ for (n = 0; n < s->num; n++) {
+ if (s->tag[i] != tag) {
+ s->buf[t] = s->buf[i];
+ s->tag[t] = s->tag[i];
+ t = pl330_fifo_inc(s, t);
+ } else {
+ s->num = s->num - 1;
+ }
+ i = pl330_fifo_inc(s, i);
+ }
+}
+
+/* Read-Write Queue implementation
+ *
+ * A Read-Write Queue stores up to QUEUE_SIZE instructions (loads or stores).
+ * Each instruction is described by source (for loads) or destination (for
+ * stores) address ADDR, width of data to be loaded/stored LEN, number of
+ * stores/loads to be performed N, INC bit, Z bit and TAG to identify channel
+ * this instruction belongs to. Queue does not store any information about
+ * nature of the instruction: is it load or store. PL330 has different queues
+ * for loads and stores so this is already known at the top level where it
+ * matters.
+ *
+ * Queue works as FIFO for instructions with equivalent tags, but can issue
+ * instructions with different tags in arbitrary order. SEQN field attached to
+ * each instruction helps to achieve this. For each TAG queue contains
+ * instructions with consecutive SEQN values ranging from LO_SEQN[TAG] to
+ * HI_SEQN[TAG]-1 inclusive. SEQN is 8-bit unsigned integer, so SEQN=255 is
+ * followed by SEQN=0.
+ *
+ * Z bit indicates that zeroes should be stored. No MFIFO fetches are performed
+ * in this case.
+ */
+
+static void pl330_queue_reset(PL330Queue *s)
+{
+ int i;
+
+ for (i = 0; i < s->queue_size; i++) {
+ s->queue[i].tag = PL330_UNTAGGED;
+ }
+}
+
+/* Initialize queue */
+static void pl330_queue_init(PL330Queue *s, int size, PL330State *parent)
+{
+ s->parent = parent;
+ s->queue = g_new0(PL330QueueEntry, size);
+ s->queue_size = size;
+}
+
+/* Returns pointer to an empty slot or NULL if queue is full */
+static PL330QueueEntry *pl330_queue_find_empty(PL330Queue *s)
+{
+ int i;
+
+ for (i = 0; i < s->queue_size; i++) {
+ if (s->queue[i].tag == PL330_UNTAGGED) {
+ return &s->queue[i];
+ }
+ }
+ return NULL;
+}
+
+/* Put instruction in queue.
+ * Return value:
+ * - zero - OK
+ * - non-zero - queue is full
+ */
+
+static int pl330_queue_put_insn(PL330Queue *s, uint32_t addr,
+ int len, int n, bool inc, bool z, uint8_t tag)
+{
+ PL330QueueEntry *entry = pl330_queue_find_empty(s);
+
+ if (!entry) {
+ return 1;
+ }
+ entry->tag = tag;
+ entry->addr = addr;
+ entry->len = len;
+ entry->n = n;
+ entry->z = z;
+ entry->inc = inc;
+ entry->seqn = s->parent->hi_seqn[tag];
+ s->parent->hi_seqn[tag]++;
+ return 0;
+}
+
+/* Returns a pointer to queue slot containing instruction which satisfies
+ * following conditions:
+ * - it has valid tag value (not PL330_UNTAGGED)
+ * - if enforce_seq is set it has to be issuable without violating queue
+ * logic (see above)
+ * - if TAG argument is not PL330_UNTAGGED this instruction has tag value
+ * equivalent to the argument TAG value.
+ * If such instruction cannot be found NULL is returned.
+ */
+
+static PL330QueueEntry *pl330_queue_find_insn(PL330Queue *s, uint8_t tag,
+ bool enforce_seq)
+{
+ int i;
+
+ for (i = 0; i < s->queue_size; i++) {
+ if (s->queue[i].tag != PL330_UNTAGGED) {
+ if ((!enforce_seq ||
+ s->queue[i].seqn == s->parent->lo_seqn[s->queue[i].tag]) &&
+ (s->queue[i].tag == tag || tag == PL330_UNTAGGED ||
+ s->queue[i].z)) {
+ return &s->queue[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+/* Removes instruction from queue. */
+
+static inline void pl330_queue_remove_insn(PL330Queue *s, PL330QueueEntry *e)
+{
+ s->parent->lo_seqn[e->tag]++;
+ e->tag = PL330_UNTAGGED;
+}
+
+/* Removes all instructions tagged with TAG from queue. */
+
+static inline void pl330_queue_remove_tagged(PL330Queue *s, uint8_t tag)
+{
+ int i;
+
+ for (i = 0; i < s->queue_size; i++) {
+ if (s->queue[i].tag == tag) {
+ s->queue[i].tag = PL330_UNTAGGED;
+ }
+ }
+}
+
+/* DMA instruction execution engine */
+
+/* Moves DMA channel to the FAULT state and updates it's status. */
+
+static inline void pl330_fault(PL330Chan *ch, uint32_t flags)
+{
+ DB_PRINT("ch: %p, flags: %x\n", ch, flags);
+ ch->fault_type |= flags;
+ if (ch->state == pl330_chan_fault) {
+ return;
+ }
+ ch->state = pl330_chan_fault;
+ ch->parent->num_faulting++;
+ if (ch->parent->num_faulting == 1) {
+ DB_PRINT("abort interrupt raised\n");
+ qemu_irq_raise(ch->parent->irq_abort);
+ }
+}
+
+/*
+ * For information about instructions see PL330 Technical Reference Manual.
+ *
+ * Arguments:
+ * CH - channel executing the instruction
+ * OPCODE - opcode
+ * ARGS - array of 8-bit arguments
+ * LEN - number of elements in ARGS array
+ */
+
+static void pl330_dmaaddh(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+ uint16_t im = (((uint16_t)args[1]) << 8) | ((uint16_t)args[0]);
+ uint8_t ra = (opcode >> 1) & 1;
+
+ if (ch->is_manager) {
+ pl330_fault(ch, PL330_FAULT_UNDEF_INSTR);
+ return;
+ }
+ if (ra) {
+ ch->dst += im;
+ } else {
+ ch->src += im;
+ }
+}
+
+static void pl330_dmaend(PL330Chan *ch, uint8_t opcode,
+ uint8_t *args, int len)
+{
+ PL330State *s = ch->parent;
+
+ if (ch->state == pl330_chan_executing && !ch->is_manager) {
+ /* Wait for all transfers to complete */
+ if (pl330_fifo_has_tag(&s->fifo, ch->tag) ||
+ pl330_queue_find_insn(&s->read_queue, ch->tag, false) != NULL ||
+ pl330_queue_find_insn(&s->write_queue, ch->tag, false) != NULL) {
+
+ ch->stall = 1;
+ return;
+ }
+ }
+ DB_PRINT("DMA ending!\n");
+ pl330_fifo_tagged_remove(&s->fifo, ch->tag);
+ pl330_queue_remove_tagged(&s->read_queue, ch->tag);
+ pl330_queue_remove_tagged(&s->write_queue, ch->tag);
+ ch->state = pl330_chan_stopped;
+}
+
+static void pl330_dmaflushp(PL330Chan *ch, uint8_t opcode,
+ uint8_t *args, int len)
+{
+ uint8_t periph_id;
+
+ if (args[0] & 7) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ periph_id = (args[0] >> 3) & 0x1f;
+ if (periph_id >= ch->parent->num_periph_req) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) {
+ pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR);
+ return;
+ }
+ /* Do nothing */
+}
+
+static void pl330_dmago(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+ uint8_t chan_id;
+ uint8_t ns;
+ uint32_t pc;
+ PL330Chan *s;
+
+ DB_PRINT("\n");
+
+ if (!ch->is_manager) {
+ pl330_fault(ch, PL330_FAULT_UNDEF_INSTR);
+ return;
+ }
+ ns = !!(opcode & 2);
+ chan_id = args[0] & 7;
+ if ((args[0] >> 3)) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ if (chan_id >= ch->parent->num_chnls) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ pc = (((uint32_t)args[4]) << 24) | (((uint32_t)args[3]) << 16) |
+ (((uint32_t)args[2]) << 8) | (((uint32_t)args[1]));
+ if (ch->parent->chan[chan_id].state != pl330_chan_stopped) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ if (ch->ns && !ns) {
+ pl330_fault(ch, PL330_FAULT_DMAGO_ERR);
+ return;
+ }
+ s = &ch->parent->chan[chan_id];
+ s->ns = ns;
+ s->pc = pc;
+ s->state = pl330_chan_executing;
+}
+
+static void pl330_dmald(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+ uint8_t bs = opcode & 3;
+ uint32_t size, num;
+ bool inc;
+
+ if (bs == 2) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ if ((bs == 1 && ch->request_flag == PL330_BURST) ||
+ (bs == 3 && ch->request_flag == PL330_SINGLE)) {
+ /* Perform NOP */
+ return;
+ }
+ if (bs == 1 && ch->request_flag == PL330_SINGLE) {
+ num = 1;
+ } else {
+ num = ((ch->control >> 4) & 0xf) + 1;
+ }
+ size = (uint32_t)1 << ((ch->control >> 1) & 0x7);
+ inc = !!(ch->control & 1);
+ ch->stall = pl330_queue_put_insn(&ch->parent->read_queue, ch->src,
+ size, num, inc, 0, ch->tag);
+ if (!ch->stall) {
+ DB_PRINT("channel:%d address:%08x size:%d num:%d %c\n",
+ ch->tag, ch->src, size, num, inc ? 'Y' : 'N');
+ ch->src += inc ? size * num - (ch->src & (size - 1)) : 0;
+ }
+}
+
+static void pl330_dmaldp(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+ uint8_t periph_id;
+
+ if (args[0] & 7) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ periph_id = (args[0] >> 3) & 0x1f;
+ if (periph_id >= ch->parent->num_periph_req) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) {
+ pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR);
+ return;
+ }
+ pl330_dmald(ch, opcode, args, len);
+}
+
+static void pl330_dmalp(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+ uint8_t lc = (opcode & 2) >> 1;
+
+ ch->lc[lc] = args[0];
+}
+
+static void pl330_dmakill(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+ if (ch->state == pl330_chan_fault ||
+ ch->state == pl330_chan_fault_completing) {
+ /* This is the only way for a channel to leave the faulting state */
+ ch->fault_type = 0;
+ ch->parent->num_faulting--;
+ if (ch->parent->num_faulting == 0) {
+ DB_PRINT("abort interrupt lowered\n");
+ qemu_irq_lower(ch->parent->irq_abort);
+ }
+ }
+ ch->state = pl330_chan_killing;
+ pl330_fifo_tagged_remove(&ch->parent->fifo, ch->tag);
+ pl330_queue_remove_tagged(&ch->parent->read_queue, ch->tag);
+ pl330_queue_remove_tagged(&ch->parent->write_queue, ch->tag);
+ ch->state = pl330_chan_stopped;
+}
+
+static void pl330_dmalpend(PL330Chan *ch, uint8_t opcode,
+ uint8_t *args, int len)
+{
+ uint8_t nf = (opcode & 0x10) >> 4;
+ uint8_t bs = opcode & 3;
+ uint8_t lc = (opcode & 4) >> 2;
+
+ if (bs == 2) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ if ((bs == 1 && ch->request_flag == PL330_BURST) ||
+ (bs == 3 && ch->request_flag == PL330_SINGLE)) {
+ /* Perform NOP */
+ return;
+ }
+ if (!nf || ch->lc[lc]) {
+ if (nf) {
+ ch->lc[lc]--;
+ }
+ DB_PRINT("loop reiteration\n");
+ ch->pc -= args[0];
+ ch->pc -= len + 1;
+ /* "ch->pc -= args[0] + len + 1" is incorrect when args[0] == 256 */
+ } else {
+ DB_PRINT("loop fallthrough\n");
+ }
+}
+
+
+static void pl330_dmamov(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+ uint8_t rd = args[0] & 7;
+ uint32_t im;
+
+ if ((args[0] >> 3)) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ im = (((uint32_t)args[4]) << 24) | (((uint32_t)args[3]) << 16) |
+ (((uint32_t)args[2]) << 8) | (((uint32_t)args[1]));
+ switch (rd) {
+ case 0:
+ ch->src = im;
+ break;
+ case 1:
+ ch->control = im;
+ break;
+ case 2:
+ ch->dst = im;
+ break;
+ default:
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+}
+
+static void pl330_dmanop(PL330Chan *ch, uint8_t opcode,
+ uint8_t *args, int len)
+{
+ /* NOP is NOP. */
+}
+
+static void pl330_dmarmb(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+ if (pl330_queue_find_insn(&ch->parent->read_queue, ch->tag, false)) {
+ ch->state = pl330_chan_at_barrier;
+ ch->stall = 1;
+ return;
+ } else {
+ ch->state = pl330_chan_executing;
+ }
+}
+
+static void pl330_dmasev(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+ uint8_t ev_id;
+
+ if (args[0] & 7) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ ev_id = (args[0] >> 3) & 0x1f;
+ if (ev_id >= ch->parent->num_events) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ if (ch->ns && !(ch->parent->cfg[CFG_INS] & (1 << ev_id))) {
+ pl330_fault(ch, PL330_FAULT_EVENT_ERR);
+ return;
+ }
+ if (ch->parent->inten & (1 << ev_id)) {
+ ch->parent->int_status |= (1 << ev_id);
+ DB_PRINT("event interrupt raised %d\n", ev_id);
+ qemu_irq_raise(ch->parent->irq[ev_id]);
+ } else {
+ ch->parent->ev_status |= (1 << ev_id);
+ }
+}
+
+static void pl330_dmast(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+ uint8_t bs = opcode & 3;
+ uint32_t size, num;
+ bool inc;
+
+ if (bs == 2) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ if ((bs == 1 && ch->request_flag == PL330_BURST) ||
+ (bs == 3 && ch->request_flag == PL330_SINGLE)) {
+ /* Perform NOP */
+ return;
+ }
+ num = ((ch->control >> 18) & 0xf) + 1;
+ size = (uint32_t)1 << ((ch->control >> 15) & 0x7);
+ inc = !!((ch->control >> 14) & 1);
+ ch->stall = pl330_queue_put_insn(&ch->parent->write_queue, ch->dst,
+ size, num, inc, 0, ch->tag);
+ if (!ch->stall) {
+ DB_PRINT("channel:%d address:%08x size:%d num:%d %c\n",
+ ch->tag, ch->dst, size, num, inc ? 'Y' : 'N');
+ ch->dst += inc ? size * num - (ch->dst & (size - 1)) : 0;
+ }
+}
+
+static void pl330_dmastp(PL330Chan *ch, uint8_t opcode,
+ uint8_t *args, int len)
+{
+ uint8_t periph_id;
+
+ if (args[0] & 7) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ periph_id = (args[0] >> 3) & 0x1f;
+ if (periph_id >= ch->parent->num_periph_req) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) {
+ pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR);
+ return;
+ }
+ pl330_dmast(ch, opcode, args, len);
+}
+
+static void pl330_dmastz(PL330Chan *ch, uint8_t opcode,
+ uint8_t *args, int len)
+{
+ uint32_t size, num;
+ bool inc;
+
+ num = ((ch->control >> 18) & 0xf) + 1;
+ size = (uint32_t)1 << ((ch->control >> 15) & 0x7);
+ inc = !!((ch->control >> 14) & 1);
+ ch->stall = pl330_queue_put_insn(&ch->parent->write_queue, ch->dst,
+ size, num, inc, 1, ch->tag);
+ if (inc) {
+ ch->dst += size * num;
+ }
+}
+
+static void pl330_dmawfe(PL330Chan *ch, uint8_t opcode,
+ uint8_t *args, int len)
+{
+ uint8_t ev_id;
+ int i;
+
+ if (args[0] & 5) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ ev_id = (args[0] >> 3) & 0x1f;
+ if (ev_id >= ch->parent->num_events) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ if (ch->ns && !(ch->parent->cfg[CFG_INS] & (1 << ev_id))) {
+ pl330_fault(ch, PL330_FAULT_EVENT_ERR);
+ return;
+ }
+ ch->wakeup = ev_id;
+ ch->state = pl330_chan_waiting_event;
+ if (~ch->parent->inten & ch->parent->ev_status & 1 << ev_id) {
+ ch->state = pl330_chan_executing;
+ /* If anyone else is currently waiting on the same event, let them
+ * clear the ev_status so they pick up event as well
+ */
+ for (i = 0; i < ch->parent->num_chnls; ++i) {
+ PL330Chan *peer = &ch->parent->chan[i];
+ if (peer->state == pl330_chan_waiting_event &&
+ peer->wakeup == ev_id) {
+ return;
+ }
+ }
+ ch->parent->ev_status &= ~(1 << ev_id);
+ } else {
+ ch->stall = 1;
+ }
+}
+
+static void pl330_dmawfp(PL330Chan *ch, uint8_t opcode,
+ uint8_t *args, int len)
+{
+ uint8_t bs = opcode & 3;
+ uint8_t periph_id;
+
+ if (args[0] & 7) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ periph_id = (args[0] >> 3) & 0x1f;
+ if (periph_id >= ch->parent->num_periph_req) {
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+ if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) {
+ pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR);
+ return;
+ }
+ switch (bs) {
+ case 0: /* S */
+ ch->request_flag = PL330_SINGLE;
+ ch->wfp_sbp = 0;
+ break;
+ case 1: /* P */
+ ch->request_flag = PL330_BURST;
+ ch->wfp_sbp = 2;
+ break;
+ case 2: /* B */
+ ch->request_flag = PL330_BURST;
+ ch->wfp_sbp = 1;
+ break;
+ default:
+ pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+ return;
+ }
+
+ if (ch->parent->periph_busy[periph_id]) {
+ ch->state = pl330_chan_waiting_periph;
+ ch->stall = 1;
+ } else if (ch->state == pl330_chan_waiting_periph) {
+ ch->state = pl330_chan_executing;
+ }
+}
+
+static void pl330_dmawmb(PL330Chan *ch, uint8_t opcode,
+ uint8_t *args, int len)
+{
+ if (pl330_queue_find_insn(&ch->parent->write_queue, ch->tag, false)) {
+ ch->state = pl330_chan_at_barrier;
+ ch->stall = 1;
+ return;
+ } else {
+ ch->state = pl330_chan_executing;
+ }
+}
+
+/* NULL terminated array of the instruction descriptions. */
+static const PL330InsnDesc insn_desc[] = {
+ { .opcode = 0x54, .opmask = 0xFD, .size = 3, .exec = pl330_dmaaddh, },
+ { .opcode = 0x00, .opmask = 0xFF, .size = 1, .exec = pl330_dmaend, },
+ { .opcode = 0x35, .opmask = 0xFF, .size = 2, .exec = pl330_dmaflushp, },
+ { .opcode = 0xA0, .opmask = 0xFD, .size = 6, .exec = pl330_dmago, },
+ { .opcode = 0x04, .opmask = 0xFC, .size = 1, .exec = pl330_dmald, },
+ { .opcode = 0x25, .opmask = 0xFD, .size = 2, .exec = pl330_dmaldp, },
+ { .opcode = 0x20, .opmask = 0xFD, .size = 2, .exec = pl330_dmalp, },
+ /* dmastp must be before dmalpend in this list, because their maps
+ * are overlapping
+ */
+ { .opcode = 0x29, .opmask = 0xFD, .size = 2, .exec = pl330_dmastp, },
+ { .opcode = 0x28, .opmask = 0xE8, .size = 2, .exec = pl330_dmalpend, },
+ { .opcode = 0x01, .opmask = 0xFF, .size = 1, .exec = pl330_dmakill, },
+ { .opcode = 0xBC, .opmask = 0xFF, .size = 6, .exec = pl330_dmamov, },
+ { .opcode = 0x18, .opmask = 0xFF, .size = 1, .exec = pl330_dmanop, },
+ { .opcode = 0x12, .opmask = 0xFF, .size = 1, .exec = pl330_dmarmb, },
+ { .opcode = 0x34, .opmask = 0xFF, .size = 2, .exec = pl330_dmasev, },
+ { .opcode = 0x08, .opmask = 0xFC, .size = 1, .exec = pl330_dmast, },
+ { .opcode = 0x0C, .opmask = 0xFF, .size = 1, .exec = pl330_dmastz, },
+ { .opcode = 0x36, .opmask = 0xFF, .size = 2, .exec = pl330_dmawfe, },
+ { .opcode = 0x30, .opmask = 0xFC, .size = 2, .exec = pl330_dmawfp, },
+ { .opcode = 0x13, .opmask = 0xFF, .size = 1, .exec = pl330_dmawmb, },
+ { .opcode = 0x00, .opmask = 0x00, .size = 0, .exec = NULL, }
+};
+
+/* Instructions which can be issued via debug registers. */
+static const PL330InsnDesc debug_insn_desc[] = {
+ { .opcode = 0xA0, .opmask = 0xFD, .size = 6, .exec = pl330_dmago, },
+ { .opcode = 0x01, .opmask = 0xFF, .size = 1, .exec = pl330_dmakill, },
+ { .opcode = 0x34, .opmask = 0xFF, .size = 2, .exec = pl330_dmasev, },
+ { .opcode = 0x00, .opmask = 0x00, .size = 0, .exec = NULL, }
+};
+
+static inline const PL330InsnDesc *pl330_fetch_insn(PL330Chan *ch)
+{
+ uint8_t opcode;
+ int i;
+
+ dma_memory_read(&dma_context_memory, ch->pc, &opcode, 1);
+ for (i = 0; insn_desc[i].size; i++) {
+ if ((opcode & insn_desc[i].opmask) == insn_desc[i].opcode) {
+ return &insn_desc[i];
+ }
+ }
+ return NULL;
+}
+
+static inline void pl330_exec_insn(PL330Chan *ch, const PL330InsnDesc *insn)
+{
+ uint8_t buf[PL330_INSN_MAXSIZE];
+
+ assert(insn->size <= PL330_INSN_MAXSIZE);
+ dma_memory_read(&dma_context_memory, ch->pc, buf, insn->size);
+ insn->exec(ch, buf[0], &buf[1], insn->size - 1);
+}
+
+static inline void pl330_update_pc(PL330Chan *ch,
+ const PL330InsnDesc *insn)
+{
+ ch->pc += insn->size;
+}
+
+/* Try to execute current instruction in channel CH. Number of executed
+ instructions is returned (0 or 1). */
+static int pl330_chan_exec(PL330Chan *ch)
+{
+ const PL330InsnDesc *insn;
+
+ if (ch->state != pl330_chan_executing &&
+ ch->state != pl330_chan_waiting_periph &&
+ ch->state != pl330_chan_at_barrier &&
+ ch->state != pl330_chan_waiting_event) {
+ DB_PRINT("%d\n", ch->state);
+ return 0;
+ }
+ ch->stall = 0;
+ insn = pl330_fetch_insn(ch);
+ if (!insn) {
+ DB_PRINT("pl330 undefined instruction\n");
+ pl330_fault(ch, PL330_FAULT_UNDEF_INSTR);
+ return 0;
+ }
+ pl330_exec_insn(ch, insn);
+ if (!ch->stall) {
+ pl330_update_pc(ch, insn);
+ ch->watchdog_timer = 0;
+ return 1;
+ /* WDT only active in exec state */
+ } else if (ch->state == pl330_chan_executing) {
+ ch->watchdog_timer++;
+ if (ch->watchdog_timer >= PL330_WATCHDOG_LIMIT) {
+ pl330_fault(ch, PL330_FAULT_LOCKUP_ERR);
+ }
+ }
+ return 0;
+}
+
+/* Try to execute 1 instruction in each channel, one instruction from read
+ queue and one instruction from write queue. Number of successfully executed
+ instructions is returned. */
+static int pl330_exec_cycle(PL330Chan *channel)
+{
+ PL330State *s = channel->parent;
+ PL330QueueEntry *q;
+ int i;
+ int num_exec = 0;
+ int fifo_res = 0;
+ uint8_t buf[PL330_MAX_BURST_LEN];
+
+ /* Execute one instruction in each channel */
+ num_exec += pl330_chan_exec(channel);
+
+ /* Execute one instruction from read queue */
+ q = pl330_queue_find_insn(&s->read_queue, PL330_UNTAGGED, true);
+ if (q != NULL && q->len <= pl330_fifo_num_free(&s->fifo)) {
+ int len = q->len - (q->addr & (q->len - 1));
+
+ dma_memory_read(&dma_context_memory, q->addr, buf, len);
+ if (PL330_ERR_DEBUG > 1) {
+ DB_PRINT("PL330 read from memory @%08x (size = %08x):\n",
+ q->addr, len);
+ hexdump((char *)buf, stderr, "", len);
+ }
+ fifo_res = pl330_fifo_push(&s->fifo, buf, len, q->tag);
+ if (fifo_res == PL330_FIFO_OK) {
+ if (q->inc) {
+ q->addr += len;
+ }
+ q->n--;
+ if (!q->n) {
+ pl330_queue_remove_insn(&s->read_queue, q);
+ }
+ num_exec++;
+ }
+ }
+
+ /* Execute one instruction from write queue. */
+ q = pl330_queue_find_insn(&s->write_queue, pl330_fifo_tag(&s->fifo), true);
+ if (q != NULL) {
+ int len = q->len - (q->addr & (q->len - 1));
+
+ if (q->z) {
+ for (i = 0; i < len; i++) {
+ buf[i] = 0;
+ }
+ } else {
+ fifo_res = pl330_fifo_get(&s->fifo, buf, len, q->tag);
+ }
+ if (fifo_res == PL330_FIFO_OK || q->z) {
+ dma_memory_write(&dma_context_memory, q->addr, buf, len);
+ if (PL330_ERR_DEBUG > 1) {
+ DB_PRINT("PL330 read from memory @%08x (size = %08x):\n",
+ q->addr, len);
+ hexdump((char *)buf, stderr, "", len);
+ }
+ if (q->inc) {
+ q->addr += len;
+ }
+ num_exec++;
+ } else if (fifo_res == PL330_FIFO_STALL) {
+ pl330_fault(&channel->parent->chan[q->tag],
+ PL330_FAULT_FIFOEMPTY_ERR);
+ }
+ q->n--;
+ if (!q->n) {
+ pl330_queue_remove_insn(&s->write_queue, q);
+ }
+ }
+
+ return num_exec;
+}
+
+static int pl330_exec_channel(PL330Chan *channel)
+{
+ int insr_exec = 0;
+
+ /* TODO: Is it all right to execute everything or should we do per-cycle
+ simulation? */
+ while (pl330_exec_cycle(channel)) {
+ insr_exec++;
+ }
+
+ /* Detect deadlock */
+ if (channel->state == pl330_chan_executing) {
+ pl330_fault(channel, PL330_FAULT_LOCKUP_ERR);
+ }
+ /* Situation when one of the queues has deadlocked but all channels
+ * have finished their programs should be impossible.
+ */
+
+ return insr_exec;
+}
+
+static inline void pl330_exec(PL330State *s)
+{
+ DB_PRINT("\n");
+ int i, insr_exec;
+ do {
+ insr_exec = pl330_exec_channel(&s->manager);
+
+ for (i = 0; i < s->num_chnls; i++) {
+ insr_exec += pl330_exec_channel(&s->chan[i]);
+ }
+ } while (insr_exec);
+}
+
+static void pl330_exec_cycle_timer(void *opaque)
+{
+ PL330State *s = (PL330State *)opaque;
+ pl330_exec(s);
+}
+
+/* Stop or restore dma operations */
+
+static void pl330_dma_stop_irq(void *opaque, int irq, int level)
+{
+ PL330State *s = (PL330State *)opaque;
+
+ if (s->periph_busy[irq] != level) {
+ s->periph_busy[irq] = level;
+ qemu_mod_timer(s->timer, qemu_get_clock_ns(vm_clock));
+ }
+}
+
+static void pl330_debug_exec(PL330State *s)
+{
+ uint8_t args[5];
+ uint8_t opcode;
+ uint8_t chan_id;
+ int i;
+ PL330Chan *ch;
+ const PL330InsnDesc *insn;
+
+ s->debug_status = 1;
+ chan_id = (s->dbg[0] >> 8) & 0x07;
+ opcode = (s->dbg[0] >> 16) & 0xff;
+ args[0] = (s->dbg[0] >> 24) & 0xff;
+ args[1] = (s->dbg[1] >> 0) & 0xff;
+ args[2] = (s->dbg[1] >> 8) & 0xff;
+ args[3] = (s->dbg[1] >> 16) & 0xff;
+ args[4] = (s->dbg[1] >> 24) & 0xff;
+ DB_PRINT("chan id: %d\n", chan_id);
+ if (s->dbg[0] & 1) {
+ ch = &s->chan[chan_id];
+ } else {
+ ch = &s->manager;
+ }
+ insn = NULL;
+ for (i = 0; debug_insn_desc[i].size; i++) {
+ if ((opcode & debug_insn_desc[i].opmask) == debug_insn_desc[i].opcode) {
+ insn = &debug_insn_desc[i];
+ }
+ }
+ if (!insn) {
+ pl330_fault(ch, PL330_FAULT_UNDEF_INSTR | PL330_FAULT_DBG_INSTR);
+ return ;
+ }
+ ch->stall = 0;
+ insn->exec(ch, opcode, args, insn->size - 1);
+ if (ch->fault_type) {
+ ch->fault_type |= PL330_FAULT_DBG_INSTR;
+ }
+ if (ch->stall) {
+ qemu_log_mask(LOG_UNIMP, "pl330: stall of debug instruction not "
+ "implemented\n");
+ }
+ s->debug_status = 0;
+}
+
+/* IOMEM mapped registers */
+
+static void pl330_iomem_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ PL330State *s = (PL330State *) opaque;
+ uint32_t i;
+
+ DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)value);
+
+ switch (offset) {
+ case PL330_REG_INTEN:
+ s->inten = value;
+ break;
+ case PL330_REG_INTCLR:
+ for (i = 0; i < s->num_events; i++) {
+ if (s->int_status & s->inten & value & (1 << i)) {
+ DB_PRINT("event interrupt lowered %d\n", i);
+ qemu_irq_lower(s->irq[i]);
+ }
+ }
+ s->ev_status &= ~(value & s->inten);
+ s->int_status &= ~(value & s->inten);
+ break;
+ case PL330_REG_DBGCMD:
+ if ((value & 3) == 0) {
+ pl330_debug_exec(s);
+ pl330_exec(s);
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR, "pl330: write of illegal value %u "
+ "for offset " TARGET_FMT_plx "\n", (unsigned)value,
+ offset);
+ }
+ break;
+ case PL330_REG_DBGINST0:
+ DB_PRINT("s->dbg[0] = %08x\n", (unsigned)value);
+ s->dbg[0] = value;
+ break;
+ case PL330_REG_DBGINST1:
+ DB_PRINT("s->dbg[1] = %08x\n", (unsigned)value);
+ s->dbg[1] = value;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad write offset " TARGET_FMT_plx
+ "\n", offset);
+ break;
+ }
+}
+
+static inline uint32_t pl330_iomem_read_imp(void *opaque,
+ hwaddr offset)
+{
+ PL330State *s = (PL330State *)opaque;
+ int chan_id;
+ int i;
+ uint32_t res;
+
+ if (offset >= PL330_REG_PERIPH_ID && offset < PL330_REG_PERIPH_ID + 32) {
+ return pl330_id[(offset - PL330_REG_PERIPH_ID) >> 2];
+ }
+ if (offset >= PL330_REG_CR0_BASE && offset < PL330_REG_CR0_BASE + 24) {
+ return s->cfg[(offset - PL330_REG_CR0_BASE) >> 2];
+ }
+ if (offset >= PL330_REG_CHANCTRL && offset < PL330_REG_DBGSTATUS) {
+ offset -= PL330_REG_CHANCTRL;
+ chan_id = offset >> 5;
+ if (chan_id >= s->num_chnls) {
+ qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset "
+ TARGET_FMT_plx "\n", offset);
+ return 0;
+ }
+ switch (offset & 0x1f) {
+ case 0x00:
+ return s->chan[chan_id].src;
+ case 0x04:
+ return s->chan[chan_id].dst;
+ case 0x08:
+ return s->chan[chan_id].control;
+ case 0x0C:
+ return s->chan[chan_id].lc[0];
+ case 0x10:
+ return s->chan[chan_id].lc[1];
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset "
+ TARGET_FMT_plx "\n", offset);
+ return 0;
+ }
+ }
+ if (offset >= PL330_REG_CSR_BASE && offset < 0x400) {
+ offset -= PL330_REG_CSR_BASE;
+ chan_id = offset >> 3;
+ if (chan_id >= s->num_chnls) {
+ qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset "
+ TARGET_FMT_plx "\n", offset);
+ return 0;
+ }
+ switch ((offset >> 2) & 1) {
+ case 0x0:
+ res = (s->chan[chan_id].ns << 21) |
+ (s->chan[chan_id].wakeup << 4) |
+ (s->chan[chan_id].state) |
+ (s->chan[chan_id].wfp_sbp << 14);
+ return res;
+ case 0x1:
+ return s->chan[chan_id].pc;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "pl330: read error\n");
+ return 0;
+ }
+ }
+ if (offset >= PL330_REG_FTR_BASE && offset < 0x100) {
+ offset -= PL330_REG_FTR_BASE;
+ chan_id = offset >> 2;
+ if (chan_id >= s->num_chnls) {
+ qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset "
+ TARGET_FMT_plx "\n", offset);
+ return 0;
+ }
+ return s->chan[chan_id].fault_type;
+ }
+ switch (offset) {
+ case PL330_REG_DSR:
+ return (s->manager.ns << 9) | (s->manager.wakeup << 4) |
+ (s->manager.state & 0xf);
+ case PL330_REG_DPC:
+ return s->manager.pc;
+ case PL330_REG_INTEN:
+ return s->inten;
+ case PL330_REG_INT_EVENT_RIS:
+ return s->ev_status;
+ case PL330_REG_INTMIS:
+ return s->int_status;
+ case PL330_REG_INTCLR:
+ /* Documentation says that we can't read this register
+ * but linux kernel does it
+ */
+ return 0;
+ case PL330_REG_FSRD:
+ return s->manager.state ? 1 : 0;
+ case PL330_REG_FSRC:
+ res = 0;
+ for (i = 0; i < s->num_chnls; i++) {
+ if (s->chan[i].state == pl330_chan_fault ||
+ s->chan[i].state == pl330_chan_fault_completing) {
+ res |= 1 << i;
+ }
+ }
+ return res;
+ case PL330_REG_FTRD:
+ return s->manager.fault_type;
+ case PL330_REG_DBGSTATUS:
+ return s->debug_status;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset "
+ TARGET_FMT_plx "\n", offset);
+ }
+ return 0;
+}
+
+static uint64_t pl330_iomem_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ int ret = pl330_iomem_read_imp(opaque, offset);
+ DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, ret);
+ return ret;
+}
+
+static const MemoryRegionOps pl330_ops = {
+ .read = pl330_iomem_read,
+ .write = pl330_iomem_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ }
+};
+
+/* Controller logic and initialization */
+
+static void pl330_chan_reset(PL330Chan *ch)
+{
+ ch->src = 0;
+ ch->dst = 0;
+ ch->pc = 0;
+ ch->state = pl330_chan_stopped;
+ ch->watchdog_timer = 0;
+ ch->stall = 0;
+ ch->control = 0;
+ ch->status = 0;
+ ch->fault_type = 0;
+}
+
+static void pl330_reset(DeviceState *d)
+{
+ int i;
+ PL330State *s = PL330(d);
+
+ s->inten = 0;
+ s->int_status = 0;
+ s->ev_status = 0;
+ s->debug_status = 0;
+ s->num_faulting = 0;
+ s->manager.ns = s->mgr_ns_at_rst;
+ pl330_fifo_reset(&s->fifo);
+ pl330_queue_reset(&s->read_queue);
+ pl330_queue_reset(&s->write_queue);
+
+ for (i = 0; i < s->num_chnls; i++) {
+ pl330_chan_reset(&s->chan[i]);
+ }
+ for (i = 0; i < s->num_periph_req; i++) {
+ s->periph_busy[i] = 0;
+ }
+
+ qemu_del_timer(s->timer);
+}
+
+static void pl330_realize(DeviceState *dev, Error **errp)
+{
+ int i;
+ PL330State *s = PL330(dev);
+
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq_abort);
+ memory_region_init_io(&s->iomem, &pl330_ops, s, "dma", PL330_IOMEM_SIZE);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+
+ s->timer = qemu_new_timer_ns(vm_clock, pl330_exec_cycle_timer, s);
+
+ s->cfg[0] = (s->mgr_ns_at_rst ? 0x4 : 0) |
+ (s->num_periph_req > 0 ? 1 : 0) |
+ ((s->num_chnls - 1) & 0x7) << 4 |
+ ((s->num_periph_req - 1) & 0x1f) << 12 |
+ ((s->num_events - 1) & 0x1f) << 17;
+
+ switch (s->i_cache_len) {
+ case (4):
+ s->cfg[1] |= 2;
+ break;
+ case (8):
+ s->cfg[1] |= 3;
+ break;
+ case (16):
+ s->cfg[1] |= 4;
+ break;
+ case (32):
+ s->cfg[1] |= 5;
+ break;
+ default:
+ error_setg(errp, "Bad value for i-cache_len property: %d\n",
+ s->i_cache_len);
+ return;
+ }
+ s->cfg[1] |= ((s->num_i_cache_lines - 1) & 0xf) << 4;
+
+ s->chan = g_new0(PL330Chan, s->num_chnls);
+ s->hi_seqn = g_new0(uint8_t, s->num_chnls);
+ s->lo_seqn = g_new0(uint8_t, s->num_chnls);
+ for (i = 0; i < s->num_chnls; i++) {
+ s->chan[i].parent = s;
+ s->chan[i].tag = (uint8_t)i;
+ }
+ s->manager.parent = s;
+ s->manager.tag = s->num_chnls;
+ s->manager.is_manager = true;
+
+ s->irq = g_new0(qemu_irq, s->num_events);
+ for (i = 0; i < s->num_events; i++) {
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
+ }
+
+ qdev_init_gpio_in(dev, pl330_dma_stop_irq, PL330_PERIPH_NUM);
+
+ switch (s->data_width) {
+ case (32):
+ s->cfg[CFG_CRD] |= 0x2;
+ break;
+ case (64):
+ s->cfg[CFG_CRD] |= 0x3;
+ break;
+ case (128):
+ s->cfg[CFG_CRD] |= 0x4;
+ break;
+ default:
+ error_setg(errp, "Bad value for data_width property: %d\n",
+ s->data_width);
+ return;
+ }
+
+ s->cfg[CFG_CRD] |= ((s->wr_cap - 1) & 0x7) << 4 |
+ ((s->wr_q_dep - 1) & 0xf) << 8 |
+ ((s->rd_cap - 1) & 0x7) << 12 |
+ ((s->rd_q_dep - 1) & 0xf) << 16 |
+ ((s->data_buffer_dep - 1) & 0x1ff) << 20;
+
+ pl330_queue_init(&s->read_queue, s->rd_q_dep, s);
+ pl330_queue_init(&s->write_queue, s->wr_q_dep, s);
+ pl330_fifo_init(&s->fifo, s->data_buffer_dep);
+}
+
+static Property pl330_properties[] = {
+ /* CR0 */
+ DEFINE_PROP_UINT32("num_chnls", PL330State, num_chnls, 8),
+ DEFINE_PROP_UINT8("num_periph_req", PL330State, num_periph_req, 4),
+ DEFINE_PROP_UINT8("num_events", PL330State, num_events, 16),
+ DEFINE_PROP_UINT8("mgr_ns_at_rst", PL330State, mgr_ns_at_rst, 0),
+ /* CR1 */
+ DEFINE_PROP_UINT8("i-cache_len", PL330State, i_cache_len, 4),
+ DEFINE_PROP_UINT8("num_i-cache_lines", PL330State, num_i_cache_lines, 8),
+ /* CR2-4 */
+ DEFINE_PROP_UINT32("boot_addr", PL330State, cfg[CFG_BOOT_ADDR], 0),
+ DEFINE_PROP_UINT32("INS", PL330State, cfg[CFG_INS], 0),
+ DEFINE_PROP_UINT32("PNS", PL330State, cfg[CFG_PNS], 0),
+ /* CRD */
+ DEFINE_PROP_UINT8("data_width", PL330State, data_width, 64),
+ DEFINE_PROP_UINT8("wr_cap", PL330State, wr_cap, 8),
+ DEFINE_PROP_UINT8("wr_q_dep", PL330State, wr_q_dep, 16),
+ DEFINE_PROP_UINT8("rd_cap", PL330State, rd_cap, 8),
+ DEFINE_PROP_UINT8("rd_q_dep", PL330State, rd_q_dep, 16),
+ DEFINE_PROP_UINT16("data_buffer_dep", PL330State, data_buffer_dep, 256),
+
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pl330_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = pl330_realize;
+ dc->reset = pl330_reset;
+ dc->props = pl330_properties;
+ dc->vmsd = &vmstate_pl330;
+}
+
+static const TypeInfo pl330_type_info = {
+ .name = TYPE_PL330,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PL330State),
+ .class_init = pl330_class_init,
+};
+
+static void pl330_register_types(void)
+{
+ type_register_static(&pl330_type_info);
+}
+
+type_init(pl330_register_types)
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 6484d27de1..f2b0c93661 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -39,7 +39,7 @@ struct PXA2xxLCDState {
int irqlevel;
int invalidated;
- DisplayState *ds;
+ QemuConsole *con;
drawfn *line_fn[2];
int dest_width;
int xres, yres;
@@ -579,6 +579,7 @@ static const MemoryRegionOps pxa2xx_lcdc_ops = {
/* Load new palette for a given DMA channel, convert to internal format */
static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int i, n, format, r, g, b, alpha;
uint32_t *dest;
uint8_t *src;
@@ -652,7 +653,7 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
src += 4;
break;
}
- switch (ds_get_bits_per_pixel(s->ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 8:
*dest = rgb_to_pixel8(r, g, b) | alpha;
break;
@@ -676,6 +677,7 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
hwaddr addr, int *miny, int *maxy)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int src_width, dest_width;
drawfn fn = NULL;
if (s->dest_width)
@@ -693,7 +695,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
dest_width = s->xres * s->dest_width;
*miny = 0;
- framebuffer_update_display(s->ds, s->sysmem,
+ framebuffer_update_display(surface, s->sysmem,
addr, s->xres, s->yres,
src_width, dest_width, s->dest_width,
s->invalidated,
@@ -703,6 +705,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
hwaddr addr, int *miny, int *maxy)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int src_width, dest_width;
drawfn fn = NULL;
if (s->dest_width)
@@ -720,7 +723,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
dest_width = s->yres * s->dest_width;
*miny = 0;
- framebuffer_update_display(s->ds, s->sysmem,
+ framebuffer_update_display(surface, s->sysmem,
addr, s->xres, s->yres,
src_width, s->dest_width, -dest_width,
s->invalidated,
@@ -731,6 +734,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
hwaddr addr, int *miny, int *maxy)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int src_width, dest_width;
drawfn fn = NULL;
if (s->dest_width) {
@@ -751,7 +755,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
dest_width = s->xres * s->dest_width;
*miny = 0;
- framebuffer_update_display(s->ds, s->sysmem,
+ framebuffer_update_display(surface, s->sysmem,
addr, s->xres, s->yres,
src_width, -dest_width, -s->dest_width,
s->invalidated,
@@ -761,6 +765,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
hwaddr addr, int *miny, int *maxy)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int src_width, dest_width;
drawfn fn = NULL;
if (s->dest_width) {
@@ -781,7 +786,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
dest_width = s->yres * s->dest_width;
*miny = 0;
- framebuffer_update_display(s->ds, s->sysmem,
+ framebuffer_update_display(surface, s->sysmem,
addr, s->xres, s->yres,
src_width, -s->dest_width, dest_width,
s->invalidated,
@@ -800,9 +805,9 @@ static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
if (width != s->xres || height != s->yres) {
if (s->orientation == 90 || s->orientation == 270) {
- qemu_console_resize(s->ds, height, width);
+ qemu_console_resize(s->con, height, width);
} else {
- qemu_console_resize(s->ds, width, height);
+ qemu_console_resize(s->con, width, height);
}
s->invalidated = 1;
s->xres = width;
@@ -871,20 +876,20 @@ static void pxa2xx_update_display(void *opaque)
if (miny >= 0) {
switch (s->orientation) {
case 0:
- dpy_gfx_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
+ dpy_gfx_update(s->con, 0, miny, s->xres, maxy - miny + 1);
break;
case 90:
- dpy_gfx_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
+ dpy_gfx_update(s->con, miny, 0, maxy - miny + 1, s->xres);
break;
case 180:
maxy = s->yres - maxy - 1;
miny = s->yres - miny - 1;
- dpy_gfx_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
+ dpy_gfx_update(s->con, 0, maxy, s->xres, miny - maxy + 1);
break;
case 270:
maxy = s->yres - maxy - 1;
miny = s->yres - miny - 1;
- dpy_gfx_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
+ dpy_gfx_update(s->con, maxy, 0, miny - maxy + 1, s->xres);
break;
}
}
@@ -990,6 +995,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
hwaddr base, qemu_irq irq)
{
PXA2xxLCDState *s;
+ DisplaySurface *surface;
s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState));
s->invalidated = 1;
@@ -1002,11 +1008,12 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
"pxa2xx-lcd-controller", 0x00100000);
memory_region_add_subregion(sysmem, base, &s->iomem);
- s->ds = graphic_console_init(pxa2xx_update_display,
- pxa2xx_invalidate_display,
- NULL, NULL, s);
+ s->con = graphic_console_init(pxa2xx_update_display,
+ pxa2xx_invalidate_display,
+ NULL, NULL, s);
+ surface = qemu_console_surface(s->con);
- switch (ds_get_bits_per_pixel(s->ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 0:
s->dest_width = 0;
break;
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index 2486f36853..547fbc7e0d 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -175,6 +175,9 @@ struct Property {
uint8_t bitnr;
uint8_t qtype;
int64_t defval;
+ int arrayoffset;
+ PropertyInfo *arrayinfo;
+ int arrayfieldsize;
};
struct PropertyInfo {
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 0307a7830b..247ca6c5b4 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -779,6 +779,110 @@ PropertyInfo qdev_prop_pci_host_devaddr = {
.set = set_pci_host_devaddr,
};
+/* --- support for array properties --- */
+
+/* Used as an opaque for the object properties we add for each
+ * array element. Note that the struct Property must be first
+ * in the struct so that a pointer to this works as the opaque
+ * for the underlying element's property hooks as well as for
+ * our own release callback.
+ */
+typedef struct {
+ struct Property prop;
+ char *propname;
+ ObjectPropertyRelease *release;
+} ArrayElementProperty;
+
+/* object property release callback for array element properties:
+ * we call the underlying element's property release hook, and
+ * then free the memory we allocated when we added the property.
+ */
+static void array_element_release(Object *obj, const char *name, void *opaque)
+{
+ ArrayElementProperty *p = opaque;
+ if (p->release) {
+ p->release(obj, name, opaque);
+ }
+ g_free(p->propname);
+ g_free(p);
+}
+
+static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ /* Setter for the property which defines the length of a
+ * variable-sized property array. As well as actually setting the
+ * array-length field in the device struct, we have to create the
+ * array itself and dynamically add the corresponding properties.
+ */
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
+ void **arrayptr = (void *)dev + prop->arrayoffset;
+ void *eltptr;
+ const char *arrayname;
+ int i;
+
+ if (dev->realized) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+ if (*alenptr) {
+ error_setg(errp, "array size property %s may not be set more than once",
+ name);
+ return;
+ }
+ visit_type_uint32(v, alenptr, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (!*alenptr) {
+ return;
+ }
+
+ /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
+ * strip it off so we can get the name of the array itself.
+ */
+ assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
+ strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
+ arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
+
+ /* Note that it is the responsibility of the individual device's deinit
+ * to free the array proper.
+ */
+ *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
+ for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
+ char *propname = g_strdup_printf("%s[%d]", arrayname, i);
+ ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
+ arrayprop->release = prop->arrayinfo->release;
+ arrayprop->propname = propname;
+ arrayprop->prop.info = prop->arrayinfo;
+ arrayprop->prop.name = propname;
+ /* This ugly piece of pointer arithmetic sets up the offset so
+ * that when the underlying get/set hooks call qdev_get_prop_ptr
+ * they get the right answer despite the array element not actually
+ * being inside the device struct.
+ */
+ arrayprop->prop.offset = eltptr - (void *)dev;
+ assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
+ object_property_add(obj, propname,
+ arrayprop->prop.info->name,
+ arrayprop->prop.info->get,
+ arrayprop->prop.info->set,
+ array_element_release,
+ arrayprop, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ }
+}
+
+PropertyInfo qdev_prop_arraylen = {
+ .name = "uint32",
+ .get = get_uint32,
+ .set = set_prop_arraylen,
+};
+
/* --- public helpers --- */
static Property *qdev_prop_walk(Property *props, const char *name)
diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h
index 0b0465c9b3..c9bb246841 100644
--- a/hw/qdev-properties.h
+++ b/hw/qdev-properties.h
@@ -26,6 +26,7 @@ extern PropertyInfo qdev_prop_vlan;
extern PropertyInfo qdev_prop_pci_devfn;
extern PropertyInfo qdev_prop_blocksize;
extern PropertyInfo qdev_prop_pci_host_devaddr;
+extern PropertyInfo qdev_prop_arraylen;
#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
.name = (_name), \
@@ -51,6 +52,44 @@ extern PropertyInfo qdev_prop_pci_host_devaddr;
.defval = (bool)_defval, \
}
+#define PROP_ARRAY_LEN_PREFIX "len-"
+
+/**
+ * DEFINE_PROP_ARRAY:
+ * @_name: name of the array
+ * @_state: name of the device state structure type
+ * @_field: uint32_t field in @_state to hold the array length
+ * @_arrayfield: field in @_state (of type '@_arraytype *') which
+ * will point to the array
+ * @_arrayprop: PropertyInfo defining what property the array elements have
+ * @_arraytype: C type of the array elements
+ *
+ * Define device properties for a variable-length array _name. A
+ * static property "len-arrayname" is defined. When the device creator
+ * sets this property to the desired length of array, further dynamic
+ * properties "arrayname[0]", "arrayname[1]", ... are defined so the
+ * device creator can set the array element values. Setting the
+ * "len-arrayname" property more than once is an error.
+ *
+ * When the array length is set, the @_field member of the device
+ * struct is set to the array length, and @_arrayfield is set to point
+ * to (zero-initialised) memory allocated for the array. For a zero
+ * length array, @_field will be set to 0 and @_arrayfield to NULL.
+ * It is the responsibility of the device deinit code to free the
+ * @_arrayfield memory.
+ */
+#define DEFINE_PROP_ARRAY(_name, _state, _field, \
+ _arrayfield, _arrayprop, _arraytype) { \
+ .name = (PROP_ARRAY_LEN_PREFIX _name), \
+ .info = &(qdev_prop_arraylen), \
+ .offset = offsetof(_state, _field) \
+ + type_check(uint32_t, typeof_field(_state, _field)), \
+ .qtype = QTYPE_QINT, \
+ .arrayinfo = &(_arrayprop), \
+ .arrayfieldsize = sizeof(_arraytype), \
+ .arrayoffset = offsetof(_state, _arrayfield), \
+ }
+
#define DEFINE_PROP_UINT8(_n, _s, _f, _d) \
DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
#define DEFINE_PROP_UINT16(_n, _s, _f, _d) \
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index d77df42b7e..8cd9be434d 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -23,11 +23,12 @@
static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
{
+ DisplaySurface *surface = qemu_console_surface(qxl->vga.con);
+ uint8_t *dst = surface_data(surface);
uint8_t *src;
- uint8_t *dst = ds_get_data(qxl->vga.ds);
int len, i;
- if (is_buffer_shared(qxl->vga.ds->surface)) {
+ if (is_buffer_shared(surface)) {
return;
}
if (!qxl->guest_primary.data) {
@@ -98,6 +99,7 @@ static void qxl_set_rect_to_surface(PCIQXLDevice *qxl, QXLRect *area)
static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
{
VGACommonState *vga = &qxl->vga;
+ DisplaySurface *surface;
int i;
if (qxl->guest_primary.resized) {
@@ -112,8 +114,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.bytes_pp,
qxl->guest_primary.bits_pp);
if (qxl->guest_primary.qxl_stride > 0) {
- qemu_free_displaysurface(vga->ds);
- vga->ds->surface = qemu_create_displaysurface_from
+ surface = qemu_create_displaysurface_from
(qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
qxl->guest_primary.bits_pp,
@@ -121,18 +122,18 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.data,
false);
} else {
- qemu_resize_displaysurface(vga->ds,
- qxl->guest_primary.surface.width,
- qxl->guest_primary.surface.height);
+ surface = qemu_create_displaysurface
+ (qxl->guest_primary.surface.width,
+ qxl->guest_primary.surface.height);
}
- dpy_gfx_resize(vga->ds);
+ dpy_gfx_replace_surface(vga->con, surface);
}
for (i = 0; i < qxl->num_dirty_rects; i++) {
if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
break;
}
qxl_blit(qxl, qxl->dirty+i);
- dpy_gfx_update(vga->ds,
+ dpy_gfx_update(vga->con,
qxl->dirty[i].left, qxl->dirty[i].top,
qxl->dirty[i].right - qxl->dirty[i].left,
qxl->dirty[i].bottom - qxl->dirty[i].top);
@@ -236,7 +237,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
return 1;
}
- if (!dpy_cursor_define_supported(qxl->ssd.ds)) {
+ if (!dpy_cursor_define_supported(qxl->vga.con)) {
return 0;
}
diff --git a/hw/qxl.c b/hw/qxl.c
index ef693486c2..b66b41442a 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -118,8 +118,6 @@ static QXLMode qxl_modes[] = {
QXL_MODE_EX(3200, 2400),
};
-static PCIQXLDevice *qxl0;
-
static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async);
static void qxl_reset_memslots(PCIQXLDevice *d);
@@ -1075,8 +1073,8 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d)
trace_qxl_enter_vga_mode(d->id);
qemu_spice_create_host_primary(&d->ssd);
d->mode = QXL_MODE_VGA;
- dpy_gfx_resize(d->ssd.ds);
vga_dirty_log_start(&d->vga);
+ vga_hw_update();
}
static void qxl_exit_vga_mode(PCIQXLDevice *d)
@@ -1784,7 +1782,7 @@ static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch,
case QXL_MODE_COMPAT:
case QXL_MODE_NATIVE:
qxl_render_update(qxl);
- ppm_save(filename, qxl->ssd.ds->surface, errp);
+ ppm_save(filename, qxl->ssd.ds, errp);
break;
case QXL_MODE_VGA:
vga->screen_dump(vga, filename, cswitch, errp);
@@ -1866,35 +1864,45 @@ static void qxl_vm_change_state_handler(void *opaque, int running,
/* display change listener */
-static void display_update(struct DisplayState *ds, int x, int y, int w, int h)
+static void display_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h)
{
- if (qxl0->mode == QXL_MODE_VGA) {
- qemu_spice_display_update(&qxl0->ssd, x, y, w, h);
+ PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
+
+ if (qxl->mode == QXL_MODE_VGA) {
+ qemu_spice_display_update(&qxl->ssd, x, y, w, h);
}
}
-static void display_resize(struct DisplayState *ds)
+static void display_switch(DisplayChangeListener *dcl,
+ struct DisplaySurface *surface)
{
- if (qxl0->mode == QXL_MODE_VGA) {
- qemu_spice_display_resize(&qxl0->ssd);
+ PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
+
+ qxl->ssd.ds = surface;
+ if (qxl->mode == QXL_MODE_VGA) {
+ qemu_spice_display_switch(&qxl->ssd, surface);
}
}
-static void display_refresh(struct DisplayState *ds)
+static void display_refresh(DisplayChangeListener *dcl)
{
- if (qxl0->mode == QXL_MODE_VGA) {
- qemu_spice_display_refresh(&qxl0->ssd);
+ PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
+
+ if (qxl->mode == QXL_MODE_VGA) {
+ qemu_spice_display_refresh(&qxl->ssd);
} else {
- qemu_mutex_lock(&qxl0->ssd.lock);
- qemu_spice_cursor_refresh_unlocked(&qxl0->ssd);
- qemu_mutex_unlock(&qxl0->ssd.lock);
+ qemu_mutex_lock(&qxl->ssd.lock);
+ qemu_spice_cursor_refresh_unlocked(&qxl->ssd);
+ qemu_mutex_unlock(&qxl->ssd.lock);
}
}
-static DisplayChangeListener display_listener = {
+static DisplayChangeListenerOps display_listener_ops = {
+ .dpy_name = "spice/qxl",
.dpy_gfx_update = display_update,
- .dpy_gfx_resize = display_resize,
- .dpy_refresh = display_refresh,
+ .dpy_gfx_switch = display_switch,
+ .dpy_refresh = display_refresh,
};
static void qxl_init_ramsize(PCIQXLDevice *qxl)
@@ -2055,6 +2063,7 @@ static int qxl_init_primary(PCIDevice *dev)
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
VGACommonState *vga = &qxl->vga;
PortioList *qxl_vga_port_list = g_new(PortioList, 1);
+ DisplayState *ds;
int rc;
qxl->id = 0;
@@ -2065,18 +2074,20 @@ static int qxl_init_primary(PCIDevice *dev)
portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga");
portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
- vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
- qxl_hw_screen_dump, qxl_hw_text_update, qxl);
- qemu_spice_display_init_common(&qxl->ssd, vga->ds);
-
- qxl0 = qxl;
+ vga->con = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
+ qxl_hw_screen_dump, qxl_hw_text_update,
+ qxl);
+ qxl->ssd.con = vga->con,
+ qemu_spice_display_init_common(&qxl->ssd);
rc = qxl_init_common(qxl);
if (rc != 0) {
return rc;
}
- register_displaychangelistener(vga->ds, &display_listener);
+ qxl->ssd.dcl.ops = &display_listener_ops;
+ ds = qemu_console_displaystate(vga->con);
+ register_displaychangelistener(ds, &qxl->ssd.dcl);
return rc;
}
diff --git a/hw/sm501.c b/hw/sm501.c
index 0e019111bb..93a06c90b9 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -454,7 +454,7 @@ static const uint32_t sm501_mem_local_size[] = {
typedef struct SM501State {
/* graphic console status */
- DisplayState *ds;
+ QemuConsole *con;
/* status & internal resources */
hwaddr base;
@@ -1234,9 +1234,9 @@ static draw_hwc_line_func * draw_hwc_line_funcs[] = {
draw_hwc_line_16bgr,
};
-static inline int get_depth_index(DisplayState *s)
+static inline int get_depth_index(DisplaySurface *surface)
{
- switch(ds_get_bits_per_pixel(s)) {
+ switch (surface_bits_per_pixel(surface)) {
default:
case 8:
return 0;
@@ -1245,26 +1245,28 @@ static inline int get_depth_index(DisplayState *s)
case 16:
return 2;
case 32:
- if (is_surface_bgr(s->surface))
- return 4;
- else
- return 3;
+ if (is_surface_bgr(surface)) {
+ return 4;
+ } else {
+ return 3;
+ }
}
}
static void sm501_draw_crt(SM501State * s)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int y;
int width = (s->dc_crt_h_total & 0x00000FFF) + 1;
int height = (s->dc_crt_v_total & 0x00000FFF) + 1;
uint8_t * src = s->local_mem;
int src_bpp = 0;
- int dst_bpp = ds_get_bytes_per_pixel(s->ds) + (ds_get_bits_per_pixel(s->ds) % 8 ? 1 : 0);
+ int dst_bpp = surface_bytes_per_pixel(surface);
uint32_t * palette = (uint32_t *)&s->dc_palette[SM501_DC_CRT_PALETTE
- SM501_DC_PANEL_PALETTE];
uint8_t hwc_palette[3 * 3];
- int ds_depth_index = get_depth_index(s->ds);
+ int ds_depth_index = get_depth_index(surface);
draw_line_func * draw_line = NULL;
draw_hwc_line_func * draw_hwc_line = NULL;
int full_update = 0;
@@ -1312,7 +1314,8 @@ static void sm501_draw_crt(SM501State * s)
/* adjust console size */
if (s->last_width != width || s->last_height != height) {
- qemu_console_resize(s->ds, width, height);
+ qemu_console_resize(s->con, width, height);
+ surface = qemu_console_surface(s->con);
s->last_width = width;
s->last_height = height;
full_update = 1;
@@ -1331,7 +1334,8 @@ static void sm501_draw_crt(SM501State * s)
/* draw line and change status */
if (update) {
- uint8_t * d = &(ds_get_data(s->ds)[y * width * dst_bpp]);
+ uint8_t *d = surface_data(surface);
+ d += y * width * dst_bpp;
/* draw graphics layer */
draw_line(d, src, width, palette);
@@ -1350,7 +1354,7 @@ static void sm501_draw_crt(SM501State * s)
} else {
if (y_start >= 0) {
/* flush to display */
- dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
+ dpy_gfx_update(s->con, 0, y_start, width, y - y_start);
y_start = -1;
}
}
@@ -1361,7 +1365,7 @@ static void sm501_draw_crt(SM501State * s)
/* complete flush to display */
if (y_start >= 0)
- dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
+ dpy_gfx_update(s->con, 0, y_start, width, y - y_start);
/* clear dirty flags */
if (page_min != ~0l) {
@@ -1441,6 +1445,6 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
}
/* create qemu graphic console */
- s->ds = graphic_console_init(sm501_update_display, NULL,
- NULL, NULL, s);
+ s->con = graphic_console_init(sm501_update_display, NULL,
+ NULL, NULL, s);
}
diff --git a/hw/ssd0303.c b/hw/ssd0303.c
index db50909734..68d1f24b06 100644
--- a/hw/ssd0303.c
+++ b/hw/ssd0303.c
@@ -43,7 +43,7 @@ enum ssd0303_cmd {
typedef struct {
I2CSlave i2c;
- DisplayState *ds;
+ QemuConsole *con;
int row;
int col;
int start_line;
@@ -191,6 +191,7 @@ static void ssd0303_event(I2CSlave *i2c, enum i2c_event event)
static void ssd0303_update_display(void *opaque)
{
ssd0303_state *s = (ssd0303_state *)opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
uint8_t *dest;
uint8_t *src;
int x;
@@ -204,7 +205,7 @@ static void ssd0303_update_display(void *opaque)
if (!s->redraw)
return;
- switch (ds_get_bits_per_pixel(s->ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 0:
return;
case 15:
@@ -236,7 +237,7 @@ static void ssd0303_update_display(void *opaque)
colors[0] = colortab + dest_width;
colors[1] = colortab;
}
- dest = ds_get_data(s->ds);
+ dest = surface_data(surface);
for (y = 0; y < 16; y++) {
line = (y + s->start_line) & 63;
src = s->framebuffer + 132 * (line >> 3) + 36;
@@ -252,7 +253,7 @@ static void ssd0303_update_display(void *opaque)
}
}
s->redraw = 0;
- dpy_gfx_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
+ dpy_gfx_update(s->con, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
}
static void ssd0303_invalidate_display(void * opaque)
@@ -287,10 +288,10 @@ static int ssd0303_init(I2CSlave *i2c)
{
ssd0303_state *s = FROM_I2C_SLAVE(ssd0303_state, i2c);
- s->ds = graphic_console_init(ssd0303_update_display,
- ssd0303_invalidate_display,
- NULL, NULL, s);
- qemu_console_resize(s->ds, 96 * MAGNIFY, 16 * MAGNIFY);
+ s->con = graphic_console_init(ssd0303_update_display,
+ ssd0303_invalidate_display,
+ NULL, NULL, s);
+ qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY);
return 0;
}
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index 27b4151994..5cf2f7058f 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -45,7 +45,7 @@ enum ssd0323_mode
typedef struct {
SSISlave ssidev;
- DisplayState *ds;
+ QemuConsole *con;
int cmd_len;
int cmd;
@@ -175,6 +175,7 @@ static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data)
static void ssd0323_update_display(void *opaque)
{
ssd0323_state *s = (ssd0323_state *)opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
uint8_t *dest;
uint8_t *src;
int x;
@@ -189,7 +190,7 @@ static void ssd0323_update_display(void *opaque)
if (!s->redraw)
return;
- switch (ds_get_bits_per_pixel(s->ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 0:
return;
case 15:
@@ -212,7 +213,7 @@ static void ssd0323_update_display(void *opaque)
for (i = 0; i < 16; i++) {
int n;
colors[i] = p;
- switch (ds_get_bits_per_pixel(s->ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 15:
n = i * 2 + (i >> 3);
p[0] = n | (n << 5);
@@ -235,7 +236,7 @@ static void ssd0323_update_display(void *opaque)
p += dest_width;
}
/* TODO: Implement row/column remapping. */
- dest = ds_get_data(s->ds);
+ dest = surface_data(surface);
for (y = 0; y < 64; y++) {
line = y;
src = s->framebuffer + 64 * line;
@@ -260,7 +261,7 @@ static void ssd0323_update_display(void *opaque)
}
}
s->redraw = 0;
- dpy_gfx_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
+ dpy_gfx_update(s->con, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
}
static void ssd0323_invalidate_display(void * opaque)
@@ -336,10 +337,10 @@ static int ssd0323_init(SSISlave *dev)
s->col_end = 63;
s->row_end = 79;
- s->ds = graphic_console_init(ssd0323_update_display,
- ssd0323_invalidate_display,
- NULL, NULL, s);
- qemu_console_resize(s->ds, 128 * MAGNIFY, 64 * MAGNIFY);
+ s->con = graphic_console_init(ssd0323_update_display,
+ ssd0323_invalidate_display,
+ NULL, NULL, s);
+ qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index 0755463a1d..79c971b439 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -125,7 +125,7 @@ struct TC6393xbState {
DeviceState *flash;
ECCState ecc;
- DisplayState *ds;
+ QemuConsole *con;
MemoryRegion vram;
uint16_t *vram_ptr;
uint32_t scr_width, scr_height; /* in pixels */
@@ -433,7 +433,9 @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
{
- switch (ds_get_bits_per_pixel(s->ds)) {
+ DisplaySurface *surface = qemu_console_surface(s->con);
+
+ switch (surface_bits_per_pixel(surface)) {
case 8:
tc6393xb_draw_graphic8(s);
break;
@@ -450,34 +452,37 @@ static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
tc6393xb_draw_graphic32(s);
break;
default:
- printf("tc6393xb: unknown depth %d\n", ds_get_bits_per_pixel(s->ds));
+ printf("tc6393xb: unknown depth %d\n",
+ surface_bits_per_pixel(surface));
return;
}
- dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height);
+ dpy_gfx_update(s->con, 0, 0, s->scr_width, s->scr_height);
}
static void tc6393xb_draw_blank(TC6393xbState *s, int full_update)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int i, w;
uint8_t *d;
if (!full_update)
return;
- w = s->scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
- d = ds_get_data(s->ds);
+ w = s->scr_width * surface_bytes_per_pixel(surface);
+ d = surface_data(surface);
for(i = 0; i < s->scr_height; i++) {
memset(d, 0, w);
- d += ds_get_linesize(s->ds);
+ d += surface_stride(surface);
}
- dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height);
+ dpy_gfx_update(s->con, 0, 0, s->scr_width, s->scr_height);
}
static void tc6393xb_update_display(void *opaque)
{
TC6393xbState *s = opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
int full_update;
if (s->scr_width == 0 || s->scr_height == 0)
@@ -488,8 +493,9 @@ static void tc6393xb_update_display(void *opaque)
s->blanked = s->blank;
full_update = 1;
}
- if (s->scr_width != ds_get_width(s->ds) || s->scr_height != ds_get_height(s->ds)) {
- qemu_console_resize(s->ds, s->scr_width, s->scr_height);
+ if (s->scr_width != surface_width(surface) ||
+ s->scr_height != surface_height(surface)) {
+ qemu_console_resize(s->con, s->scr_width, s->scr_height);
full_update = 1;
}
if (s->blanked)
@@ -577,7 +583,7 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
memory_region_add_subregion(sysmem, base + 0x100000, &s->vram);
s->scr_width = 480;
s->scr_height = 640;
- s->ds = graphic_console_init(tc6393xb_update_display,
+ s->con = graphic_console_init(tc6393xb_update_display,
NULL, /* invalidate */
NULL, /* screen_dump */
NULL, /* text_update */
diff --git a/hw/tc6393xb_template.h b/hw/tc6393xb_template.h
index 4cbbad5dae..154aafd400 100644
--- a/hw/tc6393xb_template.h
+++ b/hw/tc6393xb_template.h
@@ -37,17 +37,18 @@
static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int i;
uint16_t *data_buffer;
uint8_t *data_display;
data_buffer = s->vram_ptr;
- data_display = ds_get_data(s->ds);
+ data_display = surface_data(surface);
for(i = 0; i < s->scr_height; i++) {
#if (BITS == 16)
memcpy(data_display, data_buffer, s->scr_width * 2);
data_buffer += s->scr_width;
- data_display += ds_get_linesize(s->ds);
+ data_display += surface_stride(surface);
#else
int j;
for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) {
diff --git a/hw/tcx.c b/hw/tcx.c
index 896407d865..f1edffd877 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -38,7 +38,7 @@
typedef struct TCXState {
SysBusDevice busdev;
hwaddr addr;
- DisplayState *ds;
+ QemuConsole *con;
uint8_t *vram;
uint32_t *vram24, *cplane;
MemoryRegion vram_mem;
@@ -75,9 +75,11 @@ static void tcx24_set_dirty(TCXState *s)
static void update_palette_entries(TCXState *s, int start, int end)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int i;
- for(i = start; i < end; i++) {
- switch(ds_get_bits_per_pixel(s->ds)) {
+
+ for (i = start; i < end; i++) {
+ switch (surface_bits_per_pixel(surface)) {
default:
case 8:
s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]);
@@ -89,10 +91,11 @@ static void update_palette_entries(TCXState *s, int start, int end)
s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
break;
case 32:
- if (is_surface_bgr(s->ds->surface))
+ if (is_surface_bgr(surface)) {
s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
- else
+ } else {
s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
+ }
break;
}
}
@@ -151,12 +154,13 @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
const uint32_t *cplane,
const uint32_t *s24)
{
+ DisplaySurface *surface = qemu_console_surface(s1->con);
int x, bgr, r, g, b;
uint8_t val, *p8;
uint32_t *p = (uint32_t *)d;
uint32_t dval;
- bgr = is_surface_bgr(s1->ds->surface);
+ bgr = is_surface_bgr(surface);
for(x = 0; x < width; x++, s++, s24++) {
if ((be32_to_cpu(*cplane++) & 0xff000000) == 0x03000000) {
// 24-bit direct, BGR order
@@ -213,23 +217,26 @@ static inline void reset_dirty(TCXState *ts, ram_addr_t page_min,
static void tcx_update_display(void *opaque)
{
TCXState *ts = opaque;
+ DisplaySurface *surface = qemu_console_surface(ts->con);
ram_addr_t page, page_min, page_max;
int y, y_start, dd, ds;
uint8_t *d, *s;
void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width);
- if (ds_get_bits_per_pixel(ts->ds) == 0)
+ if (surface_bits_per_pixel(surface) == 0) {
return;
+ }
+
page = 0;
y_start = -1;
page_min = -1;
page_max = 0;
- d = ds_get_data(ts->ds);
+ d = surface_data(surface);
s = ts->vram;
- dd = ds_get_linesize(ts->ds);
+ dd = surface_stride(surface);
ds = 1024;
- switch (ds_get_bits_per_pixel(ts->ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 32:
f = tcx_draw_line32;
break;
@@ -269,7 +276,7 @@ static void tcx_update_display(void *opaque)
} else {
if (y_start >= 0) {
/* flush to display */
- dpy_gfx_update(ts->ds, 0, y_start,
+ dpy_gfx_update(ts->con, 0, y_start,
ts->width, y - y_start);
y_start = -1;
}
@@ -279,7 +286,7 @@ static void tcx_update_display(void *opaque)
}
if (y_start >= 0) {
/* flush to display */
- dpy_gfx_update(ts->ds, 0, y_start,
+ dpy_gfx_update(ts->con, 0, y_start,
ts->width, y - y_start);
}
/* reset modified pages */
@@ -293,24 +300,27 @@ static void tcx_update_display(void *opaque)
static void tcx24_update_display(void *opaque)
{
TCXState *ts = opaque;
+ DisplaySurface *surface = qemu_console_surface(ts->con);
ram_addr_t page, page_min, page_max, cpage, page24;
int y, y_start, dd, ds;
uint8_t *d, *s;
uint32_t *cptr, *s24;
- if (ds_get_bits_per_pixel(ts->ds) != 32)
+ if (surface_bits_per_pixel(surface) != 32) {
return;
+ }
+
page = 0;
page24 = ts->vram24_offset;
cpage = ts->cplane_offset;
y_start = -1;
page_min = -1;
page_max = 0;
- d = ds_get_data(ts->ds);
+ d = surface_data(surface);
s = ts->vram;
s24 = ts->vram24;
cptr = ts->cplane;
- dd = ds_get_linesize(ts->ds);
+ dd = surface_stride(surface);
ds = 1024;
for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
@@ -345,7 +355,7 @@ static void tcx24_update_display(void *opaque)
} else {
if (y_start >= 0) {
/* flush to display */
- dpy_gfx_update(ts->ds, 0, y_start,
+ dpy_gfx_update(ts->con, 0, y_start,
ts->width, y - y_start);
y_start = -1;
}
@@ -357,7 +367,7 @@ static void tcx24_update_display(void *opaque)
}
if (y_start >= 0) {
/* flush to display */
- dpy_gfx_update(ts->ds, 0, y_start,
+ dpy_gfx_update(ts->con, 0, y_start,
ts->width, y - y_start);
}
/* reset modified pages */
@@ -371,7 +381,7 @@ static void tcx_invalidate_display(void *opaque)
TCXState *s = opaque;
tcx_set_dirty(s);
- qemu_console_resize(s->ds, s->width, s->height);
+ qemu_console_resize(s->con, s->width, s->height);
}
static void tcx24_invalidate_display(void *opaque)
@@ -380,7 +390,7 @@ static void tcx24_invalidate_display(void *opaque)
tcx_set_dirty(s);
tcx24_set_dirty(s);
- qemu_console_resize(s->ds, s->width, s->height);
+ qemu_console_resize(s->con, s->width, s->height);
}
static int vmstate_tcx_post_load(void *opaque, int version_id)
@@ -558,21 +568,21 @@ static int tcx_init1(SysBusDevice *dev)
&s->vram_mem, vram_offset, size);
sysbus_init_mmio(dev, &s->vram_cplane);
- s->ds = graphic_console_init(tcx24_update_display,
- tcx24_invalidate_display,
- tcx24_screen_dump, NULL, s);
+ s->con = graphic_console_init(tcx24_update_display,
+ tcx24_invalidate_display,
+ tcx24_screen_dump, NULL, s);
} else {
/* THC 8 bit (dummy) */
memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
TCX_THC_NREGS_8);
sysbus_init_mmio(dev, &s->thc8);
- s->ds = graphic_console_init(tcx_update_display,
- tcx_invalidate_display,
- tcx_screen_dump, NULL, s);
+ s->con = graphic_console_init(tcx_update_display,
+ tcx_invalidate_display,
+ tcx_screen_dump, NULL, s);
}
- qemu_console_resize(s->ds, s->width, s->height);
+ qemu_console_resize(s->con, s->width, s->height);
return 0;
}
diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 4aa62bf35e..02356d4d58 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -135,8 +135,9 @@ int isa_vga_mm_init(hwaddr vram_base,
vga_common_init(&s->vga);
vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
- s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
- s->vga.screen_dump, s->vga.text_update, s);
+ s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate,
+ s->vga.screen_dump, s->vga.text_update,
+ s);
vga_init_vbe(&s->vga, address_space);
return 0;
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index ffad5226fd..9e293217d0 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -62,8 +62,8 @@ static int vga_initfn(ISADevice *dev)
isa_mem_base + 0x000a0000,
vga_io_memory, 1);
memory_region_set_coalescing(vga_io_memory);
- s->ds = graphic_console_init(s->update, s->invalidate,
- s->screen_dump, s->text_update, s);
+ s->con = graphic_console_init(s->update, s->invalidate,
+ s->screen_dump, s->text_update, s);
vga_init_vbe(s, isa_address_space(dev));
/* ROM BIOS */
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 18018ff1c3..05fa9bcb64 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -150,8 +150,8 @@ static int pci_std_vga_initfn(PCIDevice *dev)
vga_common_init(s);
vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true);
- s->ds = graphic_console_init(s->update, s->invalidate,
- s->screen_dump, s->text_update, s);
+ s->con = graphic_console_init(s->update, s->invalidate,
+ s->screen_dump, s->text_update, s);
/* XXX: VGA_RAM_SIZE must be a power of two */
pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
diff --git a/hw/vga.c b/hw/vga.c
index 2213bc1a88..59bfb220f5 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1174,9 +1174,9 @@ static int update_basic_params(VGACommonState *s)
#define NB_DEPTHS 7
-static inline int get_depth_index(DisplayState *s)
+static inline int get_depth_index(DisplaySurface *s)
{
- switch(ds_get_bits_per_pixel(s)) {
+ switch (surface_bits_per_pixel(s)) {
default:
case 8:
return 0;
@@ -1185,10 +1185,11 @@ static inline int get_depth_index(DisplayState *s)
case 16:
return 2;
case 32:
- if (is_surface_bgr(s->surface))
+ if (is_surface_bgr(s)) {
return 4;
- else
+ } else {
return 3;
+ }
}
}
@@ -1294,6 +1295,7 @@ static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
*/
static void vga_draw_text(VGACommonState *s, int full_update)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
int cx_min, cx_max, linesize, x_incr, line, line1;
uint32_t offset, fgcol, bgcol, v, cursor_offset;
@@ -1345,8 +1347,9 @@ static void vga_draw_text(VGACommonState *s, int full_update)
cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
s->last_scr_width = width * cw;
s->last_scr_height = height * cheight;
- qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
- dpy_text_resize(s->ds, width, height);
+ qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
+ surface = qemu_console_surface(s->con);
+ dpy_text_resize(s->con, width, height);
s->last_depth = 0;
s->last_width = width;
s->last_height = height;
@@ -1355,10 +1358,10 @@ static void vga_draw_text(VGACommonState *s, int full_update)
full_update = 1;
}
s->rgb_to_pixel =
- rgb_to_pixel_dup_table[get_depth_index(s->ds)];
+ rgb_to_pixel_dup_table[get_depth_index(surface)];
full_update |= update_palette16(s);
palette = s->last_palette;
- x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
+ x_incr = cw * surface_bytes_per_pixel(surface);
if (full_update) {
s->full_update_text = 1;
@@ -1389,15 +1392,15 @@ static void vga_draw_text(VGACommonState *s, int full_update)
s->cursor_visible_phase = !s->cursor_visible_phase;
}
- depth_index = get_depth_index(s->ds);
+ depth_index = get_depth_index(surface);
if (cw == 16)
vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
else
vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
- dest = ds_get_data(s->ds);
- linesize = ds_get_linesize(s->ds);
+ dest = surface_data(surface);
+ linesize = surface_stride(surface);
ch_attr_ptr = s->last_ch_attr;
line = 0;
offset = s->start_addr * 4;
@@ -1465,7 +1468,7 @@ static void vga_draw_text(VGACommonState *s, int full_update)
ch_attr_ptr++;
}
if (cx_max != -1) {
- dpy_gfx_update(s->ds, cx_min * cw, cy * cheight,
+ dpy_gfx_update(s->con, cx_min * cw, cy * cheight,
(cx_max - cx_min + 1) * cw, cheight);
}
dest += linesize * cheight;
@@ -1636,6 +1639,7 @@ void vga_dirty_log_stop(VGACommonState *s)
*/
static void vga_draw_graphic(VGACommonState *s, int full_update)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int y1, y, update, linesize, y_start, double_scan, mask, depth;
int width, height, shift_control, line_offset, bwidth, bits;
ram_addr_t page0, page1, page_min, page_max;
@@ -1691,13 +1695,13 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
height != s->last_height ||
s->last_depth != depth) {
if (depth == 32 || (depth == 16 && !byteswap)) {
- qemu_free_displaysurface(s->ds);
- s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
- s->line_offset,
+ surface = qemu_create_displaysurface_from(disp_width,
+ height, depth, s->line_offset,
s->vram_ptr + (s->start_addr * 4), byteswap);
- dpy_gfx_resize(s->ds);
+ dpy_gfx_replace_surface(s->con, surface);
} else {
- qemu_console_resize(s->ds, disp_width, height);
+ qemu_console_resize(s->con, disp_width, height);
+ surface = qemu_console_surface(s->con);
}
s->last_scr_width = disp_width;
s->last_scr_height = height;
@@ -1706,19 +1710,18 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
s->last_line_offset = s->line_offset;
s->last_depth = depth;
full_update = 1;
- } else if (is_buffer_shared(s->ds->surface) &&
- (full_update || ds_get_data(s->ds) != s->vram_ptr
+ } else if (is_buffer_shared(surface) &&
+ (full_update || surface_data(surface) != s->vram_ptr
+ (s->start_addr * 4))) {
- qemu_free_displaysurface(s->ds);
- s->ds->surface = qemu_create_displaysurface_from(disp_width,
- height, depth,
- s->line_offset,
+ DisplaySurface *surface;
+ surface = qemu_create_displaysurface_from(disp_width,
+ height, depth, s->line_offset,
s->vram_ptr + (s->start_addr * 4), byteswap);
- dpy_gfx_setdata(s->ds);
+ dpy_gfx_replace_surface(s->con, surface);
}
s->rgb_to_pixel =
- rgb_to_pixel_dup_table[get_depth_index(s->ds)];
+ rgb_to_pixel_dup_table[get_depth_index(surface)];
if (shift_control == 0) {
full_update |= update_palette16(s);
@@ -1767,10 +1770,12 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
break;
}
}
- vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
+ vga_draw_line = vga_draw_line_table[v * NB_DEPTHS +
+ get_depth_index(surface)];
- if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
+ if (!is_buffer_shared(surface) && s->cursor_invalidate) {
s->cursor_invalidate(s);
+ }
line_offset = s->line_offset;
#if 0
@@ -1783,8 +1788,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
y_start = -1;
page_min = -1;
page_max = 0;
- d = ds_get_data(s->ds);
- linesize = ds_get_linesize(s->ds);
+ d = surface_data(surface);
+ linesize = surface_stride(surface);
y1 = 0;
for(y = 0; y < height; y++) {
addr = addr1;
@@ -1811,7 +1816,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
page_min = page0;
if (page1 > page_max)
page_max = page1;
- if (!(is_buffer_shared(s->ds->surface))) {
+ if (!(is_buffer_shared(surface))) {
vga_draw_line(s, d, s->vram_ptr + addr, width);
if (s->cursor_draw_line)
s->cursor_draw_line(s, d, y);
@@ -1819,7 +1824,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
} else {
if (y_start >= 0) {
/* flush to display */
- dpy_gfx_update(s->ds, 0, y_start,
+ dpy_gfx_update(s->con, 0, y_start,
disp_width, y - y_start);
y_start = -1;
}
@@ -1840,7 +1845,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
}
if (y_start >= 0) {
/* flush to display */
- dpy_gfx_update(s->ds, 0, y_start,
+ dpy_gfx_update(s->con, 0, y_start,
disp_width, y - y_start);
}
/* reset modified pages */
@@ -1855,6 +1860,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
static void vga_draw_blank(VGACommonState *s, int full_update)
{
+ DisplaySurface *surface = qemu_console_surface(s->con);
int i, w, val;
uint8_t *d;
@@ -1864,18 +1870,19 @@ static void vga_draw_blank(VGACommonState *s, int full_update)
return;
s->rgb_to_pixel =
- rgb_to_pixel_dup_table[get_depth_index(s->ds)];
- if (ds_get_bits_per_pixel(s->ds) == 8)
+ rgb_to_pixel_dup_table[get_depth_index(surface)];
+ if (surface_bits_per_pixel(surface) == 8) {
val = s->rgb_to_pixel(0, 0, 0);
- else
+ } else {
val = 0;
- w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
- d = ds_get_data(s->ds);
+ }
+ w = s->last_scr_width * surface_bytes_per_pixel(surface);
+ d = surface_data(surface);
for(i = 0; i < s->last_scr_height; i++) {
memset(d, val, w);
- d += ds_get_linesize(s->ds);
+ d += surface_stride(surface);
}
- dpy_gfx_update(s->ds, 0, 0,
+ dpy_gfx_update(s->con, 0, 0,
s->last_scr_width, s->last_scr_height);
}
@@ -1886,11 +1893,12 @@ static void vga_draw_blank(VGACommonState *s, int full_update)
static void vga_update_display(void *opaque)
{
VGACommonState *s = opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
int full_update, graphic_mode;
qemu_flush_coalesced_mmio_buffer();
- if (ds_get_bits_per_pixel(s->ds) == 0) {
+ if (surface_bits_per_pixel(surface) == 0) {
/* nothing to do */
} else {
full_update = 0;
@@ -2064,8 +2072,8 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
cw != s->last_cw || cheight != s->last_ch) {
s->last_scr_width = width * cw;
s->last_scr_height = height * cheight;
- qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
- dpy_text_resize(s->ds, width, height);
+ qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
+ dpy_text_resize(s->con, width, height);
s->last_depth = 0;
s->last_width = width;
s->last_height = height;
@@ -2090,11 +2098,11 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
- dpy_text_cursor(s->ds,
+ dpy_text_cursor(s->con,
TEXTMODE_X(cursor_offset),
TEXTMODE_Y(cursor_offset));
else
- dpy_text_cursor(s->ds, -1, -1);
+ dpy_text_cursor(s->con, -1, -1);
s->cursor_offset = cursor_offset;
s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
@@ -2107,7 +2115,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
for (i = 0; i < size; src ++, dst ++, i ++)
console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
- dpy_text_update(s->ds, 0, 0, width, height);
+ dpy_text_update(s->con, 0, 0, width, height);
} else {
c_max = 0;
@@ -2130,7 +2138,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
if (c_min <= c_max) {
i = TEXTMODE_Y(c_min);
- dpy_text_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
+ dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
}
}
@@ -2155,8 +2163,8 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
/* Display a message */
s->last_width = 60;
s->last_height = height = 3;
- dpy_text_cursor(s->ds, -1, -1);
- dpy_text_resize(s->ds, s->last_width, height);
+ dpy_text_cursor(s->con, -1, -1);
+ dpy_text_resize(s->con, s->last_width, height);
for (dst = chardata, i = 0; i < s->last_width * height; i ++)
console_write_ch(dst ++, ' ');
@@ -2167,7 +2175,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
for (i = 0; i < size; i ++)
console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
- dpy_text_update(s->ds, 0, 0, s->last_width, height);
+ dpy_text_update(s->con, 0, 0, s->last_width, height);
}
static uint64_t vga_mem_read(void *opaque, hwaddr addr,
@@ -2439,10 +2447,11 @@ static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
Error **errp)
{
VGACommonState *s = opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
if (cswitch) {
vga_invalidate_display(s);
}
vga_hw_update();
- ppm_save(filename, s->ds->surface, errp);
+ ppm_save(filename, surface, errp);
}
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 8d496ea9bf..260f7d6948 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -132,7 +132,7 @@ typedef struct VGACommonState {
uint32_t vbe_bank_mask;
int vbe_mapped;
/* display refresh support */
- DisplayState *ds;
+ QemuConsole *con;
uint32_t font_offsets[2];
int graphic_mode;
uint8_t shift_control;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index db2f187e56..5b9ce8f96b 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -57,9 +57,6 @@ struct vmsvga_state_s {
int new_height;
uint32_t guest;
uint32_t svgaid;
- uint32_t wred;
- uint32_t wgreen;
- uint32_t wblue;
int syncing;
MemoryRegion fifo_ram;
@@ -289,6 +286,7 @@ enum {
static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
int x, int y, int w, int h)
{
+ DisplaySurface *surface = qemu_console_surface(s->vga.con);
int line;
int bypl;
int width;
@@ -305,11 +303,11 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
fprintf(stderr, "%s: update w was < 0 (%d)\n", __func__, w);
w = 0;
}
- if (x + w > ds_get_width(s->vga.ds)) {
+ if (x + w > surface_width(surface)) {
fprintf(stderr, "%s: update width too large x: %d, w: %d\n",
__func__, x, w);
- x = MIN(x, ds_get_width(s->vga.ds));
- w = ds_get_width(s->vga.ds) - x;
+ x = MIN(x, surface_width(surface));
+ w = surface_width(surface) - x;
}
if (y < 0) {
@@ -321,23 +319,23 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
fprintf(stderr, "%s: update h was < 0 (%d)\n", __func__, h);
h = 0;
}
- if (y + h > ds_get_height(s->vga.ds)) {
+ if (y + h > surface_height(surface)) {
fprintf(stderr, "%s: update height too large y: %d, h: %d\n",
__func__, y, h);
- y = MIN(y, ds_get_height(s->vga.ds));
- h = ds_get_height(s->vga.ds) - y;
+ y = MIN(y, surface_height(surface));
+ h = surface_height(surface) - y;
}
- bypl = ds_get_linesize(s->vga.ds);
- width = ds_get_bytes_per_pixel(s->vga.ds) * w;
- start = ds_get_bytes_per_pixel(s->vga.ds) * x + bypl * y;
+ bypl = surface_stride(surface);
+ width = surface_bytes_per_pixel(surface) * w;
+ start = surface_bytes_per_pixel(surface) * x + bypl * y;
src = s->vga.vram_ptr + start;
- dst = ds_get_data(s->vga.ds) + start;
+ dst = surface_data(surface) + start;
for (line = h; line > 0; line--, src += bypl, dst += bypl) {
memcpy(dst, src, width);
}
- dpy_gfx_update(s->vga.ds, x, y, w, h);
+ dpy_gfx_update(s->vga.con, x, y, w, h);
}
static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
@@ -373,9 +371,10 @@ static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s)
static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
int x0, int y0, int x1, int y1, int w, int h)
{
+ DisplaySurface *surface = qemu_console_surface(s->vga.con);
uint8_t *vram = s->vga.vram_ptr;
- int bypl = ds_get_linesize(s->vga.ds);
- int bypp = ds_get_bytes_per_pixel(s->vga.ds);
+ int bypl = surface_stride(surface);
+ int bypp = surface_bytes_per_pixel(surface);
int width = bypp * w;
int line = h;
uint8_t *ptr[2];
@@ -402,8 +401,9 @@ static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
uint32_t c, int x, int y, int w, int h)
{
- int bypl = ds_get_linesize(s->vga.ds);
- int width = ds_get_bytes_per_pixel(s->vga.ds) * w;
+ DisplaySurface *surface = qemu_console_surface(s->vga.con);
+ int bypl = surface_stride(surface);
+ int width = surface_bytes_per_pixel(surface) * w;
int line = h;
int column;
uint8_t *fst;
@@ -416,14 +416,14 @@ static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
col[2] = c >> 16;
col[3] = c >> 24;
- fst = s->vga.vram_ptr + ds_get_bytes_per_pixel(s->vga.ds) * x + bypl * y;
+ fst = s->vga.vram_ptr + surface_bytes_per_pixel(surface) * x + bypl * y;
if (line--) {
dst = fst;
src = col;
for (column = width; column > 0; column--) {
*(dst++) = *(src++);
- if (src - col == ds_get_bytes_per_pixel(s->vga.ds)) {
+ if (src - col == surface_bytes_per_pixel(surface)) {
src = col;
}
}
@@ -490,7 +490,7 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
qc = cursor_builtin_left_ptr();
}
- dpy_cursor_define(s->vga.ds, qc);
+ dpy_cursor_define(s->vga.con, qc);
cursor_put(qc);
}
#endif
@@ -720,6 +720,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
{
uint32_t caps;
struct vmsvga_state_s *s = opaque;
+ DisplaySurface *surface = qemu_console_surface(s->vga.con);
switch (s->index) {
case SVGA_REG_ID:
@@ -729,10 +730,10 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
return s->enable;
case SVGA_REG_WIDTH:
- return ds_get_width(s->vga.ds);
+ return surface_width(surface);
case SVGA_REG_HEIGHT:
- return ds_get_height(s->vga.ds);
+ return surface_height(surface);
case SVGA_REG_MAX_WIDTH:
return SVGA_MAX_WIDTH;
@@ -750,13 +751,13 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
return 0x0;
case SVGA_REG_RED_MASK:
- return s->wred;
+ return surface->pf.rmask;
case SVGA_REG_GREEN_MASK:
- return s->wgreen;
+ return surface->pf.gmask;
case SVGA_REG_BLUE_MASK:
- return s->wblue;
+ return surface->pf.bmask;
case SVGA_REG_BYTES_PER_LINE:
return s->bypp * s->new_width;
@@ -785,7 +786,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
caps |= SVGA_CAP_RECT_FILL;
#endif
#ifdef HW_MOUSE_ACCEL
- if (dpy_cursor_define_supported(s->vga.ds)) {
+ if (dpy_cursor_define_supported(s->vga.con)) {
caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 |
SVGA_CAP_CURSOR_BYPASS;
}
@@ -947,7 +948,7 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
s->cursor.on &= (value != SVGA_CURSOR_ON_HIDE);
#ifdef HW_MOUSE_ACCEL
if (value <= SVGA_CURSOR_ON_SHOW) {
- dpy_mouse_set(s->vga.ds, s->cursor.x, s->cursor.y, s->cursor.on);
+ dpy_mouse_set(s->vga.con, s->cursor.x, s->cursor.y, s->cursor.on);
}
#endif
break;
@@ -982,9 +983,11 @@ static void vmsvga_bios_write(void *opaque, uint32_t address, uint32_t data)
static inline void vmsvga_check_size(struct vmsvga_state_s *s)
{
- if (s->new_width != ds_get_width(s->vga.ds) ||
- s->new_height != ds_get_height(s->vga.ds)) {
- qemu_console_resize(s->vga.ds, s->new_width, s->new_height);
+ DisplaySurface *surface = qemu_console_surface(s->vga.con);
+
+ if (s->new_width != surface_width(surface) ||
+ s->new_height != surface_height(surface)) {
+ qemu_console_resize(s->vga.con, s->new_width, s->new_height);
s->invalidated = 1;
}
}
@@ -992,6 +995,7 @@ static inline void vmsvga_check_size(struct vmsvga_state_s *s)
static void vmsvga_update_display(void *opaque)
{
struct vmsvga_state_s *s = opaque;
+ DisplaySurface *surface = qemu_console_surface(s->vga.con);
bool dirty = false;
if (!s->enable) {
@@ -1011,19 +1015,19 @@ static void vmsvga_update_display(void *opaque)
if (memory_region_is_logging(&s->vga.vram)) {
vga_sync_dirty_bitmap(&s->vga);
dirty = memory_region_get_dirty(&s->vga.vram, 0,
- ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds),
+ surface_stride(surface) * surface_height(surface),
DIRTY_MEMORY_VGA);
}
if (s->invalidated || dirty) {
s->invalidated = 0;
- memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr,
- ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds));
- dpy_gfx_update(s->vga.ds, 0, 0,
- ds_get_width(s->vga.ds), ds_get_height(s->vga.ds));
+ memcpy(surface_data(surface), s->vga.vram_ptr,
+ surface_stride(surface) * surface_height(surface));
+ dpy_gfx_update(s->vga.con, 0, 0,
+ surface_width(surface), surface_height(surface));
}
if (dirty) {
memory_region_reset_dirty(&s->vga.vram, 0,
- ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds),
+ surface_stride(surface) * surface_height(surface),
DIRTY_MEMORY_VGA);
}
}
@@ -1063,17 +1067,19 @@ static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch,
Error **errp)
{
struct vmsvga_state_s *s = opaque;
+ DisplaySurface *surface = qemu_console_surface(s->vga.con);
+
if (!s->enable) {
s->vga.screen_dump(&s->vga, filename, cswitch, errp);
return;
}
- if (ds_get_bits_per_pixel(s->vga.ds) == 32) {
+ if (surface_bits_per_pixel(surface) == 32) {
DisplaySurface *ds = qemu_create_displaysurface_from(
- ds_get_width(s->vga.ds),
- ds_get_height(s->vga.ds),
+ surface_width(surface),
+ surface_height(surface),
32,
- ds_get_linesize(s->vga.ds),
+ surface_stride(surface),
s->vga.vram_ptr, false);
ppm_save(filename, ds, errp);
g_free(ds);
@@ -1143,14 +1149,16 @@ static const VMStateDescription vmstate_vmware_vga = {
static void vmsvga_init(struct vmsvga_state_s *s,
MemoryRegion *address_space, MemoryRegion *io)
{
+ DisplaySurface *surface;
+
s->scratch_size = SVGA_SCRATCH_SIZE;
s->scratch = g_malloc(s->scratch_size * 4);
- s->vga.ds = graphic_console_init(vmsvga_update_display,
- vmsvga_invalidate_display,
- vmsvga_screen_dump,
- vmsvga_text_update, s);
-
+ s->vga.con = graphic_console_init(vmsvga_update_display,
+ vmsvga_invalidate_display,
+ vmsvga_screen_dump,
+ vmsvga_text_update, s);
+ surface = qemu_console_surface(s->vga.con);
s->fifo_size = SVGA_FIFO_SIZE;
memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size);
@@ -1162,11 +1170,8 @@ static void vmsvga_init(struct vmsvga_state_s *s,
vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
/* Save some values here in case they are changed later.
* This is suspicious and needs more though why it is needed. */
- s->depth = ds_get_bits_per_pixel(s->vga.ds);
- s->bypp = ds_get_bytes_per_pixel(s->vga.ds);
- s->wred = ds_get_rmask(s->vga.ds);
- s->wgreen = ds_get_gmask(s->vga.ds);
- s->wblue = ds_get_bmask(s->vga.ds);
+ s->depth = surface_bits_per_pixel(surface);
+ s->bypp = surface_bytes_per_pixel(surface);
}
static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, unsigned size)
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 3462ded619..7c46a2fa1e 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -54,7 +54,7 @@
struct common {
struct XenDevice xendev; /* must be first */
void *page;
- DisplayState *ds;
+ QemuConsole *con;
};
struct XenInput {
@@ -318,8 +318,9 @@ static void xenfb_mouse_event(void *opaque,
int dx, int dy, int dz, int button_state)
{
struct XenInput *xenfb = opaque;
- int dw = ds_get_width(xenfb->c.ds);
- int dh = ds_get_height(xenfb->c.ds);
+ DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
+ int dw = surface_width(surface);
+ int dh = surface_height(surface);
int i;
if (xenfb->abs_pointer_wanted)
@@ -353,16 +354,9 @@ static int input_initialise(struct XenDevice *xendev)
struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
int rc;
- if (!in->c.ds) {
- char *vfb = xenstore_read_str(NULL, "device/vfb");
- if (vfb == NULL) {
- /* there is no vfb, run vkbd on its own */
- in->c.ds = get_displaystate();
- } else {
- g_free(vfb);
- xen_be_printf(xendev, 1, "ds not set (yet)\n");
- return -1;
- }
+ if (!in->c.con) {
+ xen_be_printf(xendev, 1, "ds not set (yet)\n");
+ return -1;
}
rc = common_bind(&in->c);
@@ -615,12 +609,13 @@ static int xenfb_configure_fb(struct XenFB *xenfb, size_t fb_len_lim,
*/
static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
{
+ DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
int line, oops = 0;
- int bpp = ds_get_bits_per_pixel(xenfb->c.ds);
- int linesize = ds_get_linesize(xenfb->c.ds);
- uint8_t *data = ds_get_data(xenfb->c.ds);
+ int bpp = surface_bits_per_pixel(surface);
+ int linesize = surface_stride(surface);
+ uint8_t *data = surface_data(surface);
- if (!is_buffer_shared(xenfb->c.ds->surface)) {
+ if (!is_buffer_shared(surface)) {
switch (xenfb->depth) {
case 8:
if (bpp == 16) {
@@ -648,10 +643,10 @@ static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n",
__FUNCTION__, xenfb->depth, bpp);
- dpy_gfx_update(xenfb->c.ds, x, y, w, h);
+ dpy_gfx_update(xenfb->c.con, x, y, w, h);
}
-#ifdef XENFB_TYPE_REFRESH_PERIOD
+#if 0 /* def XENFB_TYPE_REFRESH_PERIOD */
static int xenfb_queue_full(struct XenFB *xenfb)
{
struct xenfb_page *page = xenfb->c.page;
@@ -703,13 +698,14 @@ static void xenfb_send_refresh_period(struct XenFB *xenfb, int period)
static void xenfb_update(void *opaque)
{
struct XenFB *xenfb = opaque;
+ DisplaySurface *surface;
int i;
if (xenfb->c.xendev.be_state != XenbusStateConnected)
return;
if (xenfb->feature_update) {
-#ifdef XENFB_TYPE_REFRESH_PERIOD
+#if 0 /* XENFB_TYPE_REFRESH_PERIOD */
struct DisplayChangeListener *l;
int period = 99999999;
int idle = 1;
@@ -753,21 +749,20 @@ static void xenfb_update(void *opaque)
case 16:
case 32:
/* console.c supported depth -> buffer can be used directly */
- qemu_free_displaysurface(xenfb->c.ds);
- xenfb->c.ds->surface = qemu_create_displaysurface_from
+ surface = qemu_create_displaysurface_from
(xenfb->width, xenfb->height, xenfb->depth,
xenfb->row_stride, xenfb->pixels + xenfb->offset,
false);
break;
default:
/* we must convert stuff */
- qemu_resize_displaysurface(xenfb->c.ds, xenfb->width, xenfb->height);
+ surface = qemu_create_displaysurface(xenfb->width, xenfb->height);
break;
}
+ dpy_gfx_replace_surface(xenfb->c.con, surface);
xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n",
xenfb->width, xenfb->height, xenfb->depth,
- is_buffer_shared(xenfb->c.ds->surface) ? " (shared)" : "");
- dpy_gfx_resize(xenfb->c.ds);
+ is_buffer_shared(surface) ? " (shared)" : "");
xenfb->up_fullscreen = 1;
}
@@ -1009,16 +1004,16 @@ wait_more:
/* vfb */
fb = container_of(xfb, struct XenFB, c.xendev);
- fb->c.ds = graphic_console_init(xenfb_update,
- xenfb_invalidate,
- NULL,
- NULL,
- fb);
+ fb->c.con = graphic_console_init(xenfb_update,
+ xenfb_invalidate,
+ NULL,
+ NULL,
+ fb);
fb->have_console = 1;
/* vkbd */
in = container_of(xin, struct XenInput, c.xendev);
- in->c.ds = fb->c.ds;
+ in->c.con = fb->c.con;
/* retry ->init() */
xen_be_check_state(xin);
diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c
index 6c21b9668b..b2397f4a42 100644
--- a/hw/xilinx_spips.c
+++ b/hw/xilinx_spips.c
@@ -115,6 +115,19 @@
#define SNOOP_NONE 0xFE
#define SNOOP_STRIPING 0
+typedef enum {
+ READ = 0x3,
+ FAST_READ = 0xb,
+ DOR = 0x3b,
+ QOR = 0x6b,
+ DIOR = 0xbb,
+ QIOR = 0xeb,
+
+ PP = 0x2,
+ DPP = 0xa2,
+ QPP = 0x32,
+} FlashCMD;
+
typedef struct {
SysBusDevice busdev;
MemoryRegion iomem;
@@ -141,10 +154,15 @@ typedef struct {
hwaddr lqspi_cached_addr;
} XilinxSPIPS;
+#define TYPE_XILINX_SPIPS "xilinx,spips"
+
+#define XILINX_SPIPS(obj) \
+ OBJECT_CHECK(XilinxSPIPS, (obj), TYPE_XILINX_SPIPS)
+
static inline int num_effective_busses(XilinxSPIPS *s)
{
- return (s->regs[R_LQSPI_STS] & LQSPI_CFG_SEP_BUS &&
- s->regs[R_LQSPI_STS] & LQSPI_CFG_TWO_MEM) ? s->num_busses : 1;
+ return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS &&
+ s->regs[R_LQSPI_CFG] & LQSPI_CFG_TWO_MEM) ? s->num_busses : 1;
}
static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
@@ -197,7 +215,7 @@ static void xilinx_spips_update_ixr(XilinxSPIPS *s)
static void xilinx_spips_reset(DeviceState *d)
{
- XilinxSPIPS *s = DO_UPCAST(XilinxSPIPS, busdev.qdev, d);
+ XilinxSPIPS *s = XILINX_SPIPS(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -251,15 +269,19 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
switch (s->snoop_state) {
case (SNOOP_CHECKING):
switch (tx) { /* new instruction code */
- case 0x0b: /* dual/quad output read DOR/QOR */
- case 0x6b:
- s->snoop_state = 4;
+ case READ: /* 3 address bytes, no dummy bytes/cycles */
+ case PP:
+ case DPP:
+ case QPP:
+ s->snoop_state = 3;
break;
- /* FIXME: these vary between vendor - set to spansion */
- case 0xbb: /* high performance dual read DIOR */
+ case FAST_READ: /* 3 address bytes, 1 dummy byte */
+ case DOR:
+ case QOR:
+ case DIOR: /* FIXME: these vary between vendor - set to spansion */
s->snoop_state = 4;
break;
- case 0xeb: /* high performance quad read QIOR */
+ case QIOR: /* 3 address bytes, 2 dummy bytes */
s->snoop_state = 6;
break;
default:
@@ -483,9 +505,10 @@ static const MemoryRegionOps lqspi_ops = {
}
};
-static int xilinx_spips_init(SysBusDevice *dev)
+static void xilinx_spips_realize(DeviceState *dev, Error **errp)
{
- XilinxSPIPS *s = FROM_SYSBUS(typeof(*s), dev);
+ XilinxSPIPS *s = XILINX_SPIPS(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
int i;
DB_PRINT("inited device model\n");
@@ -494,31 +517,29 @@ static int xilinx_spips_init(SysBusDevice *dev)
for (i = 0; i < s->num_busses; ++i) {
char bus_name[16];
snprintf(bus_name, 16, "spi%d", i);
- s->spi[i] = ssi_create_bus(&dev->qdev, bus_name);
+ s->spi[i] = ssi_create_bus(dev, bus_name);
}
- s->cs_lines = g_new(qemu_irq, s->num_cs * s->num_busses);
+ s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses);
ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[0]);
ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[1]);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
for (i = 0; i < s->num_cs * s->num_busses; ++i) {
- sysbus_init_irq(dev, &s->cs_lines[i]);
+ sysbus_init_irq(sbd, &s->cs_lines[i]);
}
memory_region_init_io(&s->iomem, &spips_ops, s, "spi", R_MAX*4);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
memory_region_init_io(&s->mmlqspi, &lqspi_ops, s, "lqspi",
(1 << LQSPI_ADDRESS_BITS) * 2);
- sysbus_init_mmio(dev, &s->mmlqspi);
+ sysbus_init_mmio(sbd, &s->mmlqspi);
s->irqline = -1;
s->lqspi_cached_addr = ~0ULL;
fifo8_create(&s->rx_fifo, RXFF_A);
fifo8_create(&s->tx_fifo, TXFF_A);
-
- return 0;
}
static int xilinx_spips_post_load(void *opaque, int version_id)
@@ -552,16 +573,15 @@ static Property xilinx_spips_properties[] = {
static void xilinx_spips_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
- sdc->init = xilinx_spips_init;
+ dc->realize = xilinx_spips_realize;
dc->reset = xilinx_spips_reset;
dc->props = xilinx_spips_properties;
dc->vmsd = &vmstate_xilinx_spips;
}
static const TypeInfo xilinx_spips_info = {
- .name = "xilinx,spips",
+ .name = TYPE_XILINX_SPIPS,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(XilinxSPIPS),
.class_init = xilinx_spips_class_init,
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 5e137084b5..7754ee2fcc 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -442,4 +442,10 @@ int64_t pow2floor(int64_t value);
int uleb128_encode_small(uint8_t *out, uint32_t n);
int uleb128_decode_small(const uint8_t *in, uint32_t *n);
+/*
+ * Hexdump a buffer to a file. An optional string prefix is added to every line
+ */
+
+void hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
+
#endif
diff --git a/include/ui/console.h b/include/ui/console.h
index a37cf65602..a234c72d2e 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -147,31 +147,43 @@ void cursor_set_mono(QEMUCursor *c,
void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *mask);
void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask);
-struct DisplayChangeListener {
- int idle;
- uint64_t gui_timer_interval;
+typedef struct DisplayChangeListenerOps {
+ const char *dpy_name;
- void (*dpy_refresh)(struct DisplayState *s);
+ void (*dpy_refresh)(DisplayChangeListener *dcl);
- void (*dpy_gfx_update)(struct DisplayState *s, int x, int y, int w, int h);
- void (*dpy_gfx_resize)(struct DisplayState *s);
- void (*dpy_gfx_setdata)(struct DisplayState *s);
- void (*dpy_gfx_copy)(struct DisplayState *s, int src_x, int src_y,
+ void (*dpy_gfx_update)(DisplayChangeListener *dcl,
+ int x, int y, int w, int h);
+ void (*dpy_gfx_switch)(DisplayChangeListener *dcl,
+ struct DisplaySurface *new_surface);
+ void (*dpy_gfx_copy)(DisplayChangeListener *dcl,
+ int src_x, int src_y,
int dst_x, int dst_y, int w, int h);
- void (*dpy_text_cursor)(struct DisplayState *s, int x, int y);
- void (*dpy_text_resize)(struct DisplayState *s, int w, int h);
- void (*dpy_text_update)(struct DisplayState *s, int x, int y, int w, int h);
+ void (*dpy_text_cursor)(DisplayChangeListener *dcl,
+ int x, int y);
+ void (*dpy_text_resize)(DisplayChangeListener *dcl,
+ int w, int h);
+ void (*dpy_text_update)(DisplayChangeListener *dcl,
+ int x, int y, int w, int h);
- void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on);
- void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor);
+ void (*dpy_mouse_set)(DisplayChangeListener *dcl,
+ int x, int y, int on);
+ void (*dpy_cursor_define)(DisplayChangeListener *dcl,
+ QEMUCursor *cursor);
+} DisplayChangeListenerOps;
+
+struct DisplayChangeListener {
+ int idle;
+ uint64_t gui_timer_interval;
+ const DisplayChangeListenerOps *ops;
+ DisplayState *ds;
QLIST_ENTRY(DisplayChangeListener) next;
};
struct DisplayState {
struct DisplaySurface *surface;
- void *opaque;
struct QEMUTimer *gui_timer;
bool have_gfx;
bool have_text;
@@ -189,11 +201,8 @@ DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
PixelFormat qemu_different_endianness_pixelformat(int bpp);
PixelFormat qemu_default_pixelformat(int bpp);
-DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
- int width, int height);
-DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
- int width, int height);
-void qemu_free_displaysurface(DisplayState *ds);
+DisplaySurface *qemu_create_displaysurface(int width, int height);
+void qemu_free_displaysurface(DisplaySurface *surface);
static inline int is_surface_bgr(DisplaySurface *surface)
{
@@ -210,208 +219,55 @@ static inline int is_buffer_shared(DisplaySurface *surface)
void gui_setup_refresh(DisplayState *ds);
-static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl)
-{
- QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
- gui_setup_refresh(ds);
- if (dcl->dpy_gfx_resize) {
- dcl->dpy_gfx_resize(ds);
- }
-}
-
-static inline void unregister_displaychangelistener(DisplayState *ds,
- DisplayChangeListener *dcl)
-{
- QLIST_REMOVE(dcl, next);
- gui_setup_refresh(ds);
-}
-
-static inline void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
-{
- struct DisplayChangeListener *dcl;
- int width = pixman_image_get_width(s->surface->image);
- int height = pixman_image_get_height(s->surface->image);
-
- x = MAX(x, 0);
- y = MAX(y, 0);
- x = MIN(x, width);
- y = MIN(y, height);
- w = MIN(w, width - x);
- h = MIN(h, height - y);
-
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->dpy_gfx_update) {
- dcl->dpy_gfx_update(s, x, y, w, h);
- }
- }
-}
-
-static inline void dpy_gfx_resize(DisplayState *s)
+void register_displaychangelistener(DisplayState *ds,
+ DisplayChangeListener *dcl);
+void unregister_displaychangelistener(DisplayChangeListener *dcl);
+
+void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h);
+void dpy_gfx_replace_surface(QemuConsole *con,
+ DisplaySurface *surface);
+void dpy_refresh(DisplayState *s);
+void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
+ int dst_x, int dst_y, int w, int h);
+void dpy_text_cursor(QemuConsole *con, int x, int y);
+void dpy_text_update(QemuConsole *con, int x, int y, int w, int h);
+void dpy_text_resize(QemuConsole *con, int w, int h);
+void dpy_mouse_set(QemuConsole *con, int x, int y, int on);
+void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor);
+bool dpy_cursor_define_supported(QemuConsole *con);
+
+static inline int surface_stride(DisplaySurface *s)
{
- struct DisplayChangeListener *dcl;
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->dpy_gfx_resize) {
- dcl->dpy_gfx_resize(s);
- }
- }
+ return pixman_image_get_stride(s->image);
}
-static inline void dpy_gfx_setdata(DisplayState *s)
+static inline void *surface_data(DisplaySurface *s)
{
- struct DisplayChangeListener *dcl;
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->dpy_gfx_setdata) {
- dcl->dpy_gfx_setdata(s);
- }
- }
+ return pixman_image_get_data(s->image);
}
-static inline void dpy_refresh(DisplayState *s)
+static inline int surface_width(DisplaySurface *s)
{
- struct DisplayChangeListener *dcl;
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->dpy_refresh) {
- dcl->dpy_refresh(s);
- }
- }
+ return pixman_image_get_width(s->image);
}
-static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
- int dst_x, int dst_y, int w, int h)
+static inline int surface_height(DisplaySurface *s)
{
- struct DisplayChangeListener *dcl;
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->dpy_gfx_copy) {
- dcl->dpy_gfx_copy(s, src_x, src_y, dst_x, dst_y, w, h);
- } else { /* TODO */
- dcl->dpy_gfx_update(s, dst_x, dst_y, w, h);
- }
- }
+ return pixman_image_get_height(s->image);
}
-static inline void dpy_text_cursor(struct DisplayState *s, int x, int y)
+static inline int surface_bits_per_pixel(DisplaySurface *s)
{
- struct DisplayChangeListener *dcl;
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->dpy_text_cursor) {
- dcl->dpy_text_cursor(s, x, y);
- }
- }
-}
-
-static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
-{
- struct DisplayChangeListener *dcl;
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->dpy_text_update) {
- dcl->dpy_text_update(s, x, y, w, h);
- }
- }
-}
-
-static inline void dpy_text_resize(DisplayState *s, int w, int h)
-{
- struct DisplayChangeListener *dcl;
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->dpy_text_resize) {
- dcl->dpy_text_resize(s, w, h);
- }
- }
-}
-
-static inline void dpy_mouse_set(struct DisplayState *s, int x, int y, int on)
-{
- struct DisplayChangeListener *dcl;
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->dpy_mouse_set) {
- dcl->dpy_mouse_set(s, x, y, on);
- }
- }
-}
-
-static inline void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor)
-{
- struct DisplayChangeListener *dcl;
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->dpy_cursor_define) {
- dcl->dpy_cursor_define(s, cursor);
- }
- }
-}
-
-static inline bool dpy_cursor_define_supported(struct DisplayState *s)
-{
- struct DisplayChangeListener *dcl;
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->dpy_cursor_define) {
- return true;
- }
- }
- return false;
-}
-
-static inline int ds_get_linesize(DisplayState *ds)
-{
- return pixman_image_get_stride(ds->surface->image);
-}
-
-static inline uint8_t* ds_get_data(DisplayState *ds)
-{
- return (void *)pixman_image_get_data(ds->surface->image);
-}
-
-static inline int ds_get_width(DisplayState *ds)
-{
- return pixman_image_get_width(ds->surface->image);
-}
-
-static inline int ds_get_height(DisplayState *ds)
-{
- return pixman_image_get_height(ds->surface->image);
-}
-
-static inline int ds_get_bits_per_pixel(DisplayState *ds)
-{
- int bits = PIXMAN_FORMAT_BPP(ds->surface->format);
+ int bits = PIXMAN_FORMAT_BPP(s->format);
return bits;
}
-static inline int ds_get_bytes_per_pixel(DisplayState *ds)
+static inline int surface_bytes_per_pixel(DisplaySurface *s)
{
- int bits = PIXMAN_FORMAT_BPP(ds->surface->format);
+ int bits = PIXMAN_FORMAT_BPP(s->format);
return (bits + 7) / 8;
}
-static inline pixman_format_code_t ds_get_format(DisplayState *ds)
-{
- return ds->surface->format;
-}
-
-static inline pixman_image_t *ds_get_image(DisplayState *ds)
-{
- return ds->surface->image;
-}
-
-static inline int ds_get_depth(DisplayState *ds)
-{
- return ds->surface->pf.depth;
-}
-
-static inline int ds_get_rmask(DisplayState *ds)
-{
- return ds->surface->pf.rmask;
-}
-
-static inline int ds_get_gmask(DisplayState *ds)
-{
- return ds->surface->pf.gmask;
-}
-
-static inline int ds_get_bmask(DisplayState *ds)
-{
- return ds->surface->pf.bmask;
-}
-
#ifdef CONFIG_CURSES
#include <curses.h>
typedef chtype console_ch_t;
@@ -431,11 +287,11 @@ typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch,
Error **errp);
typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *);
-DisplayState *graphic_console_init(vga_hw_update_ptr update,
- vga_hw_invalidate_ptr invalidate,
- vga_hw_screen_dump_ptr screen_dump,
- vga_hw_text_update_ptr text_update,
- void *opaque);
+QemuConsole *graphic_console_init(vga_hw_update_ptr update,
+ vga_hw_invalidate_ptr invalidate,
+ vga_hw_screen_dump_ptr screen_dump,
+ vga_hw_text_update_ptr text_update,
+ void *opaque);
void vga_hw_update(void);
void vga_hw_invalidate(void);
@@ -446,9 +302,11 @@ int is_fixedsize_console(void);
void text_consoles_set_display(DisplayState *ds);
void console_select(unsigned int index);
void console_color_init(DisplayState *ds);
-void qemu_console_resize(DisplayState *ds, int width, int height);
-void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
+void qemu_console_resize(QemuConsole *con, int width, int height);
+void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
int dst_x, int dst_y, int w, int h);
+DisplaySurface *qemu_console_surface(QemuConsole *con);
+DisplayState *qemu_console_displaystate(QemuConsole *console);
typedef CharDriverState *(VcHandler)(ChardevVC *vc);
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index 46f9530fe3..7a20fc43ff 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -71,7 +71,9 @@ typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
struct SimpleSpiceDisplay {
- DisplayState *ds;
+ QemuConsole *con;
+ DisplaySurface *ds;
+ DisplayChangeListener dcl;
void *buf;
int bufsize;
QXLWorker *worker;
@@ -112,11 +114,12 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd);
void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd);
void qemu_spice_vm_change_state_handler(void *opaque, int running,
RunState state);
-void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds);
+void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd);
void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
int x, int y, int w, int h);
-void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
+void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
+ DisplaySurface *surface);
void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd);
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 472be35bbf..c7df595c9b 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -517,13 +517,8 @@ static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
acc = ((int64_t)env->active_tc.HI[ac] << 32) |
((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
- if (shift == 0) {
- p[0] = acc << 1;
- p[1] = (acc >> 63) & 0x01;
- } else {
- p[0] = acc >> (shift - 1);
- p[1] = 0;
- }
+ p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1));
+ p[1] = (acc >> 63) & 0x01;
}
/* 128 bits long. p[0] is LO, p[1] is HI */
@@ -3161,8 +3156,8 @@ target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
tempDL[1] += 1;
}
- if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) &&
- (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) {
+ if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+ ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
set_DSPControl_overflow_flag(1, 23, env);
}
@@ -3187,8 +3182,8 @@ target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
tempDL[1] += 1;
}
- if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
- (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+ if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+ ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
set_DSPControl_overflow_flag(1, 23, env);
}
@@ -3214,9 +3209,9 @@ target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
}
tempI = tempDL[0] >> 1;
- if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
- (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
- temp64 = tempDL[1];
+ if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+ ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+ temp64 = tempDL[1] & 0x01;
if (temp64 == 0) {
tempI = 0x7FFFFFFF;
} else {
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 8f111ae732..644f484c48 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -315,8 +315,7 @@ void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
int kvm_arch_process_async_events(CPUState *cs)
{
- S390CPU *cpu = S390_CPU(cs);
- return cpu->env.halted;
+ return cs->halted;
}
void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm,
diff --git a/tests/tcg/mips/mips32-dsp/extr_r_w.c b/tests/tcg/mips/mips32-dsp/extr_r_w.c
index 02e022427a..489c1931b4 100644
--- a/tests/tcg/mips/mips32-dsp/extr_r_w.c
+++ b/tests/tcg/mips/mips32-dsp/extr_r_w.c
@@ -67,5 +67,28 @@ int main()
assert(dsp == 0);
assert(result == rt);
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0xFFFFFFFF;
+ acl = 0xFFFFFFFF;
+ result = 0;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_r.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
return 0;
}
diff --git a/tests/tcg/mips/mips32-dsp/extr_rs_w.c b/tests/tcg/mips/mips32-dsp/extr_rs_w.c
index c3a22ee704..f9d2ed646f 100644
--- a/tests/tcg/mips/mips32-dsp/extr_rs_w.c
+++ b/tests/tcg/mips/mips32-dsp/extr_rs_w.c
@@ -67,5 +67,51 @@ int main()
assert(dsp == 0);
assert(result == rt);
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x80000000;
+ acl = 0x00000000;
+ result = 0x80000000;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_rs.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0xFFFFFFFF;
+ acl = 0xFFFFFFFF;
+ result = 0;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_rs.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
return 0;
}
diff --git a/tests/tcg/mips/mips32-dsp/extr_w.c b/tests/tcg/mips/mips32-dsp/extr_w.c
index bd6b0b95c2..cf926146d5 100644
--- a/tests/tcg/mips/mips32-dsp/extr_w.c
+++ b/tests/tcg/mips/mips32-dsp/extr_w.c
@@ -67,5 +67,28 @@ int main()
assert(dsp == 0);
assert(result == rt);
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0xFFFFFFFF;
+ acl = 0xFFFFFFFF;
+ result = 0xFFFFFFFF;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
return 0;
}
diff --git a/trace-events b/trace-events
index cd73b7f3ea..406fe5f408 100644
--- a/trace-events
+++ b/trace-events
@@ -958,8 +958,11 @@ dma_bdrv_cb(void *dbs, int ret) "dbs=%p ret=%d"
dma_map_wait(void *dbs) "dbs=%p"
# console.h
-displaysurface_free(void *display_state, void *display_surface) "state=%p surface=%p"
-displaysurface_resize(void *display_state, void *display_surface, int width, int height) "state=%p surface=%p %dx%d"
+displaysurface_create(void *display_surface, int w, int h) "surface=%p, %dx%d"
+displaysurface_create_from(void *display_surface, int w, int h, int bpp, int swap) "surface=%p, %dx%d, bpp %d, bswap %d"
+displaysurface_free(void *display_surface) "surface=%p"
+displaychangelistener_register(void *dcl, const char *name) "%p [ %s ]"
+displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]"
# vga.c
ppm_save(const char *filename, void *display_surface) "%s surface=%p"
diff --git a/ui/cocoa.m b/ui/cocoa.m
index ca42413b34..8e0eaa2601 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -264,8 +264,7 @@ static int cocoa_keycode_to_qemu(int keycode)
BOOL isAbsoluteEnabled;
BOOL isTabletEnabled;
}
-- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds;
-- (void) updateDataOffset:(DisplayState *)ds;
+- (void) switchSurface:(DisplaySurface *)surface;
- (void) grabMouse;
- (void) ungrabMouse;
- (void) toggleFullScreen:(id)sender;
@@ -400,19 +399,19 @@ QemuCocoaView *cocoaView;
}
}
-- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds
+- (void) switchSurface:(DisplaySurface *)surface
{
- COCOA_DEBUG("QemuCocoaView: resizeContent\n");
+ COCOA_DEBUG("QemuCocoaView: switchSurface\n");
// update screenBuffer
if (dataProviderRef)
CGDataProviderRelease(dataProviderRef);
//sync host window color space with guests
- screen.bitsPerPixel = ds_get_bits_per_pixel(ds);
- screen.bitsPerComponent = ds_get_bytes_per_pixel(ds) * 2;
+ screen.bitsPerPixel = surface_bits_per_pixel(surface);
+ screen.bitsPerComponent = surface_bytes_per_pixel(surface) * 2;
- dataProviderRef = CGDataProviderCreateWithData(NULL, ds_get_data(ds), w * 4 * h, NULL);
+ dataProviderRef = CGDataProviderCreateWithData(NULL, surface_data(surface), w * 4 * h, NULL);
// update windows
if (isFullscreen) {
@@ -430,20 +429,6 @@ QemuCocoaView *cocoaView;
[self setFrame:NSMakeRect(cx, cy, cw, ch)];
}
-- (void) updateDataOffset:(DisplayState *)ds
-{
- COCOA_DEBUG("QemuCocoaView: UpdateDataOffset\n");
-
- // update screenBuffer
- if (dataProviderRef) {
- CGDataProviderRelease(dataProviderRef);
- }
-
- size_t size = ds_get_width(ds) * 4 * ds_get_height(ds);
- dataProviderRef = CGDataProviderCreateWithData(NULL, ds_get_data(ds),
- size, NULL);
-}
-
- (void) toggleFullScreen:(id)sender
{
COCOA_DEBUG("QemuCocoaView: toggleFullScreen\n");
@@ -969,7 +954,8 @@ int main (int argc, const char * argv[]) {
#pragma mark qemu
-static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
+static void cocoa_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h)
{
COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
@@ -986,14 +972,15 @@ static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
[cocoaView setNeedsDisplayInRect:rect];
}
-static void cocoa_resize(DisplayState *ds)
+static void cocoa_switch(DisplayChangeListener *dcl,
+ DisplaySurface *surface)
{
COCOA_DEBUG("qemu_cocoa: cocoa_resize\n");
- [cocoaView resizeContentToWidth:(int)(ds_get_width(ds)) height:(int)(ds_get_height(ds)) displayState:ds];
+ [cocoaView switchSurface:surface];
}
-static void cocoa_refresh(DisplayState *ds)
+static void cocoa_refresh(DisplayChangeListener *dcl)
{
COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n");
@@ -1019,17 +1006,19 @@ static void cocoa_refresh(DisplayState *ds)
vga_hw_update();
}
-static void cocoa_setdata(DisplayState *ds)
-{
- [cocoaView updateDataOffset:ds];
-}
-
static void cocoa_cleanup(void)
{
COCOA_DEBUG("qemu_cocoa: cocoa_cleanup\n");
g_free(dcl);
}
+static const DisplayChangeListenerOps dcl_ops = {
+ .dpy_name = "cocoa",
+ .dpy_gfx_update = cocoa_update;
+ .dpy_gfx_switch = cocoa_switch;
+ .dpy_refresh = cocoa_refresh;
+};
+
void cocoa_display_init(DisplayState *ds, int full_screen)
{
COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n");
@@ -1037,12 +1026,8 @@ void cocoa_display_init(DisplayState *ds, int full_screen)
dcl = g_malloc0(sizeof(DisplayChangeListener));
// register vga output callbacks
- dcl->dpy_gfx_update = cocoa_update;
- dcl->dpy_gfx_resize = cocoa_resize;
- dcl->dpy_refresh = cocoa_refresh;
- dcl->dpy_gfx_setdata = cocoa_setdata;
-
- register_displaychangelistener(ds, dcl);
+ dcl->ops = &dcl_ops;
+ register_displaychangelistener(ds, dcl);
// register cleanup function
atexit(cocoa_cleanup);
diff --git a/ui/console.c b/ui/console.c
index 27e87f8879..eb7a2bc1bf 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -208,51 +208,17 @@ void vga_hw_text_update(console_ch_t *chardata)
active_console->hw_text_update(active_console->hw, chardata);
}
-/* convert a RGBA color to a color index usable in graphic primitives */
-static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
-{
- unsigned int r, g, b, color;
-
- switch(ds_get_bits_per_pixel(ds)) {
-#if 0
- case 8:
- r = (rgba >> 16) & 0xff;
- g = (rgba >> 8) & 0xff;
- b = (rgba) & 0xff;
- color = (rgb_to_index[r] * 6 * 6) +
- (rgb_to_index[g] * 6) +
- (rgb_to_index[b]);
- break;
-#endif
- case 15:
- r = (rgba >> 16) & 0xff;
- g = (rgba >> 8) & 0xff;
- b = (rgba) & 0xff;
- color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
- break;
- case 16:
- r = (rgba >> 16) & 0xff;
- g = (rgba >> 8) & 0xff;
- b = (rgba) & 0xff;
- color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
- break;
- case 32:
- default:
- color = rgba;
- break;
- }
- return color;
-}
-
-static void vga_fill_rect (DisplayState *ds,
- int posx, int posy, int width, int height, uint32_t color)
+static void vga_fill_rect(QemuConsole *con,
+ int posx, int posy, int width, int height,
+ uint32_t color)
{
+ DisplaySurface *surface = qemu_console_surface(con);
uint8_t *d, *d1;
int x, y, bpp;
- bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
- d1 = ds_get_data(ds) +
- ds_get_linesize(ds) * posy + bpp * posx;
+ bpp = surface_bytes_per_pixel(surface);
+ d1 = surface_data(surface) +
+ surface_stride(surface) * posy + bpp * posx;
for (y = 0; y < height; y++) {
d = d1;
switch(bpp) {
@@ -275,38 +241,40 @@ static void vga_fill_rect (DisplayState *ds,
}
break;
}
- d1 += ds_get_linesize(ds);
+ d1 += surface_stride(surface);
}
}
/* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
-static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h)
+static void vga_bitblt(QemuConsole *con,
+ int xs, int ys, int xd, int yd, int w, int h)
{
+ DisplaySurface *surface = qemu_console_surface(con);
const uint8_t *s;
uint8_t *d;
int wb, y, bpp;
- bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
+ bpp = surface_bytes_per_pixel(surface);
wb = w * bpp;
if (yd <= ys) {
- s = ds_get_data(ds) +
- ds_get_linesize(ds) * ys + bpp * xs;
- d = ds_get_data(ds) +
- ds_get_linesize(ds) * yd + bpp * xd;
+ s = surface_data(surface) +
+ surface_stride(surface) * ys + bpp * xs;
+ d = surface_data(surface) +
+ surface_stride(surface) * yd + bpp * xd;
for (y = 0; y < h; y++) {
memmove(d, s, wb);
- d += ds_get_linesize(ds);
- s += ds_get_linesize(ds);
+ d += surface_stride(surface);
+ s += surface_stride(surface);
}
} else {
- s = ds_get_data(ds) +
- ds_get_linesize(ds) * (ys + h - 1) + bpp * xs;
- d = ds_get_data(ds) +
- ds_get_linesize(ds) * (yd + h - 1) + bpp * xd;
+ s = surface_data(surface) +
+ surface_stride(surface) * (ys + h - 1) + bpp * xs;
+ d = surface_data(surface) +
+ surface_stride(surface) * (yd + h - 1) + bpp * xd;
for (y = 0; y < h; y++) {
memmove(d, s, wb);
- d -= ds_get_linesize(ds);
- s -= ds_get_linesize(ds);
+ d -= surface_stride(surface);
+ s -= surface_stride(surface);
}
}
}
@@ -358,8 +326,6 @@ static const uint32_t dmask4[4] = {
PAT(0xffffffff),
};
-static uint32_t color_table[2][8];
-
#ifndef CONFIG_CURSES
enum color_names {
COLOR_BLACK = 0,
@@ -396,23 +362,6 @@ static const uint32_t color_table_rgb[2][8] = {
}
};
-static inline unsigned int col_expand(DisplayState *ds, unsigned int col)
-{
- switch(ds_get_bits_per_pixel(ds)) {
- case 8:
- col |= col << 8;
- col |= col << 16;
- break;
- case 15:
- case 16:
- col |= col << 16;
- break;
- default:
- break;
- }
-
- return col;
-}
#ifdef DEBUG_CONSOLE
static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
{
@@ -446,9 +395,10 @@ static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
}
#endif
-static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
+static void vga_putcharxy(QemuConsole *s, int x, int y, int ch,
TextAttributes *t_attrib)
{
+ DisplaySurface *surface = qemu_console_surface(s);
uint8_t *d;
const uint8_t *font_ptr;
unsigned int font_data, linesize, xorcol, bpp;
@@ -461,20 +411,20 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
#endif
if (t_attrib->invers) {
- bgcol = color_table[t_attrib->bold][t_attrib->fgcol];
- fgcol = color_table[t_attrib->bold][t_attrib->bgcol];
+ bgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
+ fgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
} else {
- fgcol = color_table[t_attrib->bold][t_attrib->fgcol];
- bgcol = color_table[t_attrib->bold][t_attrib->bgcol];
+ fgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
+ bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
}
- bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
- d = ds_get_data(ds) +
- ds_get_linesize(ds) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
- linesize = ds_get_linesize(ds);
+ bpp = surface_bytes_per_pixel(surface);
+ d = surface_data(surface) +
+ surface_stride(surface) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
+ linesize = surface_stride(surface);
font_ptr = vgafont16 + FONT_HEIGHT * ch;
xorcol = bgcol ^ fgcol;
- switch(ds_get_bits_per_pixel(ds)) {
+ switch (surface_bits_per_pixel(surface)) {
case 8:
for(i = 0; i < FONT_HEIGHT; i++) {
font_data = *font_ptr++;
@@ -579,19 +529,22 @@ static void update_xy(QemuConsole *s, int x, int y)
TextCell *c;
int y1, y2;
- if (s == active_console) {
- if (!ds_get_bits_per_pixel(s->ds)) {
- text_update_xy(s, x, y);
- return;
- }
+ if (s != active_console) {
+ return;
+ }
+ if (s->ds->have_text) {
+ text_update_xy(s, x, y);
+ }
+
+ if (s->ds->have_gfx) {
y1 = (s->y_base + y) % s->total_height;
y2 = y1 - s->y_displayed;
if (y2 < 0)
y2 += s->total_height;
if (y2 < s->height) {
c = &s->cells[y1 * s->width + x];
- vga_putcharxy(s->ds, x, y2, c->ch,
+ vga_putcharxy(s, x, y2, c->ch,
&(c->t_attrib));
invalidate_xy(s, x, y2);
}
@@ -602,15 +555,17 @@ static void console_show_cursor(QemuConsole *s, int show)
{
TextCell *c;
int y, y1;
+ int x = s->x;
- if (s == active_console) {
- int x = s->x;
+ if (s != active_console) {
+ return;
+ }
- if (!ds_get_bits_per_pixel(s->ds)) {
- s->cursor_invalidate = 1;
- return;
- }
+ if (s->ds->have_text) {
+ s->cursor_invalidate = 1;
+ }
+ if (s->ds->have_gfx) {
if (x >= s->width) {
x = s->width - 1;
}
@@ -623,9 +578,9 @@ static void console_show_cursor(QemuConsole *s, int show)
if (show && s->cursor_visible_phase) {
TextAttributes t_attrib = s->t_attrib_default;
t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
- vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
+ vga_putcharxy(s, x, y, c->ch, &t_attrib);
} else {
- vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
+ vga_putcharxy(s, x, y, c->ch, &(c->t_attrib));
}
invalidate_xy(s, x, y);
}
@@ -634,6 +589,7 @@ static void console_show_cursor(QemuConsole *s, int show)
static void console_refresh(QemuConsole *s)
{
+ DisplaySurface *surface = qemu_console_surface(s);
TextCell *c;
int x, y, y1;
@@ -649,13 +605,13 @@ static void console_refresh(QemuConsole *s)
}
if (s->ds->have_gfx) {
- vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
- color_table[0][COLOR_BLACK]);
+ vga_fill_rect(s, 0, 0, surface_width(surface), surface_height(surface),
+ color_table_rgb[0][COLOR_BLACK]);
y1 = s->y_displayed;
for (y = 0; y < s->height; y++) {
c = s->cells + y1 * s->width;
for (x = 0; x < s->width; x++) {
- vga_putcharxy(s->ds, x, y, c->ch,
+ vga_putcharxy(s, x, y, c->ch,
&(c->t_attrib));
c++;
}
@@ -664,7 +620,8 @@ static void console_refresh(QemuConsole *s)
}
}
console_show_cursor(s, 1);
- dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
+ dpy_gfx_update(s, 0, 0,
+ surface_width(surface), surface_height(surface));
}
}
@@ -727,24 +684,25 @@ static void console_put_lf(QemuConsole *s)
c++;
}
if (s == active_console && s->y_displayed == s->y_base) {
- if (!ds_get_bits_per_pixel(s->ds)) {
+ if (s->ds->have_text) {
s->text_x[0] = 0;
s->text_y[0] = 0;
s->text_x[1] = s->width - 1;
s->text_y[1] = s->height - 1;
- return;
}
- vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
- s->width * FONT_WIDTH,
- (s->height - 1) * FONT_HEIGHT);
- vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
- s->width * FONT_WIDTH, FONT_HEIGHT,
- color_table[0][s->t_attrib_default.bgcol]);
- s->update_x0 = 0;
- s->update_y0 = 0;
- s->update_x1 = s->width * FONT_WIDTH;
- s->update_y1 = s->height * FONT_HEIGHT;
+ if (s->ds->have_gfx) {
+ vga_bitblt(s, 0, FONT_HEIGHT, 0, 0,
+ s->width * FONT_WIDTH,
+ (s->height - 1) * FONT_HEIGHT);
+ vga_fill_rect(s, 0, (s->height - 1) * FONT_HEIGHT,
+ s->width * FONT_WIDTH, FONT_HEIGHT,
+ color_table_rgb[0][s->t_attrib_default.bgcol]);
+ s->update_x0 = 0;
+ s->update_y0 = 0;
+ s->update_x1 = s->width * FONT_WIDTH;
+ s->update_y1 = s->height * FONT_HEIGHT;
+ }
}
}
}
@@ -1082,13 +1040,15 @@ static void console_putchar(QemuConsole *s, int ch)
void console_select(unsigned int index)
{
+ DisplaySurface *surface;
QemuConsole *s;
if (index >= MAX_CONSOLES)
return;
if (active_console) {
- active_console->g_width = ds_get_width(active_console->ds);
- active_console->g_height = ds_get_height(active_console->ds);
+ surface = qemu_console_surface(active_console);
+ active_console->g_width = surface_width(surface);
+ active_console->g_height = surface_height(surface);
}
s = consoles[index];
if (s) {
@@ -1099,11 +1059,11 @@ void console_select(unsigned int index)
}
active_console = s;
if (ds->have_gfx) {
- ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
- dpy_gfx_resize(ds);
+ surface = qemu_create_displaysurface(s->g_width, s->g_height);
+ dpy_gfx_replace_surface(s, surface);
}
if (ds->have_text) {
- dpy_text_resize(ds, s->width, s->height);
+ dpy_text_resize(s, s->width, s->height);
}
if (s->cursor_timer) {
qemu_mod_timer(s->cursor_timer,
@@ -1128,7 +1088,7 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
}
console_show_cursor(s, 1);
if (s->ds->have_gfx && s->update_x0 < s->update_x1) {
- dpy_gfx_update(s->ds, s->update_x0, s->update_y0,
+ dpy_gfx_update(s, s->update_x0, s->update_y0,
s->update_x1 - s->update_x0,
s->update_y1 - s->update_y0);
}
@@ -1216,9 +1176,11 @@ void kbd_put_keysym(int keysym)
static void text_console_invalidate(void *opaque)
{
QemuConsole *s = (QemuConsole *) opaque;
- if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) {
- s->g_width = ds_get_width(s->ds);
- s->g_height = ds_get_height(s->ds);
+ DisplaySurface *surface = qemu_console_surface(s);
+
+ if (s->ds->have_text && s->console_type == TEXT_CONSOLE) {
+ s->g_width = surface_width(surface);
+ s->g_height = surface_height(surface);
text_console_resize(s);
}
console_refresh(s);
@@ -1238,7 +1200,7 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
(s->cells[src].t_attrib.fgcol << 12) |
(s->cells[src].t_attrib.bgcol << 8) |
(s->cells[src].t_attrib.bold << 21));
- dpy_text_update(s->ds, s->text_x[0], s->text_y[0],
+ dpy_text_update(s, s->text_x[0], s->text_y[0],
s->text_x[1] - s->text_x[0], i - s->text_y[0]);
s->text_x[0] = s->width;
s->text_y[0] = s->height;
@@ -1246,23 +1208,11 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
s->text_y[1] = 0;
}
if (s->cursor_invalidate) {
- dpy_text_cursor(s->ds, s->x, s->y);
+ dpy_text_cursor(s, s->x, s->y);
s->cursor_invalidate = 0;
}
}
-static QemuConsole *get_graphic_console(DisplayState *ds)
-{
- int i;
- QemuConsole *s;
- for (i = 0; i < nb_consoles; i++) {
- s = consoles[i];
- if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds)
- return s;
- }
- return NULL;
-}
-
static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
{
QemuConsole *s;
@@ -1316,34 +1266,24 @@ static void qemu_alloc_display(DisplaySurface *surface, int width, int height,
#endif
}
-DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
- int width, int height)
+DisplaySurface *qemu_create_displaysurface(int width, int height)
{
DisplaySurface *surface = g_new0(DisplaySurface, 1);
-
int linesize = width * 4;
+
+ trace_displaysurface_create(surface, width, height);
qemu_alloc_display(surface, width, height, linesize,
qemu_default_pixelformat(32), 0);
return surface;
}
-DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
- int width, int height)
-{
- int linesize = width * 4;
-
- trace_displaysurface_resize(ds, ds->surface, width, height);
- qemu_alloc_display(ds->surface, width, height, linesize,
- qemu_default_pixelformat(32), 0);
- return ds->surface;
-}
-
DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
int linesize, uint8_t *data,
bool byteswap)
{
DisplaySurface *surface = g_new0(DisplaySurface, 1);
+ trace_displaysurface_create_from(surface, width, height, bpp, byteswap);
if (byteswap) {
surface->pf = qemu_different_endianness_pixelformat(bpp);
} else {
@@ -1364,14 +1304,162 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
return surface;
}
-void qemu_free_displaysurface(DisplayState *ds)
+void qemu_free_displaysurface(DisplaySurface *surface)
{
- trace_displaysurface_free(ds, ds->surface);
- if (ds->surface == NULL) {
+ if (surface == NULL) {
return;
}
- qemu_pixman_image_unref(ds->surface->image);
- g_free(ds->surface);
+ trace_displaysurface_free(surface);
+ qemu_pixman_image_unref(surface->image);
+ g_free(surface);
+}
+
+void register_displaychangelistener(DisplayState *ds,
+ DisplayChangeListener *dcl)
+{
+ trace_displaychangelistener_register(dcl, dcl->ops->dpy_name);
+ dcl->ds = ds;
+ QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
+ gui_setup_refresh(ds);
+ if (dcl->ops->dpy_gfx_switch) {
+ dcl->ops->dpy_gfx_switch(dcl, ds->surface);
+ }
+}
+
+void unregister_displaychangelistener(DisplayChangeListener *dcl)
+{
+ DisplayState *ds = dcl->ds;
+ trace_displaychangelistener_unregister(dcl, dcl->ops->dpy_name);
+ QLIST_REMOVE(dcl, next);
+ gui_setup_refresh(ds);
+}
+
+void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
+{
+ DisplayState *s = con->ds;
+ struct DisplayChangeListener *dcl;
+ int width = pixman_image_get_width(s->surface->image);
+ int height = pixman_image_get_height(s->surface->image);
+
+ x = MAX(x, 0);
+ y = MAX(y, 0);
+ x = MIN(x, width);
+ y = MIN(y, height);
+ w = MIN(w, width - x);
+ h = MIN(h, height - y);
+
+ QLIST_FOREACH(dcl, &s->listeners, next) {
+ if (dcl->ops->dpy_gfx_update) {
+ dcl->ops->dpy_gfx_update(dcl, x, y, w, h);
+ }
+ }
+}
+
+void dpy_gfx_replace_surface(QemuConsole *con,
+ DisplaySurface *surface)
+{
+ DisplayState *s = con->ds;
+ DisplaySurface *old_surface = s->surface;
+ struct DisplayChangeListener *dcl;
+
+ s->surface = surface;
+ QLIST_FOREACH(dcl, &s->listeners, next) {
+ if (dcl->ops->dpy_gfx_switch) {
+ dcl->ops->dpy_gfx_switch(dcl, surface);
+ }
+ }
+ qemu_free_displaysurface(old_surface);
+}
+
+void dpy_refresh(DisplayState *s)
+{
+ struct DisplayChangeListener *dcl;
+ QLIST_FOREACH(dcl, &s->listeners, next) {
+ if (dcl->ops->dpy_refresh) {
+ dcl->ops->dpy_refresh(dcl);
+ }
+ }
+}
+
+void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
+ int dst_x, int dst_y, int w, int h)
+{
+ DisplayState *s = con->ds;
+ struct DisplayChangeListener *dcl;
+ QLIST_FOREACH(dcl, &s->listeners, next) {
+ if (dcl->ops->dpy_gfx_copy) {
+ dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
+ } else { /* TODO */
+ dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h);
+ }
+ }
+}
+
+void dpy_text_cursor(QemuConsole *con, int x, int y)
+{
+ DisplayState *s = con->ds;
+ struct DisplayChangeListener *dcl;
+ QLIST_FOREACH(dcl, &s->listeners, next) {
+ if (dcl->ops->dpy_text_cursor) {
+ dcl->ops->dpy_text_cursor(dcl, x, y);
+ }
+ }
+}
+
+void dpy_text_update(QemuConsole *con, int x, int y, int w, int h)
+{
+ DisplayState *s = con->ds;
+ struct DisplayChangeListener *dcl;
+ QLIST_FOREACH(dcl, &s->listeners, next) {
+ if (dcl->ops->dpy_text_update) {
+ dcl->ops->dpy_text_update(dcl, x, y, w, h);
+ }
+ }
+}
+
+void dpy_text_resize(QemuConsole *con, int w, int h)
+{
+ DisplayState *s = con->ds;
+ struct DisplayChangeListener *dcl;
+ QLIST_FOREACH(dcl, &s->listeners, next) {
+ if (dcl->ops->dpy_text_resize) {
+ dcl->ops->dpy_text_resize(dcl, w, h);
+ }
+ }
+}
+
+void dpy_mouse_set(QemuConsole *con, int x, int y, int on)
+{
+ DisplayState *s = con->ds;
+ struct DisplayChangeListener *dcl;
+ QLIST_FOREACH(dcl, &s->listeners, next) {
+ if (dcl->ops->dpy_mouse_set) {
+ dcl->ops->dpy_mouse_set(dcl, x, y, on);
+ }
+ }
+}
+
+void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor)
+{
+ DisplayState *s = con->ds;
+ struct DisplayChangeListener *dcl;
+ QLIST_FOREACH(dcl, &s->listeners, next) {
+ if (dcl->ops->dpy_cursor_define) {
+ dcl->ops->dpy_cursor_define(dcl, cursor);
+ }
+ }
+}
+
+bool dpy_cursor_define_supported(QemuConsole *con)
+{
+ DisplayState *s = con->ds;
+ struct DisplayChangeListener *dcl;
+ QLIST_FOREACH(dcl, &s->listeners, next) {
+ if (dcl->ops->dpy_cursor_define) {
+ return true;
+ }
+ }
+ return false;
}
static void dumb_display_init(void)
@@ -1384,7 +1472,8 @@ static void dumb_display_init(void)
width = active_console->g_width;
height = active_console->g_height;
}
- ds->surface = qemu_create_displaysurface(ds, width, height);
+ ds->surface = qemu_create_displaysurface(width, height);
+
register_displaystate(ds);
}
@@ -1409,32 +1498,27 @@ DisplayState *get_displaystate(void)
return display_state;
}
-DisplayState *graphic_console_init(vga_hw_update_ptr update,
- vga_hw_invalidate_ptr invalidate,
- vga_hw_screen_dump_ptr screen_dump,
- vga_hw_text_update_ptr text_update,
- void *opaque)
+QemuConsole *graphic_console_init(vga_hw_update_ptr update,
+ vga_hw_invalidate_ptr invalidate,
+ vga_hw_screen_dump_ptr screen_dump,
+ vga_hw_text_update_ptr text_update,
+ void *opaque)
{
QemuConsole *s;
DisplayState *ds;
ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
- ds->surface = qemu_create_displaysurface(ds, 640, 480);
-
s = new_console(ds, GRAPHIC_CONSOLE);
- if (s == NULL) {
- qemu_free_displaysurface(ds);
- g_free(ds);
- return NULL;
- }
s->hw_update = update;
s->hw_invalidate = invalidate;
s->hw_screen_dump = screen_dump;
s->hw_text_update = text_update;
s->hw = opaque;
+ ds->surface = qemu_create_displaysurface(640, 480);
+
register_displaystate(ds);
- return ds;
+ return s;
}
int is_graphic_console(void)
@@ -1447,17 +1531,6 @@ int is_fixedsize_console(void)
return active_console && active_console->console_type != TEXT_CONSOLE;
}
-void console_color_init(DisplayState *ds)
-{
- int i, j;
- for (j = 0; j < 2; j++) {
- for (i = 0; i < 8; i++) {
- color_table[j][i] = col_expand(ds,
- vga_get_color(ds, color_table_rgb[j][i]));
- }
- }
-}
-
static void text_console_set_echo(CharDriverState *chr, bool echo)
{
QemuConsole *s = chr->opaque;
@@ -1478,7 +1551,6 @@ static void text_console_update_cursor(void *opaque)
static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
{
QemuConsole *s;
- static int color_inited;
s = chr->opaque;
@@ -1489,18 +1561,14 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s);
s->ds = ds;
- if (!color_inited) {
- color_inited = 1;
- console_color_init(s->ds);
- }
s->y_displayed = 0;
s->y_base = 0;
s->total_height = DEFAULT_BACKSCROLL;
s->x = 0;
s->y = 0;
if (s->console_type == TEXT_CONSOLE) {
- s->g_width = ds_get_width(s->ds);
- s->g_height = ds_get_height(s->ds);
+ s->g_width = surface_width(s->ds->surface);
+ s->g_height = surface_height(s->ds->surface);
}
s->cursor_timer =
@@ -1600,27 +1668,35 @@ void text_consoles_set_display(DisplayState *ds)
}
}
-void qemu_console_resize(DisplayState *ds, int width, int height)
+void qemu_console_resize(QemuConsole *s, int width, int height)
{
- QemuConsole *s = get_graphic_console(ds);
- if (!s) return;
-
s->g_width = width;
s->g_height = height;
if (is_graphic_console()) {
- ds->surface = qemu_resize_displaysurface(ds, width, height);
- dpy_gfx_resize(ds);
+ DisplaySurface *surface;
+ surface = qemu_create_displaysurface(width, height);
+ dpy_gfx_replace_surface(s, surface);
}
}
-void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
+void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
int dst_x, int dst_y, int w, int h)
{
if (is_graphic_console()) {
- dpy_gfx_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
+ dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
}
}
+DisplaySurface *qemu_console_surface(QemuConsole *console)
+{
+ return console->ds->surface;
+}
+
+DisplayState *qemu_console_displaystate(QemuConsole *console)
+{
+ return console->ds;
+}
+
PixelFormat qemu_different_endianness_pixelformat(int bpp)
{
PixelFormat pf;
diff --git a/ui/curses.c b/ui/curses.c
index d78e378440..ff82307361 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -35,12 +35,14 @@
#define FONT_HEIGHT 16
#define FONT_WIDTH 8
+static DisplayChangeListener *dcl;
static console_ch_t screen[160 * 100];
static WINDOW *screenpad = NULL;
static int width, height, gwidth, gheight, invalidate;
static int px, py, sminx, sminy, smaxx, smaxy;
-static void curses_update(DisplayState *ds, int x, int y, int w, int h)
+static void curses_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h)
{
chtype *line;
@@ -91,7 +93,8 @@ static void curses_calc_pad(void)
}
}
-static void curses_resize(DisplayState *ds, int width, int height)
+static void curses_resize(DisplayChangeListener *dcl,
+ int width, int height)
{
if (width == gwidth && height == gheight) {
return;
@@ -128,7 +131,8 @@ static void curses_winch_handler(int signum)
#endif
#endif
-static void curses_cursor_position(DisplayState *ds, int x, int y)
+static void curses_cursor_position(DisplayChangeListener *dcl,
+ int x, int y)
{
if (x >= 0) {
x = sminx + x - px;
@@ -154,7 +158,7 @@ static void curses_cursor_position(DisplayState *ds, int x, int y)
static kbd_layout_t *kbd_layout = NULL;
-static void curses_refresh(DisplayState *ds)
+static void curses_refresh(DisplayChangeListener *dcl)
{
int chr, nextchr, keysym, keycode, keycode_alt;
@@ -187,7 +191,7 @@ static void curses_refresh(DisplayState *ds)
clear();
refresh();
curses_calc_pad();
- curses_update(ds, 0, 0, width, height);
+ curses_update(dcl, 0, 0, width, height);
continue;
}
#endif
@@ -323,9 +327,16 @@ static void curses_keyboard_setup(void)
}
}
+static const DisplayChangeListenerOps dcl_ops = {
+ .dpy_name = "curses",
+ .dpy_text_update = curses_update,
+ .dpy_text_resize = curses_resize,
+ .dpy_refresh = curses_refresh,
+ .dpy_text_cursor = curses_cursor_position,
+};
+
void curses_display_init(DisplayState *ds, int full_screen)
{
- DisplayChangeListener *dcl;
#ifndef _WIN32
if (!isatty(1)) {
fprintf(stderr, "We need a terminal output\n");
@@ -346,10 +357,7 @@ void curses_display_init(DisplayState *ds, int full_screen)
#endif
dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener));
- dcl->dpy_text_update = curses_update;
- dcl->dpy_text_resize = curses_resize;
- dcl->dpy_refresh = curses_refresh;
- dcl->dpy_text_cursor = curses_cursor_position;
+ dcl->ops = &dcl_ops;
register_displaychangelistener(ds, dcl);
invalidate = 1;
diff --git a/ui/gtk.c b/ui/gtk.c
index 794dab15b1..305940d0ba 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -143,7 +143,7 @@ typedef struct GtkDisplayState
GtkWidget *drawing_area;
cairo_surface_t *surface;
DisplayChangeListener dcl;
- DisplayState *ds;
+ DisplaySurface *ds;
int button_mask;
int last_x;
int last_y;
@@ -225,11 +225,50 @@ static void gd_update_caption(GtkDisplayState *s)
g_free(title);
}
+static void gd_update_windowsize(GtkDisplayState *s)
+{
+ if (!s->full_screen) {
+ GtkRequisition req;
+ double sx, sy;
+
+ if (s->free_scale) {
+ sx = s->scale_x;
+ sy = s->scale_y;
+
+ s->scale_y = 1.0;
+ s->scale_x = 1.0;
+ } else {
+ sx = 1.0;
+ sy = 1.0;
+ }
+
+ gtk_widget_set_size_request(s->drawing_area,
+ surface_width(s->ds) * s->scale_x,
+ surface_height(s->ds) * s->scale_y);
+#if GTK_CHECK_VERSION(3, 0, 0)
+ gtk_widget_get_preferred_size(s->vbox, NULL, &req);
+#else
+ gtk_widget_size_request(s->vbox, &req);
+#endif
+
+ gtk_window_resize(GTK_WINDOW(s->window),
+ req.width * sx, req.height * sy);
+ }
+}
+
+static void gd_update_full_redraw(GtkDisplayState *s)
+{
+ int ww, wh;
+ gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
+ gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh);
+}
+
/** DisplayState Callbacks **/
-static void gd_update(DisplayState *ds, int x, int y, int w, int h)
+static void gd_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h)
{
- GtkDisplayState *s = ds->opaque;
+ GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
int x1, x2, y1, y2;
int mx, my;
int fbw, fbh;
@@ -243,8 +282,8 @@ static void gd_update(DisplayState *ds, int x, int y, int w, int h)
x2 = ceil(x * s->scale_x + w * s->scale_x);
y2 = ceil(y * s->scale_y + h * s->scale_y);
- fbw = ds_get_width(s->ds) * s->scale_x;
- fbh = ds_get_height(s->ds) * s->scale_y;
+ fbw = surface_width(s->ds) * s->scale_x;
+ fbh = surface_height(s->ds) * s->scale_y;
gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
@@ -259,25 +298,33 @@ static void gd_update(DisplayState *ds, int x, int y, int w, int h)
gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1));
}
-static void gd_refresh(DisplayState *ds)
+static void gd_refresh(DisplayChangeListener *dcl)
{
vga_hw_update();
}
-static void gd_resize(DisplayState *ds)
+static void gd_switch(DisplayChangeListener *dcl,
+ DisplaySurface *surface)
{
- GtkDisplayState *s = ds->opaque;
+ GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
cairo_format_t kind;
+ bool resized = true;
int stride;
DPRINTF("resize(width=%d, height=%d)\n",
- ds_get_width(ds), ds_get_height(ds));
+ surface_width(surface), surface_height(surface));
if (s->surface) {
cairo_surface_destroy(s->surface);
}
- switch (ds->surface->pf.bits_per_pixel) {
+ if (s->ds &&
+ surface_width(s->ds) == surface_width(surface) &&
+ surface_height(s->ds) == surface_height(surface)) {
+ resized = false;
+ }
+ s->ds = surface;
+ switch (surface_bits_per_pixel(surface)) {
case 8:
kind = CAIRO_FORMAT_A8;
break;
@@ -292,41 +339,19 @@ static void gd_resize(DisplayState *ds)
break;
}
- stride = cairo_format_stride_for_width(kind, ds_get_width(ds));
- g_assert(ds_get_linesize(ds) == stride);
+ stride = cairo_format_stride_for_width(kind, surface_width(surface));
+ g_assert(surface_stride(surface) == stride);
- s->surface = cairo_image_surface_create_for_data(ds_get_data(ds),
+ s->surface = cairo_image_surface_create_for_data(surface_data(surface),
kind,
- ds_get_width(ds),
- ds_get_height(ds),
- ds_get_linesize(ds));
-
- if (!s->full_screen) {
- GtkRequisition req;
- double sx, sy;
-
- if (s->free_scale) {
- sx = s->scale_x;
- sy = s->scale_y;
-
- s->scale_y = 1.0;
- s->scale_x = 1.0;
- } else {
- sx = 1.0;
- sy = 1.0;
- }
-
- gtk_widget_set_size_request(s->drawing_area,
- ds_get_width(ds) * s->scale_x,
- ds_get_height(ds) * s->scale_y);
-#if GTK_CHECK_VERSION(3, 0, 0)
- gtk_widget_get_preferred_size(s->vbox, NULL, &req);
-#else
- gtk_widget_size_request(s->vbox, &req);
-#endif
+ surface_width(surface),
+ surface_height(surface),
+ surface_stride(surface));
- gtk_window_resize(GTK_WINDOW(s->window),
- req.width * sx, req.height * sy);
+ if (resized) {
+ gd_update_windowsize(s);
+ } else {
+ gd_update_full_redraw(s);
}
}
@@ -382,7 +407,7 @@ static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event,
GtkDisplayState *s = opaque;
if (!no_quit) {
- unregister_displaychangelistener(s->ds, &s->dcl);
+ unregister_displaychangelistener(&s->dcl);
qmp_quit(NULL);
return FALSE;
}
@@ -401,8 +426,8 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
return FALSE;
}
- fbw = ds_get_width(s->ds);
- fbh = ds_get_height(s->ds);
+ fbw = surface_width(s->ds);
+ fbh = surface_height(s->ds);
gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh);
@@ -480,8 +505,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
int fbh, fbw;
int ww, wh;
- fbw = ds_get_width(s->ds) * s->scale_x;
- fbh = ds_get_height(s->ds) * s->scale_y;
+ fbw = surface_width(s->ds) * s->scale_x;
+ fbh = surface_height(s->ds) * s->scale_y;
gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
@@ -497,14 +522,14 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
y = (motion->y - my) / s->scale_y;
if (x < 0 || y < 0 ||
- x >= ds_get_width(s->ds) ||
- y >= ds_get_height(s->ds)) {
+ x >= surface_width(s->ds) ||
+ y >= surface_height(s->ds)) {
return TRUE;
}
if (kbd_mouse_is_absolute()) {
- dx = x * 0x7FFF / (ds_get_width(s->ds) - 1);
- dy = y * 0x7FFF / (ds_get_height(s->ds) - 1);
+ dx = x * 0x7FFF / (surface_width(s->ds) - 1);
+ dy = y * 0x7FFF / (surface_height(s->ds) - 1);
} else if (s->last_x == -1 || s->last_y == -1) {
dx = 0;
dy = 0;
@@ -585,8 +610,8 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
}
if (kbd_mouse_is_absolute()) {
- dx = s->last_x * 0x7FFF / (ds_get_width(s->ds) - 1);
- dy = s->last_y * 0x7FFF / (ds_get_height(s->ds) - 1);
+ dx = s->last_x * 0x7FFF / (surface_width(s->ds) - 1);
+ dy = s->last_y * 0x7FFF / (surface_height(s->ds) - 1);
} else {
dx = 0;
dy = 0;
@@ -715,7 +740,8 @@ static void gd_menu_full_screen(GtkMenuItem *item, void *opaque)
gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s);
gtk_widget_set_size_request(s->menu_bar, -1, -1);
gtk_widget_set_size_request(s->drawing_area,
- ds_get_width(s->ds), ds_get_height(s->ds));
+ surface_width(s->ds),
+ surface_height(s->ds));
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), FALSE);
s->full_screen = FALSE;
s->scale_x = 1.0;
@@ -735,7 +761,7 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque)
s->scale_x += .25;
s->scale_y += .25;
- gd_resize(s->ds);
+ gd_update_windowsize(s);
}
static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
@@ -751,7 +777,7 @@ static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
s->scale_x = MAX(s->scale_x, .25);
s->scale_y = MAX(s->scale_y, .25);
- gd_resize(s->ds);
+ gd_update_windowsize(s);
}
static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque)
@@ -761,13 +787,12 @@ static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque)
s->scale_x = 1.0;
s->scale_y = 1.0;
- gd_resize(s->ds);
+ gd_update_windowsize(s);
}
static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
{
GtkDisplayState *s = opaque;
- int ww, wh;
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item))) {
s->free_scale = TRUE;
@@ -775,10 +800,8 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
s->free_scale = FALSE;
}
- gd_resize(s->ds);
-
- gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
- gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh);
+ gd_update_windowsize(s);
+ gd_update_full_redraw(s);
}
static void gd_grab_keyboard(GtkDisplayState *s)
@@ -1281,17 +1304,20 @@ static void gd_create_menus(GtkDisplayState *s)
gtk_menu_shell_append(GTK_MENU_SHELL(s->menu_bar), s->view_menu_item);
}
+static const DisplayChangeListenerOps dcl_ops = {
+ .dpy_name = "gtk",
+ .dpy_gfx_update = gd_update,
+ .dpy_gfx_switch = gd_switch,
+ .dpy_refresh = gd_refresh,
+};
+
void gtk_display_init(DisplayState *ds)
{
GtkDisplayState *s = g_malloc0(sizeof(*s));
gtk_init(NULL, NULL);
- ds->opaque = s;
- s->ds = ds;
- s->dcl.dpy_gfx_update = gd_update;
- s->dcl.dpy_gfx_resize = gd_resize;
- s->dcl.dpy_refresh = gd_refresh;
+ s->dcl.ops = &dcl_ops;
s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
#if GTK_CHECK_VERSION(3, 2, 0)
diff --git a/ui/sdl.c b/ui/sdl.c
index 1657848e9f..8da05341bb 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -35,6 +35,7 @@
#include "sdl_zoom.h"
static DisplayChangeListener *dcl;
+static DisplaySurface *surface;
static SDL_Surface *real_screen;
static SDL_Surface *guest_screen = NULL;
static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
@@ -59,7 +60,8 @@ static SDL_PixelFormat host_format;
static int scaling_active = 0;
static Notifier mouse_mode_notifier;
-static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
+static void sdl_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h)
{
// printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
SDL_Rect rec;
@@ -81,16 +83,6 @@ static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h);
}
-static void sdl_setdata(DisplayState *ds)
-{
- if (guest_screen != NULL) SDL_FreeSurface(guest_screen);
-
- guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds),
- ds_get_bits_per_pixel(ds), ds_get_linesize(ds),
- ds->surface->pf.rmask, ds->surface->pf.gmask,
- ds->surface->pf.bmask, ds->surface->pf.amask);
-}
-
static void do_sdl_resize(int width, int height, int bpp)
{
int flags;
@@ -114,15 +106,32 @@ static void do_sdl_resize(int width, int height, int bpp)
}
}
-static void sdl_resize(DisplayState *ds)
+static void sdl_switch(DisplayChangeListener *dcl,
+ DisplaySurface *new_surface)
{
+
+ /* temporary hack: allows to call sdl_switch to handle scaling changes */
+ if (new_surface) {
+ surface = new_surface;
+ }
+
if (!scaling_active) {
- do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
- } else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds)) {
+ do_sdl_resize(surface_width(surface), surface_height(surface), 0);
+ } else if (real_screen->format->BitsPerPixel !=
+ surface_bits_per_pixel(surface)) {
do_sdl_resize(real_screen->w, real_screen->h,
- ds_get_bits_per_pixel(ds));
+ surface_bits_per_pixel(surface));
+ }
+
+ if (guest_screen != NULL) {
+ SDL_FreeSurface(guest_screen);
}
- sdl_setdata(ds);
+ guest_screen = SDL_CreateRGBSurfaceFrom
+ (surface_data(surface),
+ surface_width(surface), surface_height(surface),
+ surface_bits_per_pixel(surface), surface_stride(surface),
+ surface->pf.rmask, surface->pf.gmask,
+ surface->pf.bmask, surface->pf.amask);
}
/* generic keyboard conversion */
@@ -445,7 +454,7 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state
kbd_mouse_event(dx, dy, dz, buttons);
}
-static void sdl_scale(DisplayState *ds, int width, int height)
+static void sdl_scale(int width, int height)
{
int bpp = real_screen->format->BitsPerPixel;
@@ -454,32 +463,30 @@ static void sdl_scale(DisplayState *ds, int width, int height)
}
do_sdl_resize(width, height, bpp);
scaling_active = 1;
- if (!is_buffer_shared(ds->surface)) {
- ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds),
- ds_get_height(ds));
- dpy_gfx_resize(ds);
- }
}
-static void toggle_full_screen(DisplayState *ds)
+static void toggle_full_screen(void)
{
+ int width = surface_width(surface);
+ int height = surface_height(surface);
+ int bpp = surface_bits_per_pixel(surface);
+
gui_fullscreen = !gui_fullscreen;
if (gui_fullscreen) {
gui_saved_width = real_screen->w;
gui_saved_height = real_screen->h;
gui_saved_scaling = scaling_active;
- do_sdl_resize(ds_get_width(ds), ds_get_height(ds),
- ds_get_bits_per_pixel(ds));
+ do_sdl_resize(width, height, bpp);
scaling_active = 0;
gui_saved_grab = gui_grab;
sdl_grab_start();
} else {
if (gui_saved_scaling) {
- sdl_scale(ds, gui_saved_width, gui_saved_height);
+ sdl_scale(gui_saved_width, gui_saved_height);
} else {
- do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
+ do_sdl_resize(width, height, 0);
}
if (!gui_saved_grab || !is_graphic_console()) {
sdl_grab_end();
@@ -489,7 +496,7 @@ static void toggle_full_screen(DisplayState *ds)
vga_hw_update();
}
-static void handle_keydown(DisplayState *ds, SDL_Event *ev)
+static void handle_keydown(SDL_Event *ev)
{
int mod_state;
int keycode;
@@ -508,13 +515,13 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev)
keycode = sdl_keyevent_to_keycode(&ev->key);
switch (keycode) {
case 0x21: /* 'f' key on US keyboard */
- toggle_full_screen(ds);
+ toggle_full_screen();
gui_keysym = 1;
break;
case 0x16: /* 'u' key on US keyboard */
if (scaling_active) {
scaling_active = 0;
- sdl_resize(ds);
+ sdl_switch(dcl, NULL);
vga_hw_invalidate();
vga_hw_update();
}
@@ -545,9 +552,10 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev)
if (!gui_fullscreen) {
int width = MAX(real_screen->w + (keycode == 0x1b ? 50 : -50),
160);
- int height = (ds_get_height(ds) * width) / ds_get_width(ds);
+ int height = (surface_height(surface) * width) /
+ surface_width(surface);
- sdl_scale(ds, width, height);
+ sdl_scale(width, height);
vga_hw_invalidate();
vga_hw_update();
gui_keysym = 1;
@@ -634,7 +642,7 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev)
}
}
-static void handle_keyup(DisplayState *ds, SDL_Event *ev)
+static void handle_keyup(SDL_Event *ev)
{
int mod_state;
@@ -666,7 +674,7 @@ static void handle_keyup(DisplayState *ds, SDL_Event *ev)
}
}
-static void handle_mousemotion(DisplayState *ds, SDL_Event *ev)
+static void handle_mousemotion(SDL_Event *ev)
{
int max_x, max_y;
@@ -690,7 +698,7 @@ static void handle_mousemotion(DisplayState *ds, SDL_Event *ev)
}
}
-static void handle_mousebutton(DisplayState *ds, SDL_Event *ev)
+static void handle_mousebutton(SDL_Event *ev)
{
int buttonstate = SDL_GetMouseState(NULL, NULL);
SDL_MouseButtonEvent *bev;
@@ -726,7 +734,7 @@ static void handle_mousebutton(DisplayState *ds, SDL_Event *ev)
}
}
-static void handle_activation(DisplayState *ds, SDL_Event *ev)
+static void handle_activation(SDL_Event *ev)
{
#ifdef _WIN32
/* Disable grab if the window no longer has the focus
@@ -753,7 +761,7 @@ static void handle_activation(DisplayState *ds, SDL_Event *ev)
}
}
-static void sdl_refresh(DisplayState *ds)
+static void sdl_refresh(DisplayChangeListener *dcl)
{
SDL_Event ev1, *ev = &ev1;
@@ -768,13 +776,13 @@ static void sdl_refresh(DisplayState *ds)
while (SDL_PollEvent(ev)) {
switch (ev->type) {
case SDL_VIDEOEXPOSE:
- sdl_update(ds, 0, 0, real_screen->w, real_screen->h);
+ sdl_update(dcl, 0, 0, real_screen->w, real_screen->h);
break;
case SDL_KEYDOWN:
- handle_keydown(ds, ev);
+ handle_keydown(ev);
break;
case SDL_KEYUP:
- handle_keyup(ds, ev);
+ handle_keyup(ev);
break;
case SDL_QUIT:
if (!no_quit) {
@@ -783,17 +791,17 @@ static void sdl_refresh(DisplayState *ds)
}
break;
case SDL_MOUSEMOTION:
- handle_mousemotion(ds, ev);
+ handle_mousemotion(ev);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
- handle_mousebutton(ds, ev);
+ handle_mousebutton(ev);
break;
case SDL_ACTIVEEVENT:
- handle_activation(ds, ev);
+ handle_activation(ev);
break;
case SDL_VIDEORESIZE:
- sdl_scale(ds, ev->resize.w, ev->resize.h);
+ sdl_scale(ev->resize.w, ev->resize.h);
vga_hw_invalidate();
vga_hw_update();
break;
@@ -803,7 +811,8 @@ static void sdl_refresh(DisplayState *ds)
}
}
-static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on)
+static void sdl_mouse_warp(DisplayChangeListener *dcl,
+ int x, int y, int on)
{
if (on) {
if (!guest_cursor)
@@ -819,7 +828,8 @@ static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on)
guest_x = x, guest_y = y;
}
-static void sdl_mouse_define(DisplayState *ds, QEMUCursor *c)
+static void sdl_mouse_define(DisplayChangeListener *dcl,
+ QEMUCursor *c)
{
uint8_t *image, *mask;
int bpl;
@@ -849,6 +859,15 @@ static void sdl_cleanup(void)
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
+static const DisplayChangeListenerOps dcl_ops = {
+ .dpy_name = "sdl",
+ .dpy_gfx_update = sdl_update,
+ .dpy_gfx_switch = sdl_switch,
+ .dpy_refresh = sdl_refresh,
+ .dpy_mouse_set = sdl_mouse_warp,
+ .dpy_cursor_define = sdl_mouse_define,
+};
+
void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
{
int flags;
@@ -917,12 +936,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
}
dcl = g_malloc0(sizeof(DisplayChangeListener));
- dcl->dpy_gfx_update = sdl_update;
- dcl->dpy_gfx_resize = sdl_resize;
- dcl->dpy_refresh = sdl_refresh;
- dcl->dpy_gfx_setdata = sdl_setdata;
- dcl->dpy_mouse_set = sdl_mouse_warp;
- dcl->dpy_cursor_define = sdl_mouse_define;
+ dcl->ops = &dcl_ops;
register_displaychangelistener(ds, dcl);
mouse_mode_notifier.notify = sdl_mouse_mode_change;
diff --git a/ui/spice-display.c b/ui/spice-display.c
index dc7e58d0ed..eaab19d9bd 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -214,10 +214,10 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd,
static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
{
static const int blksize = 32;
- int blocks = (ds_get_width(ssd->ds) + blksize - 1) / blksize;
+ int blocks = (surface_width(ssd->ds) + blksize - 1) / blksize;
int dirty_top[blocks];
int y, yoff, x, xoff, blk, bw;
- int bpp = ds_get_bytes_per_pixel(ssd->ds);
+ int bpp = surface_bytes_per_pixel(ssd->ds);
uint8_t *guest, *mirror;
if (qemu_spice_rect_is_empty(&ssd->dirty)) {
@@ -225,19 +225,19 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
};
if (ssd->surface == NULL) {
- ssd->surface = pixman_image_ref(ds_get_image(ssd->ds));
- ssd->mirror = qemu_pixman_mirror_create(ds_get_format(ssd->ds),
- ds_get_image(ssd->ds));
+ ssd->surface = pixman_image_ref(ssd->ds->image);
+ ssd->mirror = qemu_pixman_mirror_create(ssd->ds->format,
+ ssd->ds->image);
}
for (blk = 0; blk < blocks; blk++) {
dirty_top[blk] = -1;
}
- guest = ds_get_data(ssd->ds);
+ guest = surface_data(ssd->ds);
mirror = (void *)pixman_image_get_data(ssd->mirror);
for (y = ssd->dirty.top; y < ssd->dirty.bottom; y++) {
- yoff = y * ds_get_linesize(ssd->ds);
+ yoff = y * surface_stride(ssd->ds);
for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) {
xoff = x * bpp;
blk = x / blksize;
@@ -312,11 +312,11 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
memset(&surface, 0, sizeof(surface));
dprint(1, "%s: %dx%d\n", __FUNCTION__,
- ds_get_width(ssd->ds), ds_get_height(ssd->ds));
+ surface_width(ssd->ds), surface_height(ssd->ds));
surface.format = SPICE_SURFACE_FMT_32_xRGB;
- surface.width = ds_get_width(ssd->ds);
- surface.height = ds_get_height(ssd->ds);
+ surface.width = surface_width(ssd->ds);
+ surface.height = surface_height(ssd->ds);
surface.stride = -surface.width * 4;
surface.mouse_mode = true;
surface.flags = 0;
@@ -334,9 +334,8 @@ void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
qemu_spice_destroy_primary_surface(ssd, 0, QXL_SYNC);
}
-void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds)
+void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd)
{
- ssd->ds = ds;
qemu_mutex_init(&ssd->lock);
QTAILQ_INIT(&ssd->updates);
ssd->mouse_x = -1;
@@ -367,7 +366,8 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
qemu_spice_rect_union(&ssd->dirty, &update_area);
}
-void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
+void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
+ DisplaySurface *surface)
{
SimpleSpiceUpdate *update;
@@ -382,6 +382,7 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
}
qemu_mutex_lock(&ssd->lock);
+ ssd->ds = surface;
while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) {
QTAILQ_REMOVE(&ssd->updates, update, next);
qemu_spice_destroy_update(ssd, update);
@@ -397,12 +398,14 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
{
if (ssd->cursor) {
- dpy_cursor_define(ssd->ds, ssd->cursor);
+ assert(ssd->con);
+ dpy_cursor_define(ssd->con, ssd->cursor);
cursor_put(ssd->cursor);
ssd->cursor = NULL;
}
if (ssd->mouse_x != -1 && ssd->mouse_y != -1) {
- dpy_mouse_set(ssd->ds, ssd->mouse_x, ssd->mouse_y, 1);
+ assert(ssd->con);
+ dpy_mouse_set(ssd->con, ssd->mouse_x, ssd->mouse_y, 1);
ssd->mouse_x = -1;
ssd->mouse_y = -1;
}
@@ -414,7 +417,7 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
vga_hw_update();
qemu_mutex_lock(&ssd->lock);
- if (QTAILQ_EMPTY(&ssd->updates)) {
+ if (QTAILQ_EMPTY(&ssd->updates) && ssd->ds) {
qemu_spice_create_update(ssd);
ssd->notify++;
}
@@ -581,39 +584,47 @@ static const QXLInterface dpy_interface = {
.client_monitors_config = interface_client_monitors_config,
};
-static SimpleSpiceDisplay sdpy;
-
-static void display_update(struct DisplayState *ds, int x, int y, int w, int h)
+static void display_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h)
{
- qemu_spice_display_update(&sdpy, x, y, w, h);
+ SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
+ qemu_spice_display_update(ssd, x, y, w, h);
}
-static void display_resize(struct DisplayState *ds)
+static void display_switch(DisplayChangeListener *dcl,
+ struct DisplaySurface *surface)
{
- qemu_spice_display_resize(&sdpy);
+ SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
+ qemu_spice_display_switch(ssd, surface);
}
-static void display_refresh(struct DisplayState *ds)
+static void display_refresh(DisplayChangeListener *dcl)
{
- qemu_spice_display_refresh(&sdpy);
+ SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
+ qemu_spice_display_refresh(ssd);
}
-static DisplayChangeListener display_listener = {
+static const DisplayChangeListenerOps display_listener_ops = {
+ .dpy_name = "spice",
.dpy_gfx_update = display_update,
- .dpy_gfx_resize = display_resize,
- .dpy_refresh = display_refresh,
+ .dpy_gfx_switch = display_switch,
+ .dpy_refresh = display_refresh,
};
void qemu_spice_display_init(DisplayState *ds)
{
- assert(sdpy.ds == NULL);
- qemu_spice_display_init_common(&sdpy, ds);
+ SimpleSpiceDisplay *ssd = g_new0(SimpleSpiceDisplay, 1);
+
+ qemu_spice_display_init_common(ssd);
+
+ ssd->qxl.base.sif = &dpy_interface.base;
+ qemu_spice_add_interface(&ssd->qxl.base);
+ assert(ssd->worker);
- sdpy.qxl.base.sif = &dpy_interface.base;
- qemu_spice_add_interface(&sdpy.qxl.base);
- assert(sdpy.worker);
+ qemu_spice_create_host_memslot(ssd);
- qemu_spice_create_host_memslot(&sdpy);
- qemu_spice_create_host_primary(&sdpy);
- register_displaychangelistener(ds, &display_listener);
+ ssd->dcl.ops = &display_listener_ops;
+ register_displaychangelistener(ds, &ssd->dcl);
+
+ qemu_spice_create_host_primary(ssd);
}
diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 4ddea7d4f5..e6966aebc3 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -123,7 +123,7 @@ static bool tight_can_send_png_rect(VncState *vs, int w, int h)
return false;
}
- if (ds_get_bytes_per_pixel(vs->ds) == 1 ||
+ if (surface_bytes_per_pixel(vs->vd->ds) == 1 ||
vs->client_pf.bytes_per_pixel == 1) {
return false;
}
@@ -301,7 +301,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h)
return 0;
}
- if (ds_get_bytes_per_pixel(vs->ds) == 1 ||
+ if (surface_bytes_per_pixel(vs->vd->ds) == 1 ||
vs->client_pf.bytes_per_pixel == 1 ||
w < VNC_TIGHT_DETECT_MIN_WIDTH || h < VNC_TIGHT_DETECT_MIN_HEIGHT) {
return 0;
@@ -1184,8 +1184,9 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality)
uint8_t *buf;
int dy;
- if (ds_get_bytes_per_pixel(vs->ds) == 1)
+ if (surface_bytes_per_pixel(vs->vd->ds) == 1) {
return send_full_color_rect(vs, x, y, w, h);
+ }
buffer_reserve(&vs->tight.jpeg, 2048);
diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c
index 0bfc0c5485..2d3fce8155 100644
--- a/ui/vnc-jobs.c
+++ b/ui/vnc-jobs.c
@@ -183,7 +183,6 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local)
{
local->vnc_encoding = orig->vnc_encoding;
local->features = orig->features;
- local->ds = orig->ds;
local->vd = orig->vd;
local->lossy_rect = orig->lossy_rect;
local->write_pixels = orig->write_pixels;
diff --git a/ui/vnc.c b/ui/vnc.c
index ff4e2ae586..bbe1e0f179 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -44,7 +44,6 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
#include "d3des.h"
static VncDisplay *vnc_display; /* needed for info vnc */
-static DisplayChangeListener *dcl;
static int vnc_cursor_define(VncState *vs);
static void vnc_release_modifiers(VncState *vs);
@@ -430,13 +429,14 @@ static void framebuffer_update_request(VncState *vs, int incremental,
static void vnc_refresh(void *opaque);
static int vnc_refresh_server_surface(VncDisplay *vd);
-static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
+static void vnc_dpy_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h)
{
int i;
- VncDisplay *vd = ds->opaque;
+ VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
struct VncSurface *s = &vd->guest;
- int width = ds_get_width(ds);
- int height = ds_get_height(ds);
+ int width = surface_width(vd->ds);
+ int height = surface_height(vd->ds);
h += y;
@@ -518,17 +518,17 @@ void buffer_advance(Buffer *buf, size_t len)
static void vnc_desktop_resize(VncState *vs)
{
- DisplayState *ds = vs->ds;
+ DisplaySurface *ds = vs->vd->ds;
if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
return;
}
- if (vs->client_width == ds_get_width(ds) &&
- vs->client_height == ds_get_height(ds)) {
+ if (vs->client_width == surface_width(ds) &&
+ vs->client_height == surface_height(ds)) {
return;
}
- vs->client_width = ds_get_width(ds);
- vs->client_height = ds_get_height(ds);
+ vs->client_width = surface_width(ds);
+ vs->client_height = surface_height(ds);
vnc_lock_output(vs);
vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
vnc_write_u8(vs, 0);
@@ -573,18 +573,20 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
return ptr;
}
-static void vnc_dpy_resize(DisplayState *ds)
+static void vnc_dpy_switch(DisplayChangeListener *dcl,
+ DisplaySurface *surface)
{
- VncDisplay *vd = ds->opaque;
+ VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
VncState *vs;
vnc_abort_display_jobs(vd);
/* server surface */
qemu_pixman_image_unref(vd->server);
+ vd->ds = surface;
vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT,
- ds_get_width(ds),
- ds_get_height(ds),
+ surface_width(vd->ds),
+ surface_height(vd->ds),
NULL, 0);
/* guest surface */
@@ -593,8 +595,8 @@ static void vnc_dpy_resize(DisplayState *ds)
console_color_init(ds);
#endif
qemu_pixman_image_unref(vd->guest.fb);
- vd->guest.fb = pixman_image_ref(ds->surface->image);
- vd->guest.format = ds->surface->format;
+ vd->guest.fb = pixman_image_ref(surface->image);
+ vd->guest.format = surface->format;
memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty));
QTAILQ_FOREACH(vs, &vd->clients, next) {
@@ -735,9 +737,11 @@ static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, i
vnc_flush(vs);
}
-static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
+static void vnc_dpy_copy(DisplayChangeListener *dcl,
+ int src_x, int src_y,
+ int dst_x, int dst_y, int w, int h)
{
- VncDisplay *vd = ds->opaque;
+ VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
VncState *vs, *vn;
uint8_t *src_row;
uint8_t *dst_row;
@@ -806,7 +810,8 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int
}
}
-static void vnc_mouse_set(DisplayState *ds, int x, int y, int visible)
+static void vnc_mouse_set(DisplayChangeListener *dcl,
+ int x, int y, int visible)
{
/* can we ask the client(s) to move the pointer ??? */
}
@@ -832,7 +837,8 @@ static int vnc_cursor_define(VncState *vs)
return -1;
}
-static void vnc_dpy_cursor_define(DisplayState *ds, QEMUCursor *c)
+static void vnc_dpy_cursor_define(DisplayChangeListener *dcl,
+ QEMUCursor *c)
{
VncDisplay *vd = vnc_display;
VncState *vs;
@@ -1059,7 +1065,7 @@ void vnc_disconnect_finish(VncState *vs)
}
if (QTAILQ_EMPTY(&vs->vd->clients)) {
- dcl->idle = 1;
+ vs->vd->dcl.idle = 1;
}
vnc_remove_timer(vs->vd);
@@ -1453,7 +1459,8 @@ static void check_pointer_type_change(Notifier *notifier, void *data)
vnc_write_u8(vs, 0);
vnc_write_u16(vs, 1);
vnc_framebuffer_update(vs, absolute, 0,
- ds_get_width(vs->ds), ds_get_height(vs->ds),
+ surface_width(vs->vd->ds),
+ surface_height(vs->vd->ds),
VNC_ENCODING_POINTER_TYPE_CHANGE);
vnc_unlock_output(vs);
vnc_flush(vs);
@@ -1465,6 +1472,8 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
{
int buttons = 0;
int dz = 0;
+ int width = surface_width(vs->vd->ds);
+ int height = surface_height(vs->vd->ds);
if (button_mask & 0x01)
buttons |= MOUSE_EVENT_LBUTTON;
@@ -1478,10 +1487,8 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
dz = 1;
if (vs->absolute) {
- kbd_mouse_event(ds_get_width(vs->ds) > 1 ?
- x * 0x7FFF / (ds_get_width(vs->ds) - 1) : 0x4000,
- ds_get_height(vs->ds) > 1 ?
- y * 0x7FFF / (ds_get_height(vs->ds) - 1) : 0x4000,
+ kbd_mouse_event(width > 1 ? x * 0x7FFF / (width - 1) : 0x4000,
+ height > 1 ? y * 0x7FFF / (height - 1) : 0x4000,
dz, buttons);
} else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
x -= 0x7FFF;
@@ -1771,12 +1778,15 @@ static void framebuffer_update_request(VncState *vs, int incremental,
int w, int h)
{
int i;
- const size_t width = ds_get_width(vs->ds) / 16;
+ const size_t width = surface_width(vs->vd->ds) / 16;
+ const size_t height = surface_height(vs->vd->ds);
- if (y_position > ds_get_height(vs->ds))
- y_position = ds_get_height(vs->ds);
- if (y_position + h >= ds_get_height(vs->ds))
- h = ds_get_height(vs->ds) - y_position;
+ if (y_position > height) {
+ y_position = height;
+ }
+ if (y_position + h >= height) {
+ h = height - y_position;
+ }
vs->need_update = 1;
if (!incremental) {
@@ -1795,7 +1805,9 @@ static void send_ext_key_event_ack(VncState *vs)
vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
vnc_write_u8(vs, 0);
vnc_write_u16(vs, 1);
- vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
+ vnc_framebuffer_update(vs, 0, 0,
+ surface_width(vs->vd->ds),
+ surface_height(vs->vd->ds),
VNC_ENCODING_EXT_KEY_EVENT);
vnc_unlock_output(vs);
vnc_flush(vs);
@@ -1807,7 +1819,9 @@ static void send_ext_audio_ack(VncState *vs)
vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
vnc_write_u8(vs, 0);
vnc_write_u16(vs, 1);
- vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
+ vnc_framebuffer_update(vs, 0, 0,
+ surface_width(vs->vd->ds),
+ surface_height(vs->vd->ds),
VNC_ENCODING_AUDIO);
vnc_unlock_output(vs);
vnc_flush(vs);
@@ -1972,16 +1986,6 @@ static void pixel_format_message (VncState *vs) {
vs->write_pixels = vnc_write_pixels_copy;
}
-static void vnc_dpy_setdata(DisplayState *ds)
-{
- VncDisplay *vd = ds->opaque;
-
- qemu_pixman_image_unref(vd->guest.fb);
- vd->guest.fb = pixman_image_ref(ds->surface->image);
- vd->guest.format = ds->surface->format;
- vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
-}
-
static void vnc_colordepth(VncState *vs)
{
if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) {
@@ -1990,8 +1994,10 @@ static void vnc_colordepth(VncState *vs)
vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
vnc_write_u8(vs, 0);
vnc_write_u16(vs, 1); /* number of rects */
- vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
- ds_get_height(vs->ds), VNC_ENCODING_WMVi);
+ vnc_framebuffer_update(vs, 0, 0,
+ surface_width(vs->vd->ds),
+ surface_height(vs->vd->ds),
+ VNC_ENCODING_WMVi);
pixel_format_message(vs);
vnc_unlock_output(vs);
vnc_flush(vs);
@@ -2207,8 +2213,8 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
}
vnc_set_share_mode(vs, mode);
- vs->client_width = ds_get_width(vs->ds);
- vs->client_height = ds_get_height(vs->ds);
+ vs->client_width = surface_width(vs->vd->ds);
+ vs->client_height = surface_height(vs->vd->ds);
vnc_write_u16(vs, vs->client_width);
vnc_write_u16(vs, vs->client_height);
@@ -2686,7 +2692,7 @@ static void vnc_init_timer(VncDisplay *vd)
vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) {
vd->timer = qemu_new_timer_ms(rt_clock, vnc_refresh, vd);
- vnc_dpy_resize(vd->ds);
+ vga_hw_update();
vnc_refresh(vd);
}
}
@@ -2725,7 +2731,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket)
}
VNC_DEBUG("New client on socket %d\n", csock);
- dcl->idle = 0;
+ vd->dcl.idle = 0;
socket_set_nonblock(vs->csock);
#ifdef CONFIG_VNC_WS
if (websocket) {
@@ -2756,7 +2762,6 @@ void vnc_init_state(VncState *vs)
vs->initialized = true;
VncDisplay *vd = vs->vd;
- vs->ds = vd->ds;
vs->last_x = -1;
vs->last_y = -1;
@@ -2822,14 +2827,20 @@ static void vnc_listen_websocket_read(void *opaque)
}
#endif /* CONFIG_VNC_WS */
+static const DisplayChangeListenerOps dcl_ops = {
+ .dpy_name = "vnc",
+ .dpy_gfx_copy = vnc_dpy_copy,
+ .dpy_gfx_update = vnc_dpy_update,
+ .dpy_gfx_switch = vnc_dpy_switch,
+ .dpy_mouse_set = vnc_mouse_set,
+ .dpy_cursor_define = vnc_dpy_cursor_define,
+};
+
void vnc_display_init(DisplayState *ds)
{
VncDisplay *vs = g_malloc0(sizeof(*vs));
- dcl = g_malloc0(sizeof(DisplayChangeListener));
-
- ds->opaque = vs;
- dcl->idle = 1;
+ vs->dcl.idle = 1;
vnc_display = vs;
vs->lsock = -1;
@@ -2837,7 +2848,6 @@ void vnc_display_init(DisplayState *ds)
vs->lwebsock = -1;
#endif
- vs->ds = ds;
QTAILQ_INIT(&vs->clients);
vs->expires = TIME_MAX;
@@ -2852,19 +2862,14 @@ void vnc_display_init(DisplayState *ds)
qemu_mutex_init(&vs->mutex);
vnc_start_worker_thread();
- dcl->dpy_gfx_copy = vnc_dpy_copy;
- dcl->dpy_gfx_update = vnc_dpy_update;
- dcl->dpy_gfx_resize = vnc_dpy_resize;
- dcl->dpy_gfx_setdata = vnc_dpy_setdata;
- dcl->dpy_mouse_set = vnc_mouse_set;
- dcl->dpy_cursor_define = vnc_dpy_cursor_define;
- register_displaychangelistener(ds, dcl);
+ vs->dcl.ops = &dcl_ops;
+ register_displaychangelistener(ds, &vs->dcl);
}
static void vnc_display_close(DisplayState *ds)
{
- VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+ VncDisplay *vs = vnc_display;
if (!vs)
return;
@@ -2895,7 +2900,7 @@ static void vnc_display_close(DisplayState *ds)
static int vnc_display_disable_login(DisplayState *ds)
{
- VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+ VncDisplay *vs = vnc_display;
if (!vs) {
return -1;
@@ -2915,7 +2920,7 @@ static int vnc_display_disable_login(DisplayState *ds)
int vnc_display_password(DisplayState *ds, const char *password)
{
- VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+ VncDisplay *vs = vnc_display;
if (!vs) {
return -EINVAL;
@@ -2941,7 +2946,7 @@ int vnc_display_password(DisplayState *ds, const char *password)
int vnc_display_pw_expire(DisplayState *ds, time_t expires)
{
- VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+ VncDisplay *vs = vnc_display;
if (!vs) {
return -EINVAL;
@@ -2953,14 +2958,14 @@ int vnc_display_pw_expire(DisplayState *ds, time_t expires)
char *vnc_display_local_addr(DisplayState *ds)
{
- VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+ VncDisplay *vs = vnc_display;
return vnc_socket_local_addr("%s:%s", vs->lsock);
}
void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
{
- VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+ VncDisplay *vs = vnc_display;
const char *options;
int password = 0;
int reverse = 0;
@@ -3266,7 +3271,7 @@ fail:
void vnc_display_add_client(DisplayState *ds, int csock, int skipauth)
{
- VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+ VncDisplay *vs = vnc_display;
vnc_connect(vs, csock, skipauth, 0);
}
diff --git a/ui/vnc.h b/ui/vnc.h
index 45d7686843..58e002eed3 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -150,7 +150,8 @@ struct VncDisplay
bool websocket;
char *ws_display;
#endif
- DisplayState *ds;
+ DisplaySurface *ds;
+ DisplayChangeListener dcl;
kbd_layout_t *kbd_layout;
int lock_key_sync;
QemuMutex mutex;
@@ -247,7 +248,6 @@ struct VncState
{
int csock;
- DisplayState *ds;
DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_DIRTY_BITS);
uint8_t **lossy_rect; /* Not an Array to avoid costly memcpy in
* vnc-jobs-async.c */
diff --git a/util/Makefile.objs b/util/Makefile.objs
index cad5ce87db..557bda7a15 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -9,3 +9,4 @@ util-obj-y += error.o qemu-error.o
util-obj-$(CONFIG_POSIX) += compatfd.o
util-obj-y += iov.o aes.o qemu-config.o qemu-sockets.o uri.o notify.o
util-obj-y += qemu-option.o qemu-progress.o
+util-obj-y += hexdump.o
diff --git a/util/hexdump.c b/util/hexdump.c
new file mode 100644
index 0000000000..0d0efc86de
--- /dev/null
+++ b/util/hexdump.c
@@ -0,0 +1,37 @@
+/*
+ * Helper to hexdump a buffer
+ *
+ * Copyright (c) 2013 Red Hat, Inc.
+ * Copyright (c) 2013 Gerd Hoffmann <kraxel@redhat.com>
+ * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
+ * Copyright (c) 2013 Xilinx, Inc
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "qemu-common.h"
+
+void hexdump(const char *buf, FILE *fp, const char *prefix, size_t size)
+{
+ unsigned int b;
+
+ for (b = 0; b < size; b++) {
+ if ((b % 16) == 0) {
+ fprintf(fp, "%s: %04x:", prefix, b);
+ }
+ if ((b % 4) == 0) {
+ fprintf(fp, " ");
+ }
+ fprintf(fp, " %02x", (unsigned char)buf[b]);
+ if ((b % 16) == 15) {
+ fprintf(fp, "\n");
+ }
+ }
+ if ((b % 16) != 0) {
+ fprintf(fp, "\n");
+ }
+}
diff --git a/util/iov.c b/util/iov.c
index fbe675d373..9dae318197 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -201,32 +201,18 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
FILE *fp, const char *prefix, size_t limit)
{
- unsigned int i, v, b;
- uint8_t *c;
-
- c = iov[0].iov_base;
- for (i = 0, v = 0, b = 0; b < limit; i++, b++) {
- if (i == iov[v].iov_len) {
- i = 0; v++;
- if (v == iov_cnt) {
- break;
- }
- c = iov[v].iov_base;
- }
- if ((b % 16) == 0) {
- fprintf(fp, "%s: %04x:", prefix, b);
- }
- if ((b % 4) == 0) {
- fprintf(fp, " ");
- }
- fprintf(fp, " %02x", c[i]);
- if ((b % 16) == 15) {
- fprintf(fp, "\n");
- }
- }
- if ((b % 16) != 0) {
- fprintf(fp, "\n");
+ int v;
+ size_t size = 0;
+ char *buf;
+
+ for (v = 0; v < iov_cnt; v++) {
+ size += iov[v].iov_len;
}
+ size = size > limit ? limit : size;
+ buf = g_malloc(size);
+ iov_to_buf(iov, iov_cnt, 0, buf, size);
+ hexdump(buf, fp, prefix, size);
+ g_free(buf);
}
unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt,
diff --git a/vl.c b/vl.c
index a621aec0a4..ce51e65368 100644
--- a/vl.c
+++ b/vl.c
@@ -1639,13 +1639,13 @@ void gui_setup_refresh(DisplayState *ds)
bool have_text = false;
QLIST_FOREACH(dcl, &ds->listeners, next) {
- if (dcl->dpy_refresh != NULL) {
+ if (dcl->ops->dpy_refresh != NULL) {
need_timer = true;
}
- if (dcl->dpy_gfx_update != NULL) {
+ if (dcl->ops->dpy_gfx_update != NULL) {
have_gfx = true;
}
- if (dcl->dpy_text_update != NULL) {
+ if (dcl->ops->dpy_text_update != NULL) {
have_text = true;
}
}