From: Leonid Shatz <leonid.sh...@oracle.com> Add missing functionality of interrupt mask and status registers. Writing to interrupt status register clears interrupt request.
Signed-off-by: Leonid Shatz <leonid.sh...@oracle.com> Reviewed-by: Darren Kenny <darren.ke...@oracle.com> Signed-off-by: Liran Alon <liran.a...@oracle.com> --- hw/display/vmware_vga.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index eae3f1455445..4e4f6f8eec42 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -78,6 +78,8 @@ struct vmsvga_state_s { int redraw_fifo_first, redraw_fifo_last; uint32_t num_fifo_regs; + uint32_t irq_mask; + uint32_t irq_status; }; #define TYPE_VMWARE_SVGA "vmware-svga" @@ -104,6 +106,7 @@ struct pci_vmsvga_state_s { #define SVGA_INDEX_PORT 0x0 #define SVGA_VALUE_PORT 0x1 #define SVGA_BIOS_PORT 0x2 +#define SVGA_IRQSTATUS_PORT 0x8 #define SVGA_VERSION_2 @@ -158,6 +161,7 @@ enum { SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */ SVGA_REG_NUM_DISPLAYS = 31, /* Number of guest displays */ SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */ + SVGA_REG_IRQMASK = 33, /* Interrupt mask */ SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ SVGA_PALETTE_END = SVGA_PALETTE_BASE + 767, @@ -183,6 +187,7 @@ enum { #define SVGA_CAP_EXTENDED_FIFO (1 << 15) #define SVGA_CAP_MULTIMON (1 << 16) #define SVGA_CAP_PITCHLOCK (1 << 17) +#define SVGA_CAP_IRQMASK (1 << 18) /* * FIFO offsets (seen as an array of 32-bit words) @@ -1034,6 +1039,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) } #endif caps |= SVGA_CAP_EXTENDED_FIFO; + caps |= SVGA_CAP_IRQMASK; ret = caps; break; @@ -1091,6 +1097,10 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) ret = 0; break; + case SVGA_REG_IRQMASK: + ret = s->irq_mask; + break; + default: if (s->index >= SVGA_SCRATCH_BASE && s->index < SVGA_SCRATCH_BASE + s->scratch_size) { @@ -1221,6 +1231,10 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) case SVGA_PALETTE_BASE ... SVGA_PALETTE_END: break; + case SVGA_REG_IRQMASK: + s->irq_mask = value; + break; + default: if (s->index >= SVGA_SCRATCH_BASE && s->index < SVGA_SCRATCH_BASE + s->scratch_size) { @@ -1231,6 +1245,28 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) } } +static uint32_t vmsvga_irqstatus_read(void *opaque, uint32_t address) +{ + struct vmsvga_state_s *s = opaque; + return s->irq_status; +} + +static void vmsvga_irqstatus_write(void *opaque, uint32_t address, uint32_t data) +{ + struct vmsvga_state_s *s = opaque; + struct pci_vmsvga_state_s *pci_vmsvga = + container_of(s, struct pci_vmsvga_state_s, chip); + PCIDevice *pci_dev = PCI_DEVICE(pci_vmsvga); + + /* + * Clear selected interrupt sources and lower + * interrupt request when none are left active + */ + s->irq_status &= ~data; + if (!s->irq_status) + pci_set_irq(pci_dev, 0); +} + static uint32_t vmsvga_bios_read(void *opaque, uint32_t address) { printf("%s: what are we supposed to return?\n", __func__); @@ -1298,6 +1334,8 @@ static void vmsvga_reset(DeviceState *dev) s->redraw_fifo_first = 0; s->redraw_fifo_last = 0; s->syncing = 0; + s->irq_mask = 0; + s->irq_status = 0; vga_dirty_log_start(&s->vga); } @@ -1327,12 +1365,18 @@ static int vmsvga_post_load(void *opaque, int version_id) struct vmsvga_state_s *s = opaque; s->invalidated = 1; + + if (version_id < 1) { + s->irq_mask = 0; + s->irq_status = 0; + } + return 0; } static const VMStateDescription vmstate_vmware_vga_internal = { .name = "vmware_vga_internal", - .version_id = 0, + .version_id = 1, .minimum_version_id = 0, .post_load = vmsvga_post_load, .fields = (VMStateField[]) { @@ -1352,6 +1396,8 @@ static const VMStateDescription vmstate_vmware_vga_internal = { VMSTATE_UINT32(svgaid, struct vmsvga_state_s), VMSTATE_INT32(syncing, struct vmsvga_state_s), VMSTATE_UNUSED(4), /* was fb_size */ + VMSTATE_UINT32_V(irq_mask, struct vmsvga_state_s, 1), + VMSTATE_UINT32_V(irq_status, struct vmsvga_state_s, 1), VMSTATE_END_OF_LIST() } }; @@ -1404,6 +1450,7 @@ static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, unsigned size) case SVGA_IO_MUL * SVGA_INDEX_PORT: return vmsvga_index_read(s, addr); case SVGA_IO_MUL * SVGA_VALUE_PORT: return vmsvga_value_read(s, addr); case SVGA_IO_MUL * SVGA_BIOS_PORT: return vmsvga_bios_read(s, addr); + case SVGA_IO_MUL * SVGA_IRQSTATUS_PORT: return vmsvga_irqstatus_read(s, addr); default: return -1u; } } @@ -1423,6 +1470,9 @@ static void vmsvga_io_write(void *opaque, hwaddr addr, case SVGA_IO_MUL * SVGA_BIOS_PORT: vmsvga_bios_write(s, addr, data); break; + case SVGA_IO_MUL * SVGA_IRQSTATUS_PORT: + vmsvga_irqstatus_write(s, addr, data); + break; } } -- 1.9.1