From 3232794bcb77940dd7167abb8cc72897883523f6 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Tue, 3 Jul 2018 20:10:43 +0100 Subject: ppc: fix default VGA display for Mac machines Commit 29f9cef39e "ppc: Include vga cirrus card into the compiling process" changed the default display adapter for all PPC machines to cirrus. Unfortunately it missed setting the default display type to stdvga for both Mac machines causing the display to fail to initialise under OpenBIOS. Update the MachineClass for both Old World and New World Macs so that the default std(vga) display adapter is the default if no options are specified which fixes the display for the Mac machines. Signed-off-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/ppc/mac_newworld.c | 1 + hw/ppc/mac_oldworld.c | 1 + 2 files changed, 2 insertions(+) (limited to 'hw') diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index d119801..2ca2946 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -525,6 +525,7 @@ static void core99_machine_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_IDE; mc->max_cpus = MAX_CPUS; mc->default_boot_order = "cd"; + mc->default_display = "std"; mc->kvm_type = core99_kvm_type; #ifdef TARGET_PPC64 mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("970fx_v3.1"); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 06ed6f6..064d7eb 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -383,6 +383,7 @@ static void heathrow_class_init(ObjectClass *oc, void *data) mc->default_boot_order = "cd"; mc->kvm_type = heathrow_kvm_type; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("750_v3.1"); + mc->default_display = "std"; } static const TypeInfo ppc_heathrow_machine_info = { -- cgit v1.1 From 9e3a83a15b4d94e7738464e92b6c5cb335961ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 3 Jul 2018 17:23:59 +0200 Subject: spapr/vio: quiet down the "irq" property accessors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit efe2add7cb7f ("spapr/vio: deprecate the "irq" property") introduced get/set accessors for the "irq" property to warn of its usage, but the warning in the get pollutes the monitor 'info qtree'. Signed-off-by: Cédric Le Goater Signed-off-by: David Gibson --- hw/ppc/spapr_vio.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index daf8513..be9af71 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -43,7 +43,16 @@ #include -static void spapr_vio_getset_irq(Object *obj, Visitor *v, const char *name, +static void spapr_vio_get_irq(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + Property *prop = opaque; + uint32_t *ptr = qdev_get_prop_ptr(DEVICE(obj), prop); + + visit_type_uint32(v, name, ptr, errp); +} + +static void spapr_vio_set_irq(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { Property *prop = opaque; @@ -57,8 +66,8 @@ static void spapr_vio_getset_irq(Object *obj, Visitor *v, const char *name, static const PropertyInfo spapr_vio_irq_propinfo = { .name = "irq", - .get = spapr_vio_getset_irq, - .set = spapr_vio_getset_irq, + .get = spapr_vio_get_irq, + .set = spapr_vio_set_irq, }; static Property spapr_vio_props[] = { -- cgit v1.1 From 4a1f253adb45ac6019971193d5077c4d5d55886a Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 4 Jul 2018 11:40:58 +0200 Subject: sm501: Implement i2c part for reading monitor EDID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Emulate the i2c part of SM501 which is used to access the EDID info from a monitor. The vmstate structure is changed and its version is increased but SM501 is only used on SH and PPC sam460ex machines that don't support cross-version migration. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/display/sm501.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 143 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 9dec0d3..05c964b 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qapi/error.h" +#include "qemu/log.h" #include "qemu-common.h" #include "cpu.h" #include "hw/hw.h" @@ -34,6 +35,8 @@ #include "hw/devices.h" #include "hw/sysbus.h" #include "hw/pci/pci.h" +#include "hw/i2c/i2c.h" +#include "hw/i2c/i2c-ddc.h" #include "qemu/range.h" #include "ui/pixel_ops.h" @@ -216,6 +219,14 @@ #define SM501_I2C_SLAVE_ADDRESS (0x03) #define SM501_I2C_DATA (0x04) +#define SM501_I2C_CONTROL_START (1 << 2) +#define SM501_I2C_CONTROL_ENABLE (1 << 0) + +#define SM501_I2C_STATUS_COMPLETE (1 << 3) +#define SM501_I2C_STATUS_ERROR (1 << 2) + +#define SM501_I2C_RESET_ERROR (1 << 2) + /* SSP base */ #define SM501_SSP (0x020000) @@ -471,10 +482,12 @@ typedef struct SM501State { MemoryRegion local_mem_region; MemoryRegion mmio_region; MemoryRegion system_config_region; + MemoryRegion i2c_region; MemoryRegion disp_ctrl_region; MemoryRegion twoD_engine_region; uint32_t last_width; uint32_t last_height; + I2CBus *i2c_bus; /* mmio registers */ uint32_t system_control; @@ -487,6 +500,11 @@ typedef struct SM501State { uint32_t misc_timing; uint32_t power_mode_control; + uint8_t i2c_byte_count; + uint8_t i2c_status; + uint8_t i2c_addr; + uint8_t i2c_data[16]; + uint32_t uart0_ier; uint32_t uart0_lcr; uint32_t uart0_mcr; @@ -897,6 +915,109 @@ static const MemoryRegionOps sm501_system_config_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +static uint64_t sm501_i2c_read(void *opaque, hwaddr addr, unsigned size) +{ + SM501State *s = (SM501State *)opaque; + uint8_t ret = 0; + + switch (addr) { + case SM501_I2C_BYTE_COUNT: + ret = s->i2c_byte_count; + break; + case SM501_I2C_STATUS: + ret = s->i2c_status; + break; + case SM501_I2C_SLAVE_ADDRESS: + ret = s->i2c_addr; + break; + case SM501_I2C_DATA ... SM501_I2C_DATA + 15: + ret = s->i2c_data[addr - SM501_I2C_DATA]; + break; + default: + qemu_log_mask(LOG_UNIMP, "sm501 i2c : not implemented register read." + " addr=0x%" HWADDR_PRIx "\n", addr); + } + + SM501_DPRINTF("sm501 i2c regs : read addr=%" HWADDR_PRIx " val=%x\n", + addr, ret); + return ret; +} + +static void sm501_i2c_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ + SM501State *s = (SM501State *)opaque; + SM501_DPRINTF("sm501 i2c regs : write addr=%" HWADDR_PRIx + " val=%" PRIx64 "\n", addr, value); + + switch (addr) { + case SM501_I2C_BYTE_COUNT: + s->i2c_byte_count = value & 0xf; + break; + case SM501_I2C_CONTROL: + if (value & SM501_I2C_CONTROL_ENABLE) { + if (value & SM501_I2C_CONTROL_START) { + int res = i2c_start_transfer(s->i2c_bus, + s->i2c_addr >> 1, + s->i2c_addr & 1); + s->i2c_status |= (res ? SM501_I2C_STATUS_ERROR : 0); + if (!res) { + int i; + SM501_DPRINTF("sm501 i2c : transferring %d bytes to 0x%x\n", + s->i2c_byte_count + 1, s->i2c_addr >> 1); + for (i = 0; i <= s->i2c_byte_count; i++) { + res = i2c_send_recv(s->i2c_bus, &s->i2c_data[i], + !(s->i2c_addr & 1)); + if (res) { + SM501_DPRINTF("sm501 i2c : transfer failed" + " i=%d, res=%d\n", i, res); + s->i2c_status |= (res ? SM501_I2C_STATUS_ERROR : 0); + return; + } + } + if (i) { + SM501_DPRINTF("sm501 i2c : transferred %d bytes\n", i); + s->i2c_status = SM501_I2C_STATUS_COMPLETE; + } + } + } else { + SM501_DPRINTF("sm501 i2c : end transfer\n"); + i2c_end_transfer(s->i2c_bus); + s->i2c_status &= ~SM501_I2C_STATUS_ERROR; + } + } + break; + case SM501_I2C_RESET: + if ((value & SM501_I2C_RESET_ERROR) == 0) { + s->i2c_status &= ~SM501_I2C_STATUS_ERROR; + } + break; + case SM501_I2C_SLAVE_ADDRESS: + s->i2c_addr = value & 0xff; + break; + case SM501_I2C_DATA ... SM501_I2C_DATA + 15: + s->i2c_data[addr - SM501_I2C_DATA] = value & 0xff; + break; + default: + qemu_log_mask(LOG_UNIMP, "sm501 i2c : not implemented register write. " + "addr=0x%" HWADDR_PRIx " val=%" PRIx64 "\n", addr, value); + } +} + +static const MemoryRegionOps sm501_i2c_ops = { + .read = sm501_i2c_read, + .write = sm501_i2c_write, + .valid = { + .min_access_size = 1, + .max_access_size = 1, + }, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + static uint32_t sm501_palette_read(void *opaque, hwaddr addr) { SM501State *s = (SM501State *)opaque; @@ -1577,6 +1698,10 @@ static void sm501_reset(SM501State *s) s->irq_mask = 0; s->misc_timing = 0; s->power_mode_control = 0; + s->i2c_byte_count = 0; + s->i2c_status = 0; + s->i2c_addr = 0; + memset(s->i2c_data, 0, 16); s->dc_panel_control = 0x00010000; /* FIFO level 3 */ s->dc_video_control = 0; s->dc_crt_control = 0x00010000; @@ -1615,6 +1740,12 @@ static void sm501_init(SM501State *s, DeviceState *dev, memory_region_set_log(&s->local_mem_region, true, DIRTY_MEMORY_VGA); s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region); + /* i2c */ + s->i2c_bus = i2c_init_bus(dev, "sm501.i2c"); + /* ddc */ + I2CDDCState *ddc = I2CDDC(qdev_create(BUS(s->i2c_bus), TYPE_I2CDDC)); + i2c_set_slave_address(I2C_SLAVE(ddc), 0x50); + /* mmio */ memory_region_init(&s->mmio_region, OBJECT(dev), "sm501.mmio", MMIO_SIZE); memory_region_init_io(&s->system_config_region, OBJECT(dev), @@ -1622,6 +1753,9 @@ static void sm501_init(SM501State *s, DeviceState *dev, "sm501-system-config", 0x6c); memory_region_add_subregion(&s->mmio_region, SM501_SYS_CONFIG, &s->system_config_region); + memory_region_init_io(&s->i2c_region, OBJECT(dev), &sm501_i2c_ops, s, + "sm501-i2c", 0x14); + memory_region_add_subregion(&s->mmio_region, SM501_I2C, &s->i2c_region); memory_region_init_io(&s->disp_ctrl_region, OBJECT(dev), &sm501_disp_ctrl_ops, s, "sm501-disp-ctrl", 0x1000); @@ -1705,6 +1839,11 @@ static const VMStateDescription vmstate_sm501_state = { VMSTATE_UINT32(twoD_destination_base, SM501State), VMSTATE_UINT32(twoD_alpha, SM501State), VMSTATE_UINT32(twoD_wrap, SM501State), + /* Added in version 2 */ + VMSTATE_UINT8(i2c_byte_count, SM501State), + VMSTATE_UINT8(i2c_status, SM501State), + VMSTATE_UINT8(i2c_addr, SM501State), + VMSTATE_UINT8_ARRAY(i2c_data, SM501State, 16), VMSTATE_END_OF_LIST() } }; @@ -1770,8 +1909,8 @@ static void sm501_reset_sysbus(DeviceState *dev) static const VMStateDescription vmstate_sm501_sysbus = { .name = TYPE_SYSBUS_SM501, - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { VMSTATE_STRUCT(state, SM501SysBusState, 1, vmstate_sm501_state, SM501State), @@ -1843,8 +1982,8 @@ static void sm501_reset_pci(DeviceState *dev) static const VMStateDescription vmstate_sm501_pci = { .name = TYPE_PCI_SM501, - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(parent_obj, SM501PCIState), VMSTATE_STRUCT(state, SM501PCIState, 1, -- cgit v1.1 From d27335592a187de0ba77894b522025827907038c Mon Sep 17 00:00:00 2001 From: Sebastian Bauer Date: Wed, 4 Jul 2018 11:40:58 +0200 Subject: sm501: Perform a full update after palette change Changing the palette of a color index has as an immediate effect on all pixels with the corresponding index on real hardware. Performing a full update after a palette change is a simple way to emulate this effect. Signed-off-by: Sebastian Bauer Signed-off-by: BALATON Zoltan Signed-off-by: David Gibson --- hw/display/sm501.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'hw') diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 05c964b..b095134 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -487,6 +487,7 @@ typedef struct SM501State { MemoryRegion twoD_engine_region; uint32_t last_width; uint32_t last_height; + bool do_full_update; /* perform a full update next time */ I2CBus *i2c_bus; /* mmio registers */ @@ -1042,6 +1043,7 @@ static void sm501_palette_write(void *opaque, hwaddr addr, assert(range_covers_byte(0, 0x400 * 3, addr)); *(uint32_t *)&s->dc_palette[addr] = value; + s->do_full_update = true; } static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr, @@ -1630,6 +1632,12 @@ static void sm501_update_display(void *opaque) full_update = 1; } + /* someone else requested a full update */ + if (s->do_full_update) { + s->do_full_update = false; + full_update = 1; + } + /* draw each line according to conditions */ snap = memory_region_snapshot_and_clear_dirty(&s->local_mem_region, offset, width * height * src_bpp, DIRTY_MEMORY_VGA); -- cgit v1.1 From 54b2a4339ccae45d4264c2437978abd04ff82bca Mon Sep 17 00:00:00 2001 From: Sebastian Bauer Date: Wed, 4 Jul 2018 11:40:58 +0200 Subject: sm501: Use values from the pitch register for 2D operations Before, crt_h_total was used for src_width and dst_width. This is a property of the current display setting and not relevant for the 2D operation that also can be done off-screen. The pitch register's purpose is to describe line pitch relevant of the 2D operation. Signed-off-by: Sebastian Bauer Signed-off-by: BALATON Zoltan Signed-off-by: David Gibson --- hw/display/sm501.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/display/sm501.c b/hw/display/sm501.c index b095134..d4878f0 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -709,8 +709,8 @@ static void sm501_2d_operation(SM501State *s) /* get frame buffer info */ uint8_t *src = s->local_mem + (s->twoD_source_base & 0x03FFFFFF); uint8_t *dst = s->local_mem + (s->twoD_destination_base & 0x03FFFFFF); - int src_width = (s->dc_crt_h_total & 0x00000FFF) + 1; - int dst_width = (s->dc_crt_h_total & 0x00000FFF) + 1; + int src_width = s->twoD_pitch & 0x1FFF; + int dst_width = (s->twoD_pitch >> 16) & 0x1FFF; if (addressing != 0x0) { printf("%s: only XY addressing is supported.\n", __func__); -- cgit v1.1 From debc7e7dad1e70c03d585d96625da0038eba375c Mon Sep 17 00:00:00 2001 From: Sebastian Bauer Date: Wed, 4 Jul 2018 11:40:58 +0200 Subject: sm501: Implement negated destination raster operation mode Add support for the negated destination operation mode. This is used e.g. by AmigaOS for the INVERSEVID drawing mode. With this change, the cursor in the shell and non-immediate window adjustment are working now. Signed-off-by: BALATON Zoltan Signed-off-by: David Gibson --- hw/display/sm501.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/display/sm501.c b/hw/display/sm501.c index d4878f0..0b44d95 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -705,6 +705,8 @@ static void sm501_2d_operation(SM501State *s) uint32_t color = s->twoD_foreground; int format_flags = (s->twoD_stretch >> 20) & 0x3; int addressing = (s->twoD_stretch >> 16) & 0xF; + int rop_mode = (s->twoD_control >> 15) & 0x1; /* 1 for rop2, else rop3 */ + int rop = s->twoD_control & 0xFF; /* get frame buffer info */ uint8_t *src = s->local_mem + (s->twoD_source_base & 0x03FFFFFF); @@ -729,6 +731,8 @@ static void sm501_2d_operation(SM501State *s) int y, x, index_d, index_s; \ for (y = 0; y < operation_height; y++) { \ for (x = 0; x < operation_width; x++) { \ + _pixel_type val; \ + \ if (rtl) { \ index_s = ((src_y - y) * src_width + src_x - x) * _bpp; \ index_d = ((dst_y - y) * dst_width + dst_x - x) * _bpp; \ @@ -736,7 +740,13 @@ static void sm501_2d_operation(SM501State *s) index_s = ((src_y + y) * src_width + src_x + x) * _bpp; \ index_d = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \ } \ - *(_pixel_type *)&dst[index_d] = *(_pixel_type *)&src[index_s];\ + if (rop_mode == 1 && rop == 5) { \ + /* Invert dest */ \ + val = ~*(_pixel_type *)&dst[index_d]; \ + } else { \ + val = *(_pixel_type *)&src[index_s]; \ + } \ + *(_pixel_type *)&dst[index_d] = val; \ } \ } \ } -- cgit v1.1 From 06cb926aaa51970fc009245bb5e15700c19a56f8 Mon Sep 17 00:00:00 2001 From: Sebastian Bauer Date: Wed, 4 Jul 2018 11:40:58 +0200 Subject: sm501: Log unimplemented raster operation modes The sm501 currently implements only a very limited set of raster operation modes. After this change, unknown raster operation modes are logged so these can be easily spotted. Signed-off-by: BALATON Zoltan Signed-off-by: David Gibson --- hw/display/sm501.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'hw') diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 0b44d95..ebd1390 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -706,6 +706,8 @@ static void sm501_2d_operation(SM501State *s) int format_flags = (s->twoD_stretch >> 20) & 0x3; int addressing = (s->twoD_stretch >> 16) & 0xF; int rop_mode = (s->twoD_control >> 15) & 0x1; /* 1 for rop2, else rop3 */ + /* 1 if rop2 source is the pattern, otherwise the source is the bitmap */ + int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1; int rop = s->twoD_control & 0xFF; /* get frame buffer info */ @@ -719,6 +721,27 @@ static void sm501_2d_operation(SM501State *s) abort(); } + if (rop_mode == 0) { + if (rop != 0xcc) { + /* Anything other than plain copies are not supported */ + qemu_log_mask(LOG_UNIMP, "sm501: rop3 mode with rop %x is not " + "supported.\n", rop); + } + } else { + if (rop2_source_is_pattern && rop != 0x5) { + /* For pattern source, we support only inverse dest */ + qemu_log_mask(LOG_UNIMP, "sm501: rop2 source being the pattern and " + "rop %x is not supported.\n", rop); + } else { + if (rop != 0x5 && rop != 0xc) { + /* Anything other than plain copies or inverse dest is not + * supported */ + qemu_log_mask(LOG_UNIMP, "sm501: rop mode %x is not " + "supported.\n", rop); + } + } + } + if ((s->twoD_source_base & 0x08000000) || (s->twoD_destination_base & 0x08000000)) { printf("%s: only local memory is supported.\n", __func__); -- cgit v1.1 From 33159dd7ce2ccd14ab31062d80632297e04e46cf Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 4 Jul 2018 11:40:58 +0200 Subject: sm501: Fix support for non-zero frame buffer start address Display updates and drawing hardware cursor did not work when frame buffer address was non-zero. Fix this by taking the frame buffer address into account in these cases. This fixes screen dragging on AmigaOS. Based on patch by Sebastian Bauer. Signed-off-by: Sebastian Bauer Signed-off-by: BALATON Zoltan Signed-off-by: David Gibson --- hw/display/sm501.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/display/sm501.c b/hw/display/sm501.c index ebd1390..10ee008 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -586,6 +586,11 @@ static uint32_t get_local_mem_size_index(uint32_t size) return index; } +static ram_addr_t get_fb_addr(SM501State *s, int crt) +{ + return (crt ? s->dc_crt_fb_addr : s->dc_panel_fb_addr) & 0x3FFFFF0; +} + static inline int get_width(SM501State *s, int crt) { int width = crt ? s->dc_crt_h_total : s->dc_panel_h_total; @@ -688,7 +693,8 @@ static inline void hwc_invalidate(SM501State *s, int crt) start *= w * bpp; end *= w * bpp; - memory_region_set_dirty(&s->local_mem_region, start, end - start); + memory_region_set_dirty(&s->local_mem_region, + get_fb_addr(s, crt) + start, end - start); } static void sm501_2d_operation(SM501State *s) @@ -1213,6 +1219,9 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr addr, break; case SM501_DC_PANEL_FB_ADDR: s->dc_panel_fb_addr = value & 0x8FFFFFF0; + if (value & 0x8000000) { + qemu_log_mask(LOG_UNIMP, "Panel external memory not supported\n"); + } break; case SM501_DC_PANEL_FB_OFFSET: s->dc_panel_fb_offset = value & 0x3FF03FF0; @@ -1273,6 +1282,9 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr addr, break; case SM501_DC_CRT_FB_ADDR: s->dc_crt_fb_addr = value & 0x8FFFFFF0; + if (value & 0x8000000) { + qemu_log_mask(LOG_UNIMP, "CRT external memory not supported\n"); + } break; case SM501_DC_CRT_FB_OFFSET: s->dc_crt_fb_offset = value & 0x3FF03FF0; @@ -1615,7 +1627,7 @@ static void sm501_update_display(void *opaque) draw_hwc_line_func *draw_hwc_line = NULL; int full_update = 0; int y_start = -1; - ram_addr_t offset = 0; + ram_addr_t offset; uint32_t *palette; uint8_t hwc_palette[3 * 3]; uint8_t *hwc_src = NULL; @@ -1672,9 +1684,10 @@ static void sm501_update_display(void *opaque) } /* draw each line according to conditions */ + offset = get_fb_addr(s, crt); snap = memory_region_snapshot_and_clear_dirty(&s->local_mem_region, offset, width * height * src_bpp, DIRTY_MEMORY_VGA); - for (y = 0, offset = 0; y < height; y++, offset += width * src_bpp) { + for (y = 0; y < height; y++, offset += width * src_bpp) { int update, update_hwc; /* check if hardware cursor is enabled and we're within its range */ -- cgit v1.1 From eb76243c9da613d0abc27eb38a0d47b82f7ca00b Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 4 Jul 2018 11:40:58 +0200 Subject: sm501: Set updated region dirty after 2D operation Set the changed memory region dirty after performed a 2D operation to ensure that the screen is updated properly. Signed-off-by: BALATON Zoltan Signed-off-by: David Gibson --- hw/display/sm501.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 10ee008..3661a89 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -715,12 +715,16 @@ static void sm501_2d_operation(SM501State *s) /* 1 if rop2 source is the pattern, otherwise the source is the bitmap */ int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1; int rop = s->twoD_control & 0xFF; + uint32_t src_base = s->twoD_source_base & 0x03FFFFFF; + uint32_t dst_base = s->twoD_destination_base & 0x03FFFFFF; /* get frame buffer info */ - uint8_t *src = s->local_mem + (s->twoD_source_base & 0x03FFFFFF); - uint8_t *dst = s->local_mem + (s->twoD_destination_base & 0x03FFFFFF); + uint8_t *src = s->local_mem + src_base; + uint8_t *dst = s->local_mem + dst_base; int src_width = s->twoD_pitch & 0x1FFF; int dst_width = (s->twoD_pitch >> 16) & 0x1FFF; + int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0; + int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt); if (addressing != 0x0) { printf("%s: only XY addressing is supported.\n", __func__); @@ -821,6 +825,15 @@ static void sm501_2d_operation(SM501State *s) abort(); break; } + + if (dst_base >= get_fb_addr(s, crt) && + dst_base <= get_fb_addr(s, crt) + fb_len) { + int dst_len = MIN(fb_len, ((dst_y + operation_height - 1) * dst_width + + dst_x + operation_width) * (1 << format_flags)); + if (dst_len) { + memory_region_set_dirty(&s->local_mem_region, dst_base, dst_len); + } + } } static uint64_t sm501_system_config_read(void *opaque, hwaddr addr, -- cgit v1.1 From 7aeb1e5100c026f2f232e570cd4d56942785f462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 4 Jul 2018 11:44:00 -0300 Subject: ppc440_uc: Fix a copy/paste error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missed in 3c409c1927e, hopefully reported by Coverity. Fixes: Coverity CID 1393788 (Copy-paste error) Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: BALATON Zoltan Signed-off-by: David Gibson --- hw/ppc/ppc440_uc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 0bbaa68..09ccda5 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -935,7 +935,7 @@ static void dcr_write_dma(void *opaque, int dcrn, uint32_t val) if (wptr) { cpu_physical_memory_unmap(wptr, wlen, 1, didx); } - if (wptr) { + if (rptr) { cpu_physical_memory_unmap(rptr, rlen, 0, sidx); } } -- cgit v1.1 From 4cb25fbb433581a0f80a8564bd2bcf574b1d84a7 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Fri, 6 Jul 2018 08:51:55 +0100 Subject: ppc: fix default VGA display for PReP machines Commit 29f9cef "ppc: Include vga cirrus card into the compiling process" changed the default display adapter for all PPC machines to cirrus. Unfortunately it missed setting the default display type to stdvga for both PReP machines causing the display to fail to initialise under OpenHackWare. Update the MachineClass for both prep and 40p machines so that the default std(vga) display adapter is the default if no options are specified which fixes the display for the PReP machines. Signed-off-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/ppc/prep.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'hw') diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 6689407..3401570 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -682,6 +682,7 @@ static void prep_machine_init(MachineClass *mc) mc->max_cpus = MAX_CPUS; mc->default_boot_order = "cad"; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("602"); + mc->default_display = "std"; } static int prep_set_cmos_checksum(DeviceState *dev, void *opaque) @@ -888,6 +889,7 @@ static void ibm_40p_machine_init(MachineClass *mc) mc->block_default_type = IF_SCSI; mc->default_boot_order = "c"; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("604"); + mc->default_display = "std"; } DEFINE_MACHINE("40p", ibm_40p_machine_init) -- cgit v1.1 From ad633de6f5a08ad8e9b74e2372863101239c2cc3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 9 Jul 2018 14:23:05 +1000 Subject: sam460ex: Check for errors from libfdt functions In a couple of places sam460ex_load_device_tree() calls "raw" libfdt functions which can fail, but doesn't check for error codes. At best, if these fail the guest will be silently started in a non-standard state, or it could fail entirely. Fix this by using the _FDT() helper macro which aborts on a libfdt failure. Signed-off-by: David Gibson --- hw/ppc/sam460ex.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 7eed2ec..1661e03 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -36,6 +36,7 @@ #include "hw/i2c/ppc4xx_i2c.h" #include "hw/i2c/smbus.h" #include "hw/usb/hcd-ehci.h" +#include "hw/ppc/fdt.h" #include @@ -318,13 +319,13 @@ static int sam460ex_load_device_tree(hwaddr addr, /* Remove cpm node if it exists (it is not emulated) */ offset = fdt_path_offset(fdt, "/cpm"); if (offset >= 0) { - fdt_nop_node(fdt, offset); + _FDT(fdt_nop_node(fdt, offset)); } /* set serial port clocks */ offset = fdt_node_offset_by_compatible(fdt, -1, "ns16550"); while (offset >= 0) { - fdt_setprop_cell(fdt, offset, "clock-frequency", UART_FREQ); + _FDT(fdt_setprop_cell(fdt, offset, "clock-frequency", UART_FREQ)); offset = fdt_node_offset_by_compatible(fdt, offset, "ns16550"); } -- cgit v1.1 From e753f33136f6230d30aa324220be112ccddbffba Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 9 Jul 2018 14:27:36 +1000 Subject: sam460ex: Don't check for errors from qemu_fdt_*() The qemu_fdt_*() helper functions already exit with a message instead of returning errors, so we don't need to check for errors in the caller. Signed-off-by: David Gibson --- hw/ppc/sam460ex.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) (limited to 'hw') diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 1661e03..8194f32 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -276,32 +276,18 @@ static int sam460ex_load_device_tree(hwaddr addr, /* Manipulate device tree in memory. */ - ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property, - sizeof(mem_reg_property)); - if (ret < 0) { - error_report("couldn't set /memory/reg"); - } + qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property, + sizeof(mem_reg_property)); /* default FDT doesn't have a /chosen node... */ qemu_fdt_add_subnode(fdt, "/chosen"); - ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", - initrd_base); - if (ret < 0) { - error_report("couldn't set /chosen/linux,initrd-start"); - } + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", initrd_base); - ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", - (initrd_base + initrd_size)); - if (ret < 0) { - error_report("couldn't set /chosen/linux,initrd-end"); - } + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", + (initrd_base + initrd_size)); - ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", - kernel_cmdline); - if (ret < 0) { - error_report("couldn't set /chosen/bootargs"); - } + qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline); /* Copy data from the host device tree into the guest. Since the guest can * directly access the timebase without host involvement, we must expose -- cgit v1.1 From 51b0d834c414f494410cc94e56886b6584ae3c54 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 9 Jul 2018 14:27:43 +1000 Subject: sam460ex: Make sam460ex_load_device_tree() handle all errors internally sam460ex_load_device_tree() handles nearly all possible errors by simply exiting (within helper functions and macros). It handles two early error cases by returning an error. There's no particular point to this, so make it handle those directly as well, removing the need for the caller to handle a failure. As a bonus it gives us more specific error messages. Signed-off-by: David Gibson --- hw/ppc/sam460ex.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'hw') diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 8194f32..e2b7028 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -255,7 +255,6 @@ static int sam460ex_load_device_tree(hwaddr addr, hwaddr initrd_size, const char *kernel_cmdline) { - int ret = -1; uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) }; char *filename; int fdt_size; @@ -266,12 +265,14 @@ static int sam460ex_load_device_tree(hwaddr addr, filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); if (!filename) { - goto out; + error_report("Couldn't find dtb file `%s'", BINARY_DEVICE_TREE_FILE); + exit(1); } fdt = load_device_tree(filename, &fdt_size); g_free(filename); - if (fdt == NULL) { - goto out; + if (!fdt) { + error_report("Couldn't load dtb file `%s'", filename); + exit(1); } /* Manipulate device tree in memory. */ @@ -325,11 +326,8 @@ static int sam460ex_load_device_tree(hwaddr addr, rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); g_free(fdt); - ret = fdt_size; - -out: - return ret; + return fdt_size; } /* Create reset TLB entries for BookE, mapping only the flash memory. */ @@ -599,10 +597,6 @@ static void sam460ex_init(MachineState *machine) dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size, RAMDISK_ADDR, initrd_size, machine->kernel_cmdline); - if (dt_size < 0) { - error_report("couldn't load device tree"); - exit(1); - } boot_info->dt_base = FDT_ADDR; boot_info->dt_size = dt_size; -- cgit v1.1