diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-05-07 21:39:28 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-05-07 21:39:28 +0100 |
commit | a6f6d24757a73f7176989134b97284a1a7df11e5 (patch) | |
tree | 0ff1de73d0b2d8623b0e237d1c5c3fb6ce779696 /hw/display | |
parent | d6de7fed802f2bf42efdc0d081c67dc2ecf01e3f (diff) | |
parent | 6306cae275c7091aa4e785809d956b475bfedab4 (diff) | |
download | qemu-a6f6d24757a73f7176989134b97284a1a7df11e5.zip qemu-a6f6d24757a73f7176989134b97284a1a7df11e5.tar.gz qemu-a6f6d24757a73f7176989134b97284a1a7df11e5.tar.bz2 |
Merge remote-tracking branch 'remotes/kraxel/tags/vga-20190507-pull-request' into staging
vga: bugfixes for qxl, cirrus, ati.
vga: add "-vga help" support.
vga: move i2c-ddc to display.
# gpg: Signature made Tue 07 May 2019 09:19:32 BST
# gpg: using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138
* remotes/kraxel/tags/vga-20190507-pull-request:
i2c-ddc: move it to hw/display
ati-vga: Fix check for blt outside vram
qxl: avoid unaligned pointer reads/writes
vl: add -vga help support
vl: constify VGAInterfaceInfo
hw/display/cirrus_vga: Remove unused include
hw/display/cirrus_vga: Update the documentation URL
qxl: check release info object
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/display')
-rw-r--r-- | hw/display/Kconfig | 5 | ||||
-rw-r--r-- | hw/display/Makefile.objs | 1 | ||||
-rw-r--r-- | hw/display/ati_2d.c | 12 | ||||
-rw-r--r-- | hw/display/cirrus_vga.c | 10 | ||||
-rw-r--r-- | hw/display/i2c-ddc.c | 127 | ||||
-rw-r--r-- | hw/display/qxl.c | 58 | ||||
-rw-r--r-- | hw/display/sii9022.c | 2 | ||||
-rw-r--r-- | hw/display/sm501.c | 2 |
8 files changed, 175 insertions, 42 deletions
diff --git a/hw/display/Kconfig b/hw/display/Kconfig index 72be57a..c236cd2 100644 --- a/hw/display/Kconfig +++ b/hw/display/Kconfig @@ -1,3 +1,8 @@ +config DDC + bool + depends on I2C + select EDID + config EDID bool diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs index dbd453a..650031f 100644 --- a/hw/display/Makefile.objs +++ b/hw/display/Makefile.objs @@ -1,3 +1,4 @@ +common-obj-$(CONFIG_DDC) += i2c-ddc.o common-obj-$(CONFIG_EDID) += edid-generate.o edid-region.o common-obj-$(CONFIG_FW_CFG_DMA) += ramfb.o diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c index bc98ba6..fe3ae14 100644 --- a/hw/display/ati_2d.c +++ b/hw/display/ati_2d.c @@ -79,10 +79,10 @@ void ati_2d_blt(ATIVGAState *s) s->regs.dst_width, s->regs.dst_height); end = s->vga.vram_ptr + s->vga.vram_size; if (src_bits >= end || dst_bits >= end || - src_bits + (s->regs.src_y + s->regs.dst_height) * src_stride + - s->regs.src_x >= end || - dst_bits + (s->regs.dst_y + s->regs.dst_height) * dst_stride + - s->regs.dst_x >= end) { + src_bits + s->regs.src_x + (s->regs.src_y + s->regs.dst_height) * + src_stride * sizeof(uint32_t) >= end || + dst_bits + s->regs.dst_x + (s->regs.dst_y + s->regs.dst_height) * + dst_stride * sizeof(uint32_t) >= end) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return; } @@ -140,8 +140,8 @@ void ati_2d_blt(ATIVGAState *s) filler); end = s->vga.vram_ptr + s->vga.vram_size; if (dst_bits >= end || - dst_bits + (s->regs.dst_y + s->regs.dst_height) * dst_stride + - s->regs.dst_x >= end) { + dst_bits + s->regs.dst_x + (s->regs.dst_y + s->regs.dst_height) * + dst_stride * sizeof(uint32_t) >= end) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return; } diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index a0e7146..76c052c 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -23,8 +23,13 @@ * THE SOFTWARE. */ /* - * Reference: Finn Thogersons' VGADOC4b - * available at http://home.worldonline.dk/~finth/ + * Reference: Finn Thogersons' VGADOC4b: + * + * http://web.archive.org/web/20021019054927/http://home.worldonline.dk/finth/ + * + * VGADOC4b.ZIP content available at: + * + * https://pdos.csail.mit.edu/6.828/2005/readings/hardware/vgadoc */ #include "qemu/osdep.h" #include "qemu/units.h" @@ -33,7 +38,6 @@ #include "hw/hw.h" #include "hw/pci/pci.h" #include "ui/pixel_ops.h" -#include "hw/loader.h" #include "cirrus_vga_internal.h" /* diff --git a/hw/display/i2c-ddc.c b/hw/display/i2c-ddc.c new file mode 100644 index 0000000..9fe5403 --- /dev/null +++ b/hw/display/i2c-ddc.c @@ -0,0 +1,127 @@ +/* A simple I2C slave for returning monitor EDID data via DDC. + * + * Copyright (c) 2011 Linaro Limited + * Written by Peter Maydell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/log.h" +#include "hw/i2c/i2c.h" +#include "hw/display/i2c-ddc.h" + +#ifndef DEBUG_I2CDDC +#define DEBUG_I2CDDC 0 +#endif + +#define DPRINTF(fmt, ...) do { \ + if (DEBUG_I2CDDC) { \ + qemu_log("i2c-ddc: " fmt , ## __VA_ARGS__); \ + } \ +} while (0) + +static void i2c_ddc_reset(DeviceState *ds) +{ + I2CDDCState *s = I2CDDC(ds); + + s->firstbyte = false; + s->reg = 0; +} + +static int i2c_ddc_event(I2CSlave *i2c, enum i2c_event event) +{ + I2CDDCState *s = I2CDDC(i2c); + + if (event == I2C_START_SEND) { + s->firstbyte = true; + } + + return 0; +} + +static uint8_t i2c_ddc_rx(I2CSlave *i2c) +{ + I2CDDCState *s = I2CDDC(i2c); + + int value; + value = s->edid_blob[s->reg % sizeof(s->edid_blob)]; + s->reg++; + return value; +} + +static int i2c_ddc_tx(I2CSlave *i2c, uint8_t data) +{ + I2CDDCState *s = I2CDDC(i2c); + if (s->firstbyte) { + s->reg = data; + s->firstbyte = false; + DPRINTF("[EDID] Written new pointer: %u\n", data); + return 0; + } + + /* Ignore all writes */ + s->reg++; + return 0; +} + +static void i2c_ddc_init(Object *obj) +{ + I2CDDCState *s = I2CDDC(obj); + + qemu_edid_generate(s->edid_blob, sizeof(s->edid_blob), &s->edid_info); +} + +static const VMStateDescription vmstate_i2c_ddc = { + .name = TYPE_I2CDDC, + .version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_BOOL(firstbyte, I2CDDCState), + VMSTATE_UINT8(reg, I2CDDCState), + VMSTATE_END_OF_LIST() + } +}; + +static Property i2c_ddc_properties[] = { + DEFINE_EDID_PROPERTIES(I2CDDCState, edid_info), + DEFINE_PROP_END_OF_LIST(), +}; + +static void i2c_ddc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc); + + dc->reset = i2c_ddc_reset; + dc->vmsd = &vmstate_i2c_ddc; + dc->props = i2c_ddc_properties; + isc->event = i2c_ddc_event; + isc->recv = i2c_ddc_rx; + isc->send = i2c_ddc_tx; +} + +static TypeInfo i2c_ddc_info = { + .name = TYPE_I2CDDC, + .parent = TYPE_I2C_SLAVE, + .instance_size = sizeof(I2CDDCState), + .instance_init = i2c_ddc_init, + .class_init = i2c_ddc_class_init +}; + +static void ddc_register_devices(void) +{ + type_register_static(&i2c_ddc_info); +} + +type_init(ddc_register_devices); diff --git a/hw/display/qxl.c b/hw/display/qxl.c index c8ce578..3880a74 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -33,24 +33,6 @@ #include "qxl.h" -/* - * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as - * such can be changed by the guest, so to avoid a guest trigerrable - * abort we just qxl_set_guest_bug and set the return to NULL. Still - * it may happen as a result of emulator bug as well. - */ -#undef SPICE_RING_PROD_ITEM -#define SPICE_RING_PROD_ITEM(qxl, r, ret) { \ - uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \ - if (prod >= ARRAY_SIZE((r)->items)) { \ - qxl_set_guest_bug(qxl, "SPICE_RING_PROD_ITEM indices mismatch " \ - "%u >= %zu", prod, ARRAY_SIZE((r)->items)); \ - ret = NULL; \ - } else { \ - ret = &(r)->items[prod].el; \ - } \ - } - #undef SPICE_RING_CONS_ITEM #define SPICE_RING_CONS_ITEM(qxl, r, ret) { \ uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \ @@ -414,7 +396,8 @@ static void init_qxl_rom(PCIQXLDevice *d) static void init_qxl_ram(PCIQXLDevice *d) { uint8_t *buf; - uint64_t *item; + uint32_t prod; + QXLReleaseRing *ring; buf = d->vga.vram_ptr; d->ram = (QXLRam *)(buf + le32_to_cpu(d->shadow_rom.ram_header_offset)); @@ -426,9 +409,12 @@ static void init_qxl_ram(PCIQXLDevice *d) SPICE_RING_INIT(&d->ram->cmd_ring); SPICE_RING_INIT(&d->ram->cursor_ring); SPICE_RING_INIT(&d->ram->release_ring); - SPICE_RING_PROD_ITEM(d, &d->ram->release_ring, item); - assert(item); - *item = 0; + + ring = &d->ram->release_ring; + prod = ring->prod & SPICE_RING_INDEX_MASK(ring); + assert(prod < ARRAY_SIZE(ring->items)); + ring->items[prod].el = 0; + qxl_ring_set_dirty(d); } @@ -732,7 +718,7 @@ static int interface_req_cmd_notification(QXLInstance *sin) static inline void qxl_push_free_res(PCIQXLDevice *d, int flush) { QXLReleaseRing *ring = &d->ram->release_ring; - uint64_t *item; + uint32_t prod; int notify; #define QXL_FREE_BUNCH_SIZE 32 @@ -759,11 +745,15 @@ static inline void qxl_push_free_res(PCIQXLDevice *d, int flush) if (notify) { qxl_send_events(d, QXL_INTERRUPT_DISPLAY); } - SPICE_RING_PROD_ITEM(d, ring, item); - if (!item) { + + ring = &d->ram->release_ring; + prod = ring->prod & SPICE_RING_INDEX_MASK(ring); + if (prod >= ARRAY_SIZE(ring->items)) { + qxl_set_guest_bug(d, "SPICE_RING_PROD_ITEM indices mismatch " + "%u >= %zu", prod, ARRAY_SIZE(ring->items)); return; } - *item = 0; + ring->items[prod].el = 0; d->num_free_res = 0; d->last_release = NULL; qxl_ring_set_dirty(d); @@ -775,8 +765,12 @@ static void interface_release_resource(QXLInstance *sin, { PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); QXLReleaseRing *ring; - uint64_t *item, id; + uint32_t prod; + uint64_t id; + if (!ext.info) { + return; + } if (ext.group_id == MEMSLOT_GROUP_HOST) { /* host group -> vga mode update request */ QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id); @@ -792,16 +786,18 @@ static void interface_release_resource(QXLInstance *sin, * pci bar 0, $command.release_info */ ring = &qxl->ram->release_ring; - SPICE_RING_PROD_ITEM(qxl, ring, item); - if (!item) { + prod = ring->prod & SPICE_RING_INDEX_MASK(ring); + if (prod >= ARRAY_SIZE(ring->items)) { + qxl_set_guest_bug(qxl, "SPICE_RING_PROD_ITEM indices mismatch " + "%u >= %zu", prod, ARRAY_SIZE(ring->items)); return; } - if (*item == 0) { + if (ring->items[prod].el == 0) { /* stick head into the ring */ id = ext.info->id; ext.info->next = 0; qxl_ram_set_dirty(qxl, &ext.info->next); - *item = id; + ring->items[prod].el = id; qxl_ring_set_dirty(qxl); } else { /* append item to the list */ diff --git a/hw/display/sii9022.c b/hw/display/sii9022.c index 9994385..9c36e4c 100644 --- a/hw/display/sii9022.c +++ b/hw/display/sii9022.c @@ -16,7 +16,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "hw/i2c/i2c.h" -#include "hw/i2c/i2c-ddc.h" +#include "hw/display/i2c-ddc.h" #include "trace.h" #define SII9022_SYS_CTRL_DATA 0x1a diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 2122291..1e2709b 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -35,7 +35,7 @@ #include "hw/sysbus.h" #include "hw/pci/pci.h" #include "hw/i2c/i2c.h" -#include "hw/i2c/i2c-ddc.h" +#include "hw/display/i2c-ddc.h" #include "qemu/range.h" #include "ui/pixel_ops.h" #include "qemu/bswap.h" |