From bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 Mon Sep 17 00:00:00 2001 From: RajithaY Date: Tue, 25 Apr 2017 03:31:15 -0700 Subject: Adding qemu as a submodule of KVMFORNFV This Patch includes the changes to add qemu as a submodule to kvmfornfv repo and make use of the updated latest qemu for the execution of all testcase Change-Id: I1280af507a857675c7f81d30c95255635667bdd7 Signed-off-by:RajithaY --- qemu/hw/display/Makefile.objs | 45 - qemu/hw/display/ads7846.c | 178 -- qemu/hw/display/bcm2835_fb.c | 425 ---- qemu/hw/display/blizzard.c | 987 --------- qemu/hw/display/blizzard_template.h | 146 -- qemu/hw/display/cg3.c | 399 ---- qemu/hw/display/cirrus_vga.c | 3091 ---------------------------- qemu/hw/display/cirrus_vga_rop.h | 207 -- qemu/hw/display/cirrus_vga_rop2.h | 281 --- qemu/hw/display/exynos4210_fimd.c | 1952 ------------------ qemu/hw/display/framebuffer.c | 125 -- qemu/hw/display/framebuffer.h | 65 - qemu/hw/display/g364fb.c | 559 ----- qemu/hw/display/jazz_led.c | 314 --- qemu/hw/display/milkymist-tmu2.c | 495 ----- qemu/hw/display/milkymist-vgafb.c | 354 ---- qemu/hw/display/milkymist-vgafb_template.h | 74 - qemu/hw/display/omap_dss.c | 1091 ---------- qemu/hw/display/omap_lcd_template.h | 175 -- qemu/hw/display/omap_lcdc.c | 420 ---- qemu/hw/display/pl110.c | 539 ----- qemu/hw/display/pl110_template.h | 399 ---- qemu/hw/display/pxa2xx_lcd.c | 1065 ---------- qemu/hw/display/pxa2xx_template.h | 447 ---- qemu/hw/display/qxl-logger.c | 276 --- qemu/hw/display/qxl-render.c | 298 --- qemu/hw/display/qxl.c | 2359 --------------------- qemu/hw/display/qxl.h | 174 -- qemu/hw/display/sm501.c | 1458 ------------- qemu/hw/display/sm501_template.h | 145 -- qemu/hw/display/ssd0303.c | 331 --- qemu/hw/display/ssd0323.c | 402 ---- qemu/hw/display/tc6393xb.c | 598 ------ qemu/hw/display/tc6393xb_template.h | 72 - qemu/hw/display/tcx.c | 1106 ---------- qemu/hw/display/vga-helpers.h | 439 ---- qemu/hw/display/vga-isa-mm.c | 143 -- qemu/hw/display/vga-isa.c | 106 - qemu/hw/display/vga-pci.c | 387 ---- qemu/hw/display/vga.c | 2289 -------------------- qemu/hw/display/vga.h | 159 -- qemu/hw/display/vga_int.h | 227 -- qemu/hw/display/virtio-gpu-3d.c | 606 ------ qemu/hw/display/virtio-gpu-pci.c | 77 - qemu/hw/display/virtio-gpu.c | 1087 ---------- qemu/hw/display/virtio-vga.c | 193 -- qemu/hw/display/vmware_vga.c | 1370 ------------ qemu/hw/display/xenfb.c | 1004 --------- 48 files changed, 29139 deletions(-) delete mode 100644 qemu/hw/display/Makefile.objs delete mode 100644 qemu/hw/display/ads7846.c delete mode 100644 qemu/hw/display/bcm2835_fb.c delete mode 100644 qemu/hw/display/blizzard.c delete mode 100644 qemu/hw/display/blizzard_template.h delete mode 100644 qemu/hw/display/cg3.c delete mode 100644 qemu/hw/display/cirrus_vga.c delete mode 100644 qemu/hw/display/cirrus_vga_rop.h delete mode 100644 qemu/hw/display/cirrus_vga_rop2.h delete mode 100644 qemu/hw/display/exynos4210_fimd.c delete mode 100644 qemu/hw/display/framebuffer.c delete mode 100644 qemu/hw/display/framebuffer.h delete mode 100644 qemu/hw/display/g364fb.c delete mode 100644 qemu/hw/display/jazz_led.c delete mode 100644 qemu/hw/display/milkymist-tmu2.c delete mode 100644 qemu/hw/display/milkymist-vgafb.c delete mode 100644 qemu/hw/display/milkymist-vgafb_template.h delete mode 100644 qemu/hw/display/omap_dss.c delete mode 100644 qemu/hw/display/omap_lcd_template.h delete mode 100644 qemu/hw/display/omap_lcdc.c delete mode 100644 qemu/hw/display/pl110.c delete mode 100644 qemu/hw/display/pl110_template.h delete mode 100644 qemu/hw/display/pxa2xx_lcd.c delete mode 100644 qemu/hw/display/pxa2xx_template.h delete mode 100644 qemu/hw/display/qxl-logger.c delete mode 100644 qemu/hw/display/qxl-render.c delete mode 100644 qemu/hw/display/qxl.c delete mode 100644 qemu/hw/display/qxl.h delete mode 100644 qemu/hw/display/sm501.c delete mode 100644 qemu/hw/display/sm501_template.h delete mode 100644 qemu/hw/display/ssd0303.c delete mode 100644 qemu/hw/display/ssd0323.c delete mode 100644 qemu/hw/display/tc6393xb.c delete mode 100644 qemu/hw/display/tc6393xb_template.h delete mode 100644 qemu/hw/display/tcx.c delete mode 100644 qemu/hw/display/vga-helpers.h delete mode 100644 qemu/hw/display/vga-isa-mm.c delete mode 100644 qemu/hw/display/vga-isa.c delete mode 100644 qemu/hw/display/vga-pci.c delete mode 100644 qemu/hw/display/vga.c delete mode 100644 qemu/hw/display/vga.h delete mode 100644 qemu/hw/display/vga_int.h delete mode 100644 qemu/hw/display/virtio-gpu-3d.c delete mode 100644 qemu/hw/display/virtio-gpu-pci.c delete mode 100644 qemu/hw/display/virtio-gpu.c delete mode 100644 qemu/hw/display/virtio-vga.c delete mode 100644 qemu/hw/display/vmware_vga.c delete mode 100644 qemu/hw/display/xenfb.c (limited to 'qemu/hw/display') diff --git a/qemu/hw/display/Makefile.objs b/qemu/hw/display/Makefile.objs deleted file mode 100644 index d99780eeb..000000000 --- a/qemu/hw/display/Makefile.objs +++ /dev/null @@ -1,45 +0,0 @@ -common-obj-$(CONFIG_ADS7846) += ads7846.o -common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o -common-obj-$(CONFIG_G364FB) += g364fb.o -common-obj-$(CONFIG_JAZZ_LED) += jazz_led.o -common-obj-$(CONFIG_PL110) += pl110.o -common-obj-$(CONFIG_SSD0303) += ssd0303.o -common-obj-$(CONFIG_SSD0323) += ssd0323.o -common-obj-$(CONFIG_XEN_BACKEND) += xenfb.o - -common-obj-$(CONFIG_VGA_PCI) += vga-pci.o -common-obj-$(CONFIG_VGA_ISA) += vga-isa.o -common-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o -common-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o - -common-obj-$(CONFIG_BLIZZARD) += blizzard.o -common-obj-$(CONFIG_EXYNOS4) += exynos4210_fimd.o -common-obj-$(CONFIG_FRAMEBUFFER) += framebuffer.o -common-obj-$(CONFIG_MILKYMIST) += milkymist-vgafb.o -common-obj-$(CONFIG_ZAURUS) += tc6393xb.o - -ifeq ($(CONFIG_MILKYMIST_TMU2),y) -common-obj-y += milkymist-tmu2.o -milkymist-tmu2.o-cflags := $(OPENGL_CFLAGS) -milkymist-tmu2.o-libs += $(OPENGL_LIBS) -endif - -obj-$(CONFIG_OMAP) += omap_dss.o -obj-$(CONFIG_OMAP) += omap_lcdc.o -obj-$(CONFIG_PXA2XX) += pxa2xx_lcd.o -obj-$(CONFIG_RASPI) += bcm2835_fb.o -obj-$(CONFIG_SM501) += sm501.o -obj-$(CONFIG_TCX) += tcx.o -obj-$(CONFIG_CG3) += cg3.o - -obj-$(CONFIG_VGA) += vga.o - -common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o - -obj-$(CONFIG_VIRTIO) += virtio-gpu.o virtio-gpu-3d.o -obj-$(CONFIG_VIRTIO_PCI) += virtio-gpu-pci.o -obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o -virtio-gpu.o-cflags := $(VIRGL_CFLAGS) -virtio-gpu.o-libs += $(VIRGL_LIBS) -virtio-gpu-3d.o-cflags := $(VIRGL_CFLAGS) -virtio-gpu-3d.o-libs += $(VIRGL_LIBS) diff --git a/qemu/hw/display/ads7846.c b/qemu/hw/display/ads7846.c deleted file mode 100644 index 05aa2d1e6..000000000 --- a/qemu/hw/display/ads7846.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * TI ADS7846 / TSC2046 chip emulation. - * - * Copyright (c) 2006 Openedhand Ltd. - * Written by Andrzej Zaborowski - * - * This code is licensed under the GNU GPL v2. - * - * 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/osdep.h" -#include "hw/ssi/ssi.h" -#include "ui/console.h" - -typedef struct { - SSISlave ssidev; - qemu_irq interrupt; - - int input[8]; - int pressure; - int noise; - - int cycle; - int output; -} ADS7846State; - -/* Control-byte bitfields */ -#define CB_PD0 (1 << 0) -#define CB_PD1 (1 << 1) -#define CB_SER (1 << 2) -#define CB_MODE (1 << 3) -#define CB_A0 (1 << 4) -#define CB_A1 (1 << 5) -#define CB_A2 (1 << 6) -#define CB_START (1 << 7) - -#define X_AXIS_DMAX 3470 -#define X_AXIS_MIN 290 -#define Y_AXIS_DMAX 3450 -#define Y_AXIS_MIN 200 - -#define ADS_VBAT 2000 -#define ADS_VAUX 2000 -#define ADS_TEMP0 2000 -#define ADS_TEMP1 3000 -#define ADS_XPOS(x, y) (X_AXIS_MIN + ((X_AXIS_DMAX * (x)) >> 15)) -#define ADS_YPOS(x, y) (Y_AXIS_MIN + ((Y_AXIS_DMAX * (y)) >> 15)) -#define ADS_Z1POS(x, y) 600 -#define ADS_Z2POS(x, y) (600 + 6000 / ADS_XPOS(x, y)) - -static void ads7846_int_update(ADS7846State *s) -{ - if (s->interrupt) - qemu_set_irq(s->interrupt, s->pressure == 0); -} - -static uint32_t ads7846_transfer(SSISlave *dev, uint32_t value) -{ - ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev); - - switch (s->cycle ++) { - case 0: - if (!(value & CB_START)) { - s->cycle = 0; - break; - } - - s->output = s->input[(value >> 4) & 7]; - - /* Imitate the ADC noise, some drivers expect this. */ - s->noise = (s->noise + 3) & 7; - switch ((value >> 4) & 7) { - case 1: s->output += s->noise ^ 2; break; - case 3: s->output += s->noise ^ 0; break; - case 4: s->output += s->noise ^ 7; break; - case 5: s->output += s->noise ^ 5; break; - } - - if (value & CB_MODE) - s->output >>= 4; /* 8 bits instead of 12 */ - - break; - case 1: - s->cycle = 0; - break; - } - return s->output; -} - -static void ads7846_ts_event(void *opaque, - int x, int y, int z, int buttons_state) -{ - ADS7846State *s = opaque; - - if (buttons_state) { - x = 0x7fff - x; - s->input[1] = ADS_XPOS(x, y); - s->input[3] = ADS_Z1POS(x, y); - s->input[4] = ADS_Z2POS(x, y); - s->input[5] = ADS_YPOS(x, y); - } - - if (s->pressure == !buttons_state) { - s->pressure = !!buttons_state; - - ads7846_int_update(s); - } -} - -static int ads7856_post_load(void *opaque, int version_id) -{ - ADS7846State *s = opaque; - - s->pressure = 0; - ads7846_int_update(s); - return 0; -} - -static const VMStateDescription vmstate_ads7846 = { - .name = "ads7846", - .version_id = 1, - .minimum_version_id = 1, - .post_load = ads7856_post_load, - .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(ssidev, ADS7846State), - VMSTATE_INT32_ARRAY(input, ADS7846State, 8), - VMSTATE_INT32(noise, ADS7846State), - VMSTATE_INT32(cycle, ADS7846State), - VMSTATE_INT32(output, ADS7846State), - VMSTATE_END_OF_LIST() - } -}; - -static int ads7846_init(SSISlave *d) -{ - DeviceState *dev = DEVICE(d); - ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, d); - - qdev_init_gpio_out(dev, &s->interrupt, 1); - - s->input[0] = ADS_TEMP0; /* TEMP0 */ - s->input[2] = ADS_VBAT; /* VBAT */ - s->input[6] = ADS_VAUX; /* VAUX */ - s->input[7] = ADS_TEMP1; /* TEMP1 */ - - /* We want absolute coordinates */ - qemu_add_mouse_event_handler(ads7846_ts_event, s, 1, - "QEMU ADS7846-driven Touchscreen"); - - ads7846_int_update(s); - - vmstate_register(NULL, -1, &vmstate_ads7846, s); - return 0; -} - -static void ads7846_class_init(ObjectClass *klass, void *data) -{ - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); - - k->init = ads7846_init; - k->transfer = ads7846_transfer; -} - -static const TypeInfo ads7846_info = { - .name = "ads7846", - .parent = TYPE_SSI_SLAVE, - .instance_size = sizeof(ADS7846State), - .class_init = ads7846_class_init, -}; - -static void ads7846_register_types(void) -{ - type_register_static(&ads7846_info); -} - -type_init(ads7846_register_types) diff --git a/qemu/hw/display/bcm2835_fb.c b/qemu/hw/display/bcm2835_fb.c deleted file mode 100644 index 506f1d3d9..000000000 --- a/qemu/hw/display/bcm2835_fb.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Raspberry Pi emulation (c) 2012 Gregory Estrade - * Refactoring for Pi2 Copyright (c) 2015, Microsoft. Written by Andrew Baumann. - * This code is licensed under the GNU GPLv2 and later. - * - * Heavily based on milkymist-vgafb.c, copyright terms below: - * QEMU model of the Milkymist VGA framebuffer. - * - * Copyright (c) 2010-2012 Michael Walle - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - * - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "hw/display/bcm2835_fb.h" -#include "hw/display/framebuffer.h" -#include "ui/pixel_ops.h" -#include "hw/misc/bcm2835_mbox_defs.h" - -#define DEFAULT_VCRAM_SIZE 0x4000000 -#define BCM2835_FB_OFFSET 0x00100000 - -static void fb_invalidate_display(void *opaque) -{ - BCM2835FBState *s = BCM2835_FB(opaque); - - s->invalidate = true; -} - -static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src, - int width, int deststep) -{ - BCM2835FBState *s = opaque; - uint16_t rgb565; - uint32_t rgb888; - uint8_t r, g, b; - DisplaySurface *surface = qemu_console_surface(s->con); - int bpp = surface_bits_per_pixel(surface); - - while (width--) { - switch (s->bpp) { - case 8: - /* lookup palette starting at video ram base - * TODO: cache translation, rather than doing this each time! - */ - rgb888 = ldl_le_phys(&s->dma_as, s->vcram_base + (*src << 2)); - r = (rgb888 >> 0) & 0xff; - g = (rgb888 >> 8) & 0xff; - b = (rgb888 >> 16) & 0xff; - src++; - break; - case 16: - rgb565 = lduw_le_p(src); - r = ((rgb565 >> 11) & 0x1f) << 3; - g = ((rgb565 >> 5) & 0x3f) << 2; - b = ((rgb565 >> 0) & 0x1f) << 3; - src += 2; - break; - case 24: - rgb888 = ldl_le_p(src); - r = (rgb888 >> 0) & 0xff; - g = (rgb888 >> 8) & 0xff; - b = (rgb888 >> 16) & 0xff; - src += 3; - break; - case 32: - rgb888 = ldl_le_p(src); - r = (rgb888 >> 0) & 0xff; - g = (rgb888 >> 8) & 0xff; - b = (rgb888 >> 16) & 0xff; - src += 4; - break; - default: - r = 0; - g = 0; - b = 0; - break; - } - - if (s->pixo == 0) { - /* swap to BGR pixel format */ - uint8_t tmp = r; - r = b; - b = tmp; - } - - switch (bpp) { - case 8: - *dst++ = rgb_to_pixel8(r, g, b); - break; - case 15: - *(uint16_t *)dst = rgb_to_pixel15(r, g, b); - dst += 2; - break; - case 16: - *(uint16_t *)dst = rgb_to_pixel16(r, g, b); - dst += 2; - break; - case 24: - rgb888 = rgb_to_pixel24(r, g, b); - *dst++ = rgb888 & 0xff; - *dst++ = (rgb888 >> 8) & 0xff; - *dst++ = (rgb888 >> 16) & 0xff; - break; - case 32: - *(uint32_t *)dst = rgb_to_pixel32(r, g, b); - dst += 4; - break; - default: - return; - } - } -} - -static void fb_update_display(void *opaque) -{ - BCM2835FBState *s = opaque; - DisplaySurface *surface = qemu_console_surface(s->con); - int first = 0; - int last = 0; - int src_width = 0; - int dest_width = 0; - - if (s->lock || !s->xres) { - return; - } - - src_width = s->xres * (s->bpp >> 3); - dest_width = s->xres; - - switch (surface_bits_per_pixel(surface)) { - case 0: - return; - case 8: - break; - case 15: - dest_width *= 2; - break; - case 16: - dest_width *= 2; - break; - case 24: - dest_width *= 3; - break; - case 32: - dest_width *= 4; - break; - default: - hw_error("bcm2835_fb: bad color depth\n"); - break; - } - - if (s->invalidate) { - framebuffer_update_memory_section(&s->fbsection, s->dma_mr, s->base, - s->yres, src_width); - } - - framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres, - src_width, dest_width, 0, s->invalidate, - draw_line_src16, s, &first, &last); - - if (first >= 0) { - dpy_gfx_update(s->con, 0, first, s->xres, last - first + 1); - } - - s->invalidate = false; -} - -static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value) -{ - value &= ~0xf; - - s->lock = true; - - s->xres = ldl_le_phys(&s->dma_as, value); - s->yres = ldl_le_phys(&s->dma_as, value + 4); - s->xres_virtual = ldl_le_phys(&s->dma_as, value + 8); - s->yres_virtual = ldl_le_phys(&s->dma_as, value + 12); - s->bpp = ldl_le_phys(&s->dma_as, value + 20); - s->xoffset = ldl_le_phys(&s->dma_as, value + 24); - s->yoffset = ldl_le_phys(&s->dma_as, value + 28); - - s->base = s->vcram_base | (value & 0xc0000000); - s->base += BCM2835_FB_OFFSET; - - /* TODO - Manage properly virtual resolution */ - - s->pitch = s->xres * (s->bpp >> 3); - s->size = s->yres * s->pitch; - - stl_le_phys(&s->dma_as, value + 16, s->pitch); - stl_le_phys(&s->dma_as, value + 32, s->base); - stl_le_phys(&s->dma_as, value + 36, s->size); - - s->invalidate = true; - qemu_console_resize(s->con, s->xres, s->yres); - s->lock = false; -} - -void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres, - uint32_t *xoffset, uint32_t *yoffset, uint32_t *bpp, - uint32_t *pixo, uint32_t *alpha) -{ - s->lock = true; - - /* TODO: input validation! */ - if (xres) { - s->xres = *xres; - } - if (yres) { - s->yres = *yres; - } - if (xoffset) { - s->xoffset = *xoffset; - } - if (yoffset) { - s->yoffset = *yoffset; - } - if (bpp) { - s->bpp = *bpp; - } - if (pixo) { - s->pixo = *pixo; - } - if (alpha) { - s->alpha = *alpha; - } - - /* TODO - Manage properly virtual resolution */ - - s->pitch = s->xres * (s->bpp >> 3); - s->size = s->yres * s->pitch; - - s->invalidate = true; - qemu_console_resize(s->con, s->xres, s->yres); - s->lock = false; -} - -static uint64_t bcm2835_fb_read(void *opaque, hwaddr offset, unsigned size) -{ - BCM2835FBState *s = opaque; - uint32_t res = 0; - - switch (offset) { - case MBOX_AS_DATA: - res = MBOX_CHAN_FB; - s->pending = false; - qemu_set_irq(s->mbox_irq, 0); - break; - - case MBOX_AS_PENDING: - res = s->pending; - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", - __func__, offset); - return 0; - } - - return res; -} - -static void bcm2835_fb_write(void *opaque, hwaddr offset, uint64_t value, - unsigned size) -{ - BCM2835FBState *s = opaque; - - switch (offset) { - case MBOX_AS_DATA: - /* bcm2835_mbox should check our pending status before pushing */ - assert(!s->pending); - s->pending = true; - bcm2835_fb_mbox_push(s, value); - qemu_set_irq(s->mbox_irq, 1); - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", - __func__, offset); - return; - } -} - -static const MemoryRegionOps bcm2835_fb_ops = { - .read = bcm2835_fb_read, - .write = bcm2835_fb_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid.min_access_size = 4, - .valid.max_access_size = 4, -}; - -static const VMStateDescription vmstate_bcm2835_fb = { - .name = TYPE_BCM2835_FB, - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_BOOL(lock, BCM2835FBState), - VMSTATE_BOOL(invalidate, BCM2835FBState), - VMSTATE_BOOL(pending, BCM2835FBState), - VMSTATE_UINT32(xres, BCM2835FBState), - VMSTATE_UINT32(yres, BCM2835FBState), - VMSTATE_UINT32(xres_virtual, BCM2835FBState), - VMSTATE_UINT32(yres_virtual, BCM2835FBState), - VMSTATE_UINT32(xoffset, BCM2835FBState), - VMSTATE_UINT32(yoffset, BCM2835FBState), - VMSTATE_UINT32(bpp, BCM2835FBState), - VMSTATE_UINT32(base, BCM2835FBState), - VMSTATE_UINT32(pitch, BCM2835FBState), - VMSTATE_UINT32(size, BCM2835FBState), - VMSTATE_UINT32(pixo, BCM2835FBState), - VMSTATE_UINT32(alpha, BCM2835FBState), - VMSTATE_END_OF_LIST() - } -}; - -static const GraphicHwOps vgafb_ops = { - .invalidate = fb_invalidate_display, - .gfx_update = fb_update_display, -}; - -static void bcm2835_fb_init(Object *obj) -{ - BCM2835FBState *s = BCM2835_FB(obj); - - memory_region_init_io(&s->iomem, obj, &bcm2835_fb_ops, s, TYPE_BCM2835_FB, - 0x10); - sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); - sysbus_init_irq(SYS_BUS_DEVICE(s), &s->mbox_irq); -} - -static void bcm2835_fb_reset(DeviceState *dev) -{ - BCM2835FBState *s = BCM2835_FB(dev); - - s->pending = false; - - s->xres_virtual = s->xres; - s->yres_virtual = s->yres; - s->xoffset = 0; - s->yoffset = 0; - s->base = s->vcram_base + BCM2835_FB_OFFSET; - s->pitch = s->xres * (s->bpp >> 3); - s->size = s->yres * s->pitch; - - s->invalidate = true; - s->lock = false; -} - -static void bcm2835_fb_realize(DeviceState *dev, Error **errp) -{ - BCM2835FBState *s = BCM2835_FB(dev); - Error *err = NULL; - Object *obj; - - if (s->vcram_base == 0) { - error_setg(errp, "%s: required vcram-base property not set", __func__); - return; - } - - obj = object_property_get_link(OBJECT(dev), "dma-mr", &err); - if (obj == NULL) { - error_setg(errp, "%s: required dma-mr link not found: %s", - __func__, error_get_pretty(err)); - return; - } - - s->dma_mr = MEMORY_REGION(obj); - address_space_init(&s->dma_as, s->dma_mr, NULL); - - bcm2835_fb_reset(dev); - - s->con = graphic_console_init(dev, 0, &vgafb_ops, s); - qemu_console_resize(s->con, s->xres, s->yres); -} - -static Property bcm2835_fb_props[] = { - DEFINE_PROP_UINT32("vcram-base", BCM2835FBState, vcram_base, 0),/*required*/ - DEFINE_PROP_UINT32("vcram-size", BCM2835FBState, vcram_size, - DEFAULT_VCRAM_SIZE), - DEFINE_PROP_UINT32("xres", BCM2835FBState, xres, 640), - DEFINE_PROP_UINT32("yres", BCM2835FBState, yres, 480), - DEFINE_PROP_UINT32("bpp", BCM2835FBState, bpp, 16), - DEFINE_PROP_UINT32("pixo", BCM2835FBState, pixo, 1), /* 1=RGB, 0=BGR */ - DEFINE_PROP_UINT32("alpha", BCM2835FBState, alpha, 2), /* alpha ignored */ - DEFINE_PROP_END_OF_LIST() -}; - -static void bcm2835_fb_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->props = bcm2835_fb_props; - dc->realize = bcm2835_fb_realize; - dc->reset = bcm2835_fb_reset; - dc->vmsd = &vmstate_bcm2835_fb; -} - -static TypeInfo bcm2835_fb_info = { - .name = TYPE_BCM2835_FB, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(BCM2835FBState), - .class_init = bcm2835_fb_class_init, - .instance_init = bcm2835_fb_init, -}; - -static void bcm2835_fb_register_types(void) -{ - type_register_static(&bcm2835_fb_info); -} - -type_init(bcm2835_fb_register_types) diff --git a/qemu/hw/display/blizzard.c b/qemu/hw/display/blizzard.c deleted file mode 100644 index c231960d9..000000000 --- a/qemu/hw/display/blizzard.c +++ /dev/null @@ -1,987 +0,0 @@ -/* - * Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller. - * - * Copyright (C) 2008 Nokia Corporation - * Written by Andrzej Zaborowski - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * 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 . - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "ui/console.h" -#include "hw/devices.h" -#include "ui/pixel_ops.h" - -typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int); - -typedef struct { - uint8_t reg; - uint32_t addr; - int swallow; - - int pll; - int pll_range; - int pll_ctrl; - uint8_t pll_mode; - uint8_t clksel; - int memenable; - int memrefresh; - uint8_t timing[3]; - int priority; - - uint8_t lcd_config; - int x; - int y; - int skipx; - int skipy; - uint8_t hndp; - uint8_t vndp; - uint8_t hsync; - uint8_t vsync; - uint8_t pclk; - uint8_t u; - uint8_t v; - uint8_t yrc[2]; - int ix[2]; - int iy[2]; - int ox[2]; - int oy[2]; - - int enable; - int blank; - int bpp; - int invalidate; - int mx[2]; - int my[2]; - uint8_t mode; - uint8_t effect; - uint8_t iformat; - uint8_t source; - QemuConsole *con; - blizzard_fn_t *line_fn_tab[2]; - void *fb; - - uint8_t hssi_config[3]; - uint8_t tv_config; - uint8_t tv_timing[4]; - uint8_t vbi; - uint8_t tv_x; - uint8_t tv_y; - uint8_t tv_test; - uint8_t tv_filter_config; - uint8_t tv_filter_idx; - uint8_t tv_filter_coeff[0x20]; - uint8_t border_r; - uint8_t border_g; - uint8_t border_b; - uint8_t gamma_config; - uint8_t gamma_idx; - uint8_t gamma_lut[0x100]; - uint8_t matrix_ena; - uint8_t matrix_coeff[0x12]; - uint8_t matrix_r; - uint8_t matrix_g; - uint8_t matrix_b; - uint8_t pm; - uint8_t status; - uint8_t rgbgpio_dir; - uint8_t rgbgpio; - uint8_t gpio_dir; - uint8_t gpio; - uint8_t gpio_edge[2]; - uint8_t gpio_irq; - uint8_t gpio_pdown; - - struct { - int x; - int y; - int dx; - int dy; - int len; - int buflen; - void *buf; - void *data; - uint16_t *ptr; - int angle; - int pitch; - blizzard_fn_t line_fn; - } data; -} BlizzardState; - -/* Bytes(!) per pixel */ -static const int blizzard_iformat_bpp[0x10] = { - 0, - 2, /* RGB 5:6:5*/ - 3, /* RGB 6:6:6 mode 1 */ - 3, /* RGB 8:8:8 mode 1 */ - 0, 0, - 4, /* RGB 6:6:6 mode 2 */ - 4, /* RGB 8:8:8 mode 2 */ - 0, /* YUV 4:2:2 */ - 0, /* YUV 4:2:0 */ - 0, 0, 0, 0, 0, 0, -}; - -static void blizzard_window(BlizzardState *s) -{ - DisplaySurface *surface = qemu_console_surface(s->con); - uint8_t *src, *dst; - int bypp[2]; - int bypl[3]; - int y; - blizzard_fn_t fn = s->data.line_fn; - - if (!fn) - return; - if (s->mx[0] > s->data.x) - s->mx[0] = s->data.x; - if (s->my[0] > s->data.y) - s->my[0] = s->data.y; - if (s->mx[1] < s->data.x + s->data.dx) - s->mx[1] = s->data.x + s->data.dx; - if (s->my[1] < s->data.y + s->data.dy) - s->my[1] = s->data.y + s->data.dy; - - bypp[0] = s->bpp; - 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; - - src = s->data.data; - dst = s->fb + bypl[1] * s->data.y + bypp[1] * s->data.x; - for (y = s->data.dy; y > 0; y --, src += bypl[0], dst += bypl[1]) - fn(dst, src, bypl[2]); -} - -static int blizzard_transfer_setup(BlizzardState *s) -{ - if (s->source > 3 || !s->bpp || - s->ix[1] < s->ix[0] || s->iy[1] < s->iy[0]) - return 0; - - s->data.angle = s->effect & 3; - s->data.line_fn = s->line_fn_tab[!!s->data.angle][s->iformat]; - s->data.x = s->ix[0]; - s->data.y = s->iy[0]; - s->data.dx = s->ix[1] - s->ix[0] + 1; - s->data.dy = s->iy[1] - s->iy[0] + 1; - s->data.len = s->bpp * s->data.dx * s->data.dy; - s->data.pitch = s->data.dx; - if (s->data.len > s->data.buflen) { - s->data.buf = g_realloc(s->data.buf, s->data.len); - s->data.buflen = s->data.len; - } - s->data.ptr = s->data.buf; - s->data.data = s->data.buf; - s->data.len /= 2; - return 1; -} - -static void blizzard_reset(BlizzardState *s) -{ - s->reg = 0; - s->swallow = 0; - - s->pll = 9; - s->pll_range = 1; - s->pll_ctrl = 0x14; - s->pll_mode = 0x32; - s->clksel = 0x00; - s->memenable = 0; - s->memrefresh = 0x25c; - s->timing[0] = 0x3f; - s->timing[1] = 0x13; - s->timing[2] = 0x21; - s->priority = 0; - - s->lcd_config = 0x74; - s->x = 8; - s->y = 1; - s->skipx = 0; - s->skipy = 0; - s->hndp = 3; - s->vndp = 2; - s->hsync = 1; - s->vsync = 1; - s->pclk = 0x80; - - s->ix[0] = 0; - s->ix[1] = 0; - s->iy[0] = 0; - s->iy[1] = 0; - s->ox[0] = 0; - s->ox[1] = 0; - s->oy[0] = 0; - s->oy[1] = 0; - - s->yrc[0] = 0x00; - s->yrc[1] = 0x30; - s->u = 0; - s->v = 0; - - s->iformat = 3; - s->source = 0; - s->bpp = blizzard_iformat_bpp[s->iformat]; - - s->hssi_config[0] = 0x00; - s->hssi_config[1] = 0x00; - s->hssi_config[2] = 0x01; - s->tv_config = 0x00; - s->tv_timing[0] = 0x00; - s->tv_timing[1] = 0x00; - s->tv_timing[2] = 0x00; - s->tv_timing[3] = 0x00; - s->vbi = 0x10; - s->tv_x = 0x14; - s->tv_y = 0x03; - s->tv_test = 0x00; - s->tv_filter_config = 0x80; - s->tv_filter_idx = 0x00; - s->border_r = 0x10; - s->border_g = 0x80; - s->border_b = 0x80; - s->gamma_config = 0x00; - s->gamma_idx = 0x00; - s->matrix_ena = 0x00; - memset(&s->matrix_coeff, 0, sizeof(s->matrix_coeff)); - s->matrix_r = 0x00; - s->matrix_g = 0x00; - s->matrix_b = 0x00; - s->pm = 0x02; - s->status = 0x00; - s->rgbgpio_dir = 0x00; - s->gpio_dir = 0x00; - s->gpio_edge[0] = 0x00; - s->gpio_edge[1] = 0x00; - s->gpio_irq = 0x00; - s->gpio_pdown = 0xff; -} - -static inline void blizzard_invalidate_display(void *opaque) { - BlizzardState *s = (BlizzardState *) opaque; - - s->invalidate = 1; -} - -static uint16_t blizzard_reg_read(void *opaque, uint8_t reg) -{ - BlizzardState *s = (BlizzardState *) opaque; - - switch (reg) { - case 0x00: /* Revision Code */ - return 0xa5; - - case 0x02: /* Configuration Readback */ - return 0x83; /* Macrovision OK, CNF[2:0] = 3 */ - - case 0x04: /* PLL M-Divider */ - return (s->pll - 1) | (1 << 7); - case 0x06: /* PLL Lock Range Control */ - return s->pll_range; - case 0x08: /* PLL Lock Synthesis Control 0 */ - return s->pll_ctrl & 0xff; - case 0x0a: /* PLL Lock Synthesis Control 1 */ - return s->pll_ctrl >> 8; - case 0x0c: /* PLL Mode Control 0 */ - return s->pll_mode; - - case 0x0e: /* Clock-Source Select */ - return s->clksel; - - case 0x10: /* Memory Controller Activate */ - case 0x14: /* Memory Controller Bank 0 Status Flag */ - return s->memenable; - - case 0x18: /* Auto-Refresh Interval Setting 0 */ - return s->memrefresh & 0xff; - case 0x1a: /* Auto-Refresh Interval Setting 1 */ - return s->memrefresh >> 8; - - case 0x1c: /* Power-On Sequence Timing Control */ - return s->timing[0]; - case 0x1e: /* Timing Control 0 */ - return s->timing[1]; - case 0x20: /* Timing Control 1 */ - return s->timing[2]; - - case 0x24: /* Arbitration Priority Control */ - return s->priority; - - case 0x28: /* LCD Panel Configuration */ - return s->lcd_config; - - case 0x2a: /* LCD Horizontal Display Width */ - return s->x >> 3; - case 0x2c: /* LCD Horizontal Non-display Period */ - return s->hndp; - case 0x2e: /* LCD Vertical Display Height 0 */ - return s->y & 0xff; - case 0x30: /* LCD Vertical Display Height 1 */ - return s->y >> 8; - case 0x32: /* LCD Vertical Non-display Period */ - return s->vndp; - case 0x34: /* LCD HS Pulse-width */ - return s->hsync; - case 0x36: /* LCd HS Pulse Start Position */ - return s->skipx >> 3; - case 0x38: /* LCD VS Pulse-width */ - return s->vsync; - case 0x3a: /* LCD VS Pulse Start Position */ - return s->skipy; - - case 0x3c: /* PCLK Polarity */ - return s->pclk; - - case 0x3e: /* High-speed Serial Interface Tx Configuration Port 0 */ - return s->hssi_config[0]; - case 0x40: /* High-speed Serial Interface Tx Configuration Port 1 */ - return s->hssi_config[1]; - case 0x42: /* High-speed Serial Interface Tx Mode */ - return s->hssi_config[2]; - case 0x44: /* TV Display Configuration */ - return s->tv_config; - case 0x46 ... 0x4c: /* TV Vertical Blanking Interval Data bits */ - return s->tv_timing[(reg - 0x46) >> 1]; - case 0x4e: /* VBI: Closed Caption / XDS Control / Status */ - return s->vbi; - case 0x50: /* TV Horizontal Start Position */ - return s->tv_x; - case 0x52: /* TV Vertical Start Position */ - return s->tv_y; - case 0x54: /* TV Test Pattern Setting */ - return s->tv_test; - case 0x56: /* TV Filter Setting */ - return s->tv_filter_config; - case 0x58: /* TV Filter Coefficient Index */ - return s->tv_filter_idx; - case 0x5a: /* TV Filter Coefficient Data */ - if (s->tv_filter_idx < 0x20) - return s->tv_filter_coeff[s->tv_filter_idx ++]; - return 0; - - case 0x60: /* Input YUV/RGB Translate Mode 0 */ - return s->yrc[0]; - case 0x62: /* Input YUV/RGB Translate Mode 1 */ - return s->yrc[1]; - case 0x64: /* U Data Fix */ - return s->u; - case 0x66: /* V Data Fix */ - return s->v; - - case 0x68: /* Display Mode */ - return s->mode; - - case 0x6a: /* Special Effects */ - return s->effect; - - case 0x6c: /* Input Window X Start Position 0 */ - return s->ix[0] & 0xff; - case 0x6e: /* Input Window X Start Position 1 */ - return s->ix[0] >> 3; - case 0x70: /* Input Window Y Start Position 0 */ - return s->ix[0] & 0xff; - case 0x72: /* Input Window Y Start Position 1 */ - return s->ix[0] >> 3; - case 0x74: /* Input Window X End Position 0 */ - return s->ix[1] & 0xff; - case 0x76: /* Input Window X End Position 1 */ - return s->ix[1] >> 3; - case 0x78: /* Input Window Y End Position 0 */ - return s->ix[1] & 0xff; - case 0x7a: /* Input Window Y End Position 1 */ - return s->ix[1] >> 3; - case 0x7c: /* Output Window X Start Position 0 */ - return s->ox[0] & 0xff; - case 0x7e: /* Output Window X Start Position 1 */ - return s->ox[0] >> 3; - case 0x80: /* Output Window Y Start Position 0 */ - return s->oy[0] & 0xff; - case 0x82: /* Output Window Y Start Position 1 */ - return s->oy[0] >> 3; - case 0x84: /* Output Window X End Position 0 */ - return s->ox[1] & 0xff; - case 0x86: /* Output Window X End Position 1 */ - return s->ox[1] >> 3; - case 0x88: /* Output Window Y End Position 0 */ - return s->oy[1] & 0xff; - case 0x8a: /* Output Window Y End Position 1 */ - return s->oy[1] >> 3; - - case 0x8c: /* Input Data Format */ - return s->iformat; - case 0x8e: /* Data Source Select */ - return s->source; - case 0x90: /* Display Memory Data Port */ - return 0; - - case 0xa8: /* Border Color 0 */ - return s->border_r; - case 0xaa: /* Border Color 1 */ - return s->border_g; - case 0xac: /* Border Color 2 */ - return s->border_b; - - case 0xb4: /* Gamma Correction Enable */ - return s->gamma_config; - case 0xb6: /* Gamma Correction Table Index */ - return s->gamma_idx; - case 0xb8: /* Gamma Correction Table Data */ - return s->gamma_lut[s->gamma_idx ++]; - - case 0xba: /* 3x3 Matrix Enable */ - return s->matrix_ena; - case 0xbc ... 0xde: /* Coefficient Registers */ - return s->matrix_coeff[(reg - 0xbc) >> 1]; - case 0xe0: /* 3x3 Matrix Red Offset */ - return s->matrix_r; - case 0xe2: /* 3x3 Matrix Green Offset */ - return s->matrix_g; - case 0xe4: /* 3x3 Matrix Blue Offset */ - return s->matrix_b; - - case 0xe6: /* Power-save */ - return s->pm; - case 0xe8: /* Non-display Period Control / Status */ - return s->status | (1 << 5); - case 0xea: /* RGB Interface Control */ - return s->rgbgpio_dir; - case 0xec: /* RGB Interface Status */ - return s->rgbgpio; - case 0xee: /* General-purpose IO Pins Configuration */ - return s->gpio_dir; - case 0xf0: /* General-purpose IO Pins Status / Control */ - return s->gpio; - case 0xf2: /* GPIO Positive Edge Interrupt Trigger */ - return s->gpio_edge[0]; - case 0xf4: /* GPIO Negative Edge Interrupt Trigger */ - return s->gpio_edge[1]; - case 0xf6: /* GPIO Interrupt Status */ - return s->gpio_irq; - case 0xf8: /* GPIO Pull-down Control */ - return s->gpio_pdown; - - default: - fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg); - return 0; - } -} - -static void blizzard_reg_write(void *opaque, uint8_t reg, uint16_t value) -{ - BlizzardState *s = (BlizzardState *) opaque; - - switch (reg) { - case 0x04: /* PLL M-Divider */ - s->pll = (value & 0x3f) + 1; - break; - case 0x06: /* PLL Lock Range Control */ - s->pll_range = value & 3; - break; - case 0x08: /* PLL Lock Synthesis Control 0 */ - s->pll_ctrl &= 0xf00; - s->pll_ctrl |= (value << 0) & 0x0ff; - break; - case 0x0a: /* PLL Lock Synthesis Control 1 */ - s->pll_ctrl &= 0x0ff; - s->pll_ctrl |= (value << 8) & 0xf00; - break; - case 0x0c: /* PLL Mode Control 0 */ - s->pll_mode = value & 0x77; - if ((value & 3) == 0 || (value & 3) == 3) - fprintf(stderr, "%s: wrong PLL Control bits (%i)\n", - __FUNCTION__, value & 3); - break; - - case 0x0e: /* Clock-Source Select */ - s->clksel = value & 0xff; - break; - - case 0x10: /* Memory Controller Activate */ - s->memenable = value & 1; - break; - case 0x14: /* Memory Controller Bank 0 Status Flag */ - break; - - case 0x18: /* Auto-Refresh Interval Setting 0 */ - s->memrefresh &= 0xf00; - s->memrefresh |= (value << 0) & 0x0ff; - break; - case 0x1a: /* Auto-Refresh Interval Setting 1 */ - s->memrefresh &= 0x0ff; - s->memrefresh |= (value << 8) & 0xf00; - break; - - case 0x1c: /* Power-On Sequence Timing Control */ - s->timing[0] = value & 0x7f; - break; - case 0x1e: /* Timing Control 0 */ - s->timing[1] = value & 0x17; - break; - case 0x20: /* Timing Control 1 */ - s->timing[2] = value & 0x35; - break; - - case 0x24: /* Arbitration Priority Control */ - s->priority = value & 1; - break; - - case 0x28: /* LCD Panel Configuration */ - s->lcd_config = value & 0xff; - if (value & (1 << 7)) - fprintf(stderr, "%s: data swap not supported!\n", __FUNCTION__); - break; - - case 0x2a: /* LCD Horizontal Display Width */ - s->x = value << 3; - break; - case 0x2c: /* LCD Horizontal Non-display Period */ - s->hndp = value & 0xff; - break; - case 0x2e: /* LCD Vertical Display Height 0 */ - s->y &= 0x300; - s->y |= (value << 0) & 0x0ff; - break; - case 0x30: /* LCD Vertical Display Height 1 */ - s->y &= 0x0ff; - s->y |= (value << 8) & 0x300; - break; - case 0x32: /* LCD Vertical Non-display Period */ - s->vndp = value & 0xff; - break; - case 0x34: /* LCD HS Pulse-width */ - s->hsync = value & 0xff; - break; - case 0x36: /* LCD HS Pulse Start Position */ - s->skipx = value & 0xff; - break; - case 0x38: /* LCD VS Pulse-width */ - s->vsync = value & 0xbf; - break; - case 0x3a: /* LCD VS Pulse Start Position */ - s->skipy = value & 0xff; - break; - - case 0x3c: /* PCLK Polarity */ - s->pclk = value & 0x82; - /* Affects calculation of s->hndp, s->hsync and s->skipx. */ - break; - - case 0x3e: /* High-speed Serial Interface Tx Configuration Port 0 */ - s->hssi_config[0] = value; - break; - case 0x40: /* High-speed Serial Interface Tx Configuration Port 1 */ - s->hssi_config[1] = value; - if (((value >> 4) & 3) == 3) - fprintf(stderr, "%s: Illegal active-data-links value\n", - __FUNCTION__); - break; - case 0x42: /* High-speed Serial Interface Tx Mode */ - s->hssi_config[2] = value & 0xbd; - break; - - case 0x44: /* TV Display Configuration */ - s->tv_config = value & 0xfe; - break; - case 0x46 ... 0x4c: /* TV Vertical Blanking Interval Data bits 0 */ - s->tv_timing[(reg - 0x46) >> 1] = value; - break; - case 0x4e: /* VBI: Closed Caption / XDS Control / Status */ - s->vbi = value; - break; - case 0x50: /* TV Horizontal Start Position */ - s->tv_x = value; - break; - case 0x52: /* TV Vertical Start Position */ - s->tv_y = value & 0x7f; - break; - case 0x54: /* TV Test Pattern Setting */ - s->tv_test = value; - break; - case 0x56: /* TV Filter Setting */ - s->tv_filter_config = value & 0xbf; - break; - case 0x58: /* TV Filter Coefficient Index */ - s->tv_filter_idx = value & 0x1f; - break; - case 0x5a: /* TV Filter Coefficient Data */ - if (s->tv_filter_idx < 0x20) - s->tv_filter_coeff[s->tv_filter_idx ++] = value; - break; - - case 0x60: /* Input YUV/RGB Translate Mode 0 */ - s->yrc[0] = value & 0xb0; - break; - case 0x62: /* Input YUV/RGB Translate Mode 1 */ - s->yrc[1] = value & 0x30; - break; - case 0x64: /* U Data Fix */ - s->u = value & 0xff; - break; - case 0x66: /* V Data Fix */ - s->v = value & 0xff; - break; - - case 0x68: /* Display Mode */ - if ((s->mode ^ value) & 3) - s->invalidate = 1; - s->mode = value & 0xb7; - s->enable = value & 1; - s->blank = (value >> 1) & 1; - if (value & (1 << 4)) - fprintf(stderr, "%s: Macrovision enable attempt!\n", __FUNCTION__); - break; - - case 0x6a: /* Special Effects */ - s->effect = value & 0xfb; - break; - - case 0x6c: /* Input Window X Start Position 0 */ - s->ix[0] &= 0x300; - s->ix[0] |= (value << 0) & 0x0ff; - break; - case 0x6e: /* Input Window X Start Position 1 */ - s->ix[0] &= 0x0ff; - s->ix[0] |= (value << 8) & 0x300; - break; - case 0x70: /* Input Window Y Start Position 0 */ - s->iy[0] &= 0x300; - s->iy[0] |= (value << 0) & 0x0ff; - break; - case 0x72: /* Input Window Y Start Position 1 */ - s->iy[0] &= 0x0ff; - s->iy[0] |= (value << 8) & 0x300; - break; - case 0x74: /* Input Window X End Position 0 */ - s->ix[1] &= 0x300; - s->ix[1] |= (value << 0) & 0x0ff; - break; - case 0x76: /* Input Window X End Position 1 */ - s->ix[1] &= 0x0ff; - s->ix[1] |= (value << 8) & 0x300; - break; - case 0x78: /* Input Window Y End Position 0 */ - s->iy[1] &= 0x300; - s->iy[1] |= (value << 0) & 0x0ff; - break; - case 0x7a: /* Input Window Y End Position 1 */ - s->iy[1] &= 0x0ff; - s->iy[1] |= (value << 8) & 0x300; - break; - case 0x7c: /* Output Window X Start Position 0 */ - s->ox[0] &= 0x300; - s->ox[0] |= (value << 0) & 0x0ff; - break; - case 0x7e: /* Output Window X Start Position 1 */ - s->ox[0] &= 0x0ff; - s->ox[0] |= (value << 8) & 0x300; - break; - case 0x80: /* Output Window Y Start Position 0 */ - s->oy[0] &= 0x300; - s->oy[0] |= (value << 0) & 0x0ff; - break; - case 0x82: /* Output Window Y Start Position 1 */ - s->oy[0] &= 0x0ff; - s->oy[0] |= (value << 8) & 0x300; - break; - case 0x84: /* Output Window X End Position 0 */ - s->ox[1] &= 0x300; - s->ox[1] |= (value << 0) & 0x0ff; - break; - case 0x86: /* Output Window X End Position 1 */ - s->ox[1] &= 0x0ff; - s->ox[1] |= (value << 8) & 0x300; - break; - case 0x88: /* Output Window Y End Position 0 */ - s->oy[1] &= 0x300; - s->oy[1] |= (value << 0) & 0x0ff; - break; - case 0x8a: /* Output Window Y End Position 1 */ - s->oy[1] &= 0x0ff; - s->oy[1] |= (value << 8) & 0x300; - break; - - case 0x8c: /* Input Data Format */ - s->iformat = value & 0xf; - s->bpp = blizzard_iformat_bpp[s->iformat]; - if (!s->bpp) - fprintf(stderr, "%s: Illegal or unsupported input format %x\n", - __FUNCTION__, s->iformat); - break; - case 0x8e: /* Data Source Select */ - s->source = value & 7; - /* Currently all windows will be "destructive overlays". */ - if ((!(s->effect & (1 << 3)) && (s->ix[0] != s->ox[0] || - s->iy[0] != s->oy[0] || - s->ix[1] != s->ox[1] || - s->iy[1] != s->oy[1])) || - !((s->ix[1] - s->ix[0]) & (s->iy[1] - s->iy[0]) & - (s->ox[1] - s->ox[0]) & (s->oy[1] - s->oy[0]) & 1)) - fprintf(stderr, "%s: Illegal input/output window positions\n", - __FUNCTION__); - - blizzard_transfer_setup(s); - break; - - case 0x90: /* Display Memory Data Port */ - if (!s->data.len && !blizzard_transfer_setup(s)) - break; - - *s->data.ptr ++ = value; - if (-- s->data.len == 0) - blizzard_window(s); - break; - - case 0xa8: /* Border Color 0 */ - s->border_r = value; - break; - case 0xaa: /* Border Color 1 */ - s->border_g = value; - break; - case 0xac: /* Border Color 2 */ - s->border_b = value; - break; - - case 0xb4: /* Gamma Correction Enable */ - s->gamma_config = value & 0x87; - break; - case 0xb6: /* Gamma Correction Table Index */ - s->gamma_idx = value; - break; - case 0xb8: /* Gamma Correction Table Data */ - s->gamma_lut[s->gamma_idx ++] = value; - break; - - case 0xba: /* 3x3 Matrix Enable */ - s->matrix_ena = value & 1; - break; - case 0xbc ... 0xde: /* Coefficient Registers */ - s->matrix_coeff[(reg - 0xbc) >> 1] = value & ((reg & 2) ? 0x80 : 0xff); - break; - case 0xe0: /* 3x3 Matrix Red Offset */ - s->matrix_r = value; - break; - case 0xe2: /* 3x3 Matrix Green Offset */ - s->matrix_g = value; - break; - case 0xe4: /* 3x3 Matrix Blue Offset */ - s->matrix_b = value; - break; - - case 0xe6: /* Power-save */ - s->pm = value & 0x83; - if (value & s->mode & 1) - fprintf(stderr, "%s: The display must be disabled before entering " - "Standby Mode\n", __FUNCTION__); - break; - case 0xe8: /* Non-display Period Control / Status */ - s->status = value & 0x1b; - break; - case 0xea: /* RGB Interface Control */ - s->rgbgpio_dir = value & 0x8f; - break; - case 0xec: /* RGB Interface Status */ - s->rgbgpio = value & 0xcf; - break; - case 0xee: /* General-purpose IO Pins Configuration */ - s->gpio_dir = value; - break; - case 0xf0: /* General-purpose IO Pins Status / Control */ - s->gpio = value; - break; - case 0xf2: /* GPIO Positive Edge Interrupt Trigger */ - s->gpio_edge[0] = value; - break; - case 0xf4: /* GPIO Negative Edge Interrupt Trigger */ - s->gpio_edge[1] = value; - break; - case 0xf6: /* GPIO Interrupt Status */ - s->gpio_irq &= value; - break; - case 0xf8: /* GPIO Pull-down Control */ - s->gpio_pdown = value; - break; - - default: - fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg); - break; - } -} - -uint16_t s1d13745_read(void *opaque, int dc) -{ - BlizzardState *s = (BlizzardState *) opaque; - uint16_t value = blizzard_reg_read(s, s->reg); - - if (s->swallow -- > 0) - return 0; - if (dc) - s->reg ++; - - return value; -} - -void s1d13745_write(void *opaque, int dc, uint16_t value) -{ - BlizzardState *s = (BlizzardState *) opaque; - - if (s->swallow -- > 0) - return; - if (dc) { - blizzard_reg_write(s, s->reg, value); - - if (s->reg != 0x90 && s->reg != 0x5a && s->reg != 0xb8) - s->reg += 2; - } else - s->reg = value & 0xff; -} - -void s1d13745_write_block(void *opaque, int dc, - void *buf, size_t len, int pitch) -{ - BlizzardState *s = (BlizzardState *) opaque; - - while (len > 0) { - if (s->reg == 0x90 && dc && - (s->data.len || blizzard_transfer_setup(s)) && - len >= (s->data.len << 1)) { - len -= s->data.len << 1; - s->data.len = 0; - s->data.data = buf; - if (pitch) - s->data.pitch = pitch; - blizzard_window(s); - s->data.data = s->data.buf; - continue; - } - - s1d13745_write(opaque, dc, *(uint16_t *) buf); - len -= 2; - buf += 2; - } -} - -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 != surface_width(surface) || s->y != surface_height(surface)) { - s->invalidate = 1; - 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 = surface_bytes_per_pixel(surface); - memset(surface_data(surface), 0, bypp * s->x * s->y); - return; - } - - s->mx[0] = 0; - s->mx[1] = s->x; - s->my[0] = 0; - s->my[1] = s->y; - } - - if (s->mx[1] <= s->mx[0]) - return; - - 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 = 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->con, s->mx[0], s->my[0], - s->mx[1] - s->mx[0], y - s->my[0]); - - s->mx[0] = s->x; - s->mx[1] = 0; - s->my[0] = s->y; - s->my[1] = 0; -} - -#define DEPTH 8 -#include "blizzard_template.h" -#define DEPTH 15 -#include "blizzard_template.h" -#define DEPTH 16 -#include "blizzard_template.h" -#define DEPTH 24 -#include "blizzard_template.h" -#define DEPTH 32 -#include "blizzard_template.h" - -static const GraphicHwOps blizzard_ops = { - .invalidate = blizzard_invalidate_display, - .gfx_update = blizzard_update_display, -}; - -void *s1d13745_init(qemu_irq gpio_int) -{ - BlizzardState *s = (BlizzardState *) g_malloc0(sizeof(*s)); - DisplaySurface *surface; - - s->fb = g_malloc(0x180000); - - s->con = graphic_console_init(NULL, 0, &blizzard_ops, s); - surface = qemu_console_surface(s->con); - - 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); - break; - case 8: - s->line_fn_tab[0] = blizzard_draw_fn_8; - s->line_fn_tab[1] = blizzard_draw_fn_r_8; - break; - case 15: - s->line_fn_tab[0] = blizzard_draw_fn_15; - s->line_fn_tab[1] = blizzard_draw_fn_r_15; - break; - case 16: - s->line_fn_tab[0] = blizzard_draw_fn_16; - s->line_fn_tab[1] = blizzard_draw_fn_r_16; - break; - case 24: - s->line_fn_tab[0] = blizzard_draw_fn_24; - s->line_fn_tab[1] = blizzard_draw_fn_r_24; - break; - case 32: - s->line_fn_tab[0] = blizzard_draw_fn_32; - s->line_fn_tab[1] = blizzard_draw_fn_r_32; - break; - default: - fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__); - exit(1); - } - - blizzard_reset(s); - - return s; -} diff --git a/qemu/hw/display/blizzard_template.h b/qemu/hw/display/blizzard_template.h deleted file mode 100644 index b7ef27c80..000000000 --- a/qemu/hw/display/blizzard_template.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * QEMU Epson S1D13744/S1D13745 templates - * - * Copyright (C) 2008 Nokia Corporation - * Written by Andrzej Zaborowski - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * 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 . - */ - -#define SKIP_PIXEL(to) (to += deststep) -#if DEPTH == 8 -# define PIXEL_TYPE uint8_t -# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0) -# define COPY_PIXEL1(to, from) (*to++ = from) -#elif DEPTH == 15 || DEPTH == 16 -# define PIXEL_TYPE uint16_t -# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0) -# define COPY_PIXEL1(to, from) (*to++ = from) -#elif DEPTH == 24 -# define PIXEL_TYPE uint8_t -# define COPY_PIXEL(to, from) \ - do { \ - to[0] = from; \ - to[1] = (from) >> 8; \ - to[2] = (from) >> 16; \ - SKIP_PIXEL(to); \ - } while (0) - -# define COPY_PIXEL1(to, from) \ - do { \ - *to++ = from; \ - *to++ = (from) >> 8; \ - *to++ = (from) >> 16; \ - } while (0) -#elif DEPTH == 32 -# define PIXEL_TYPE uint32_t -# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0) -# define COPY_PIXEL1(to, from) (*to++ = from) -#else -# error unknown bit depth -#endif - -#ifdef HOST_WORDS_BIGENDIAN -# define SWAP_WORDS 1 -#endif - -static void glue(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest, - const uint16_t *src, unsigned int width) -{ -#if !defined(SWAP_WORDS) && DEPTH == 16 - memcpy(dest, src, width); -#else - uint16_t data; - unsigned int r, g, b; - const uint16_t *end = (const void *) src + width; - while (src < end) { - data = *src ++; - b = (data & 0x1f) << 3; - data >>= 5; - g = (data & 0x3f) << 2; - data >>= 6; - r = (data & 0x1f) << 3; - data >>= 5; - COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b)); - } -#endif -} - -static void glue(blizzard_draw_line24mode1_, DEPTH)(PIXEL_TYPE *dest, - const uint8_t *src, unsigned int width) -{ - /* TODO: check if SDL 24-bit planes are not in the same format and - * if so, use memcpy */ - unsigned int r[2], g[2], b[2]; - const uint8_t *end = src + width; - while (src < end) { - g[0] = *src ++; - r[0] = *src ++; - r[1] = *src ++; - b[0] = *src ++; - COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[0], g[0], b[0])); - b[1] = *src ++; - g[1] = *src ++; - COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[1], g[1], b[1])); - } -} - -static void glue(blizzard_draw_line24mode2_, DEPTH)(PIXEL_TYPE *dest, - const uint8_t *src, unsigned int width) -{ - unsigned int r, g, b; - const uint8_t *end = src + width; - while (src < end) { - r = *src ++; - src ++; - b = *src ++; - g = *src ++; - COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b)); - } -} - -/* No rotation */ -static blizzard_fn_t glue(blizzard_draw_fn_, DEPTH)[0x10] = { - NULL, - /* RGB 5:6:5*/ - (blizzard_fn_t) glue(blizzard_draw_line16_, DEPTH), - /* RGB 6:6:6 mode 1 */ - (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH), - /* RGB 8:8:8 mode 1 */ - (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH), - NULL, NULL, - /* RGB 6:6:6 mode 2 */ - (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH), - /* RGB 8:8:8 mode 2 */ - (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH), - /* YUV 4:2:2 */ - NULL, - /* YUV 4:2:0 */ - NULL, - NULL, NULL, NULL, NULL, NULL, NULL, -}; - -/* 90deg, 180deg and 270deg rotation */ -static blizzard_fn_t glue(blizzard_draw_fn_r_, DEPTH)[0x10] = { - /* TODO */ - [0 ... 0xf] = NULL, -}; - -#undef DEPTH -#undef SKIP_PIXEL -#undef COPY_PIXEL -#undef COPY_PIXEL1 -#undef PIXEL_TYPE - -#undef SWAP_WORDS diff --git a/qemu/hw/display/cg3.c b/qemu/hw/display/cg3.c deleted file mode 100644 index fc0d97fa4..000000000 --- a/qemu/hw/display/cg3.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * QEMU CG3 Frame buffer - * - * Copyright (c) 2012 Bob Breuer - * Copyright (c) 2013 Mark Cave-Ayland - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "qemu-common.h" -#include "qemu/error-report.h" -#include "ui/console.h" -#include "hw/sysbus.h" -#include "hw/loader.h" - -/* Change to 1 to enable debugging */ -#define DEBUG_CG3 0 - -#define CG3_ROM_FILE "QEMU,cgthree.bin" -#define FCODE_MAX_ROM_SIZE 0x10000 - -#define CG3_REG_SIZE 0x20 - -#define CG3_REG_BT458_ADDR 0x0 -#define CG3_REG_BT458_COLMAP 0x4 -#define CG3_REG_FBC_CTRL 0x10 -#define CG3_REG_FBC_STATUS 0x11 -#define CG3_REG_FBC_CURSTART 0x12 -#define CG3_REG_FBC_CUREND 0x13 -#define CG3_REG_FBC_VCTRL 0x14 - -/* Control register flags */ -#define CG3_CR_ENABLE_INTS 0x80 - -/* Status register flags */ -#define CG3_SR_PENDING_INT 0x80 -#define CG3_SR_1152_900_76_B 0x60 -#define CG3_SR_ID_COLOR 0x01 - -#define CG3_VRAM_SIZE 0x100000 -#define CG3_VRAM_OFFSET 0x800000 - -#define DPRINTF(fmt, ...) do { \ - if (DEBUG_CG3) { \ - printf("CG3: " fmt , ## __VA_ARGS__); \ - } \ -} while (0); - -#define TYPE_CG3 "cgthree" -#define CG3(obj) OBJECT_CHECK(CG3State, (obj), TYPE_CG3) - -typedef struct CG3State { - SysBusDevice parent_obj; - - QemuConsole *con; - qemu_irq irq; - hwaddr prom_addr; - MemoryRegion vram_mem; - MemoryRegion rom; - MemoryRegion reg; - uint32_t vram_size; - int full_update; - uint8_t regs[16]; - uint8_t r[256], g[256], b[256]; - uint16_t width, height, depth; - uint8_t dac_index, dac_state; -} CG3State; - -static void cg3_update_display(void *opaque) -{ - CG3State *s = opaque; - DisplaySurface *surface = qemu_console_surface(s->con); - const uint8_t *pix; - uint32_t *data; - uint32_t dval; - int x, y, y_start; - unsigned int width, height; - ram_addr_t page, page_min, page_max; - - if (surface_bits_per_pixel(surface) != 32) { - return; - } - width = s->width; - height = s->height; - - y_start = -1; - page_min = -1; - page_max = 0; - page = 0; - pix = memory_region_get_ram_ptr(&s->vram_mem); - data = (uint32_t *)surface_data(surface); - - memory_region_sync_dirty_bitmap(&s->vram_mem); - for (y = 0; y < height; y++) { - int update = s->full_update; - - page = (y * width) & TARGET_PAGE_MASK; - update |= memory_region_get_dirty(&s->vram_mem, page, page + width, - DIRTY_MEMORY_VGA); - if (update) { - if (y_start < 0) { - y_start = y; - } - if (page < page_min) { - page_min = page; - } - if (page > page_max) { - page_max = page; - } - - for (x = 0; x < width; x++) { - dval = *pix++; - dval = (s->r[dval] << 16) | (s->g[dval] << 8) | s->b[dval]; - *data++ = dval; - } - } else { - if (y_start >= 0) { - dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start); - y_start = -1; - } - pix += width; - data += width; - } - } - s->full_update = 0; - if (y_start >= 0) { - dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start); - } - if (page_max >= page_min) { - memory_region_reset_dirty(&s->vram_mem, - page_min, page_max - page_min + TARGET_PAGE_SIZE, - DIRTY_MEMORY_VGA); - } - /* vsync interrupt? */ - if (s->regs[0] & CG3_CR_ENABLE_INTS) { - s->regs[1] |= CG3_SR_PENDING_INT; - qemu_irq_raise(s->irq); - } -} - -static void cg3_invalidate_display(void *opaque) -{ - CG3State *s = opaque; - - memory_region_set_dirty(&s->vram_mem, 0, CG3_VRAM_SIZE); -} - -static uint64_t cg3_reg_read(void *opaque, hwaddr addr, unsigned size) -{ - CG3State *s = opaque; - int val; - - switch (addr) { - case CG3_REG_BT458_ADDR: - case CG3_REG_BT458_COLMAP: - val = 0; - break; - case CG3_REG_FBC_CTRL: - val = s->regs[0]; - break; - case CG3_REG_FBC_STATUS: - /* monitor ID 6, board type = 1 (color) */ - val = s->regs[1] | CG3_SR_1152_900_76_B | CG3_SR_ID_COLOR; - break; - case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE - 1: - val = s->regs[addr - 0x10]; - break; - default: - qemu_log_mask(LOG_UNIMP, - "cg3: Unimplemented register read " - "reg 0x%" HWADDR_PRIx " size 0x%x\n", - addr, size); - val = 0; - break; - } - DPRINTF("read %02x from reg %" HWADDR_PRIx "\n", val, addr); - return val; -} - -static void cg3_reg_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - CG3State *s = opaque; - uint8_t regval; - int i; - - DPRINTF("write %" PRIx64 " to reg %" HWADDR_PRIx " size %d\n", - val, addr, size); - - switch (addr) { - case CG3_REG_BT458_ADDR: - s->dac_index = val; - s->dac_state = 0; - break; - case CG3_REG_BT458_COLMAP: - /* This register can be written to as either a long word or a byte */ - if (size == 1) { - val <<= 24; - } - - for (i = 0; i < size; i++) { - regval = val >> 24; - - switch (s->dac_state) { - case 0: - s->r[s->dac_index] = regval; - s->dac_state++; - break; - case 1: - s->g[s->dac_index] = regval; - s->dac_state++; - break; - case 2: - s->b[s->dac_index] = regval; - /* Index autoincrement */ - s->dac_index = (s->dac_index + 1) & 0xff; - default: - s->dac_state = 0; - break; - } - val <<= 8; - } - s->full_update = 1; - break; - case CG3_REG_FBC_CTRL: - s->regs[0] = val; - break; - case CG3_REG_FBC_STATUS: - if (s->regs[1] & CG3_SR_PENDING_INT) { - /* clear interrupt */ - s->regs[1] &= ~CG3_SR_PENDING_INT; - qemu_irq_lower(s->irq); - } - break; - case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE - 1: - s->regs[addr - 0x10] = val; - break; - default: - qemu_log_mask(LOG_UNIMP, - "cg3: Unimplemented register write " - "reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n", - addr, size, val); - break; - } -} - -static const MemoryRegionOps cg3_reg_ops = { - .read = cg3_reg_read, - .write = cg3_reg_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 4, - }, -}; - -static const GraphicHwOps cg3_ops = { - .invalidate = cg3_invalidate_display, - .gfx_update = cg3_update_display, -}; - -static void cg3_initfn(Object *obj) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - CG3State *s = CG3(obj); - - memory_region_init_ram(&s->rom, obj, "cg3.prom", FCODE_MAX_ROM_SIZE, - &error_fatal); - memory_region_set_readonly(&s->rom, true); - sysbus_init_mmio(sbd, &s->rom); - - memory_region_init_io(&s->reg, obj, &cg3_reg_ops, s, "cg3.reg", - CG3_REG_SIZE); - sysbus_init_mmio(sbd, &s->reg); -} - -static void cg3_realizefn(DeviceState *dev, Error **errp) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - CG3State *s = CG3(dev); - int ret; - char *fcode_filename; - - /* FCode ROM */ - vmstate_register_ram_global(&s->rom); - fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, CG3_ROM_FILE); - if (fcode_filename) { - ret = load_image_targphys(fcode_filename, s->prom_addr, - FCODE_MAX_ROM_SIZE); - g_free(fcode_filename); - if (ret < 0 || ret > FCODE_MAX_ROM_SIZE) { - error_report("cg3: could not load prom '%s'", CG3_ROM_FILE); - } - } - - memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size, - &error_fatal); - memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA); - vmstate_register_ram_global(&s->vram_mem); - sysbus_init_mmio(sbd, &s->vram_mem); - - sysbus_init_irq(sbd, &s->irq); - - s->con = graphic_console_init(DEVICE(dev), 0, &cg3_ops, s); - qemu_console_resize(s->con, s->width, s->height); -} - -static int vmstate_cg3_post_load(void *opaque, int version_id) -{ - CG3State *s = opaque; - - cg3_invalidate_display(s); - - return 0; -} - -static const VMStateDescription vmstate_cg3 = { - .name = "cg3", - .version_id = 1, - .minimum_version_id = 1, - .post_load = vmstate_cg3_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT16(height, CG3State), - VMSTATE_UINT16(width, CG3State), - VMSTATE_UINT16(depth, CG3State), - VMSTATE_BUFFER(r, CG3State), - VMSTATE_BUFFER(g, CG3State), - VMSTATE_BUFFER(b, CG3State), - VMSTATE_UINT8(dac_index, CG3State), - VMSTATE_UINT8(dac_state, CG3State), - VMSTATE_END_OF_LIST() - } -}; - -static void cg3_reset(DeviceState *d) -{ - CG3State *s = CG3(d); - - /* Initialize palette */ - memset(s->r, 0, 256); - memset(s->g, 0, 256); - memset(s->b, 0, 256); - - s->dac_state = 0; - s->full_update = 1; - qemu_irq_lower(s->irq); -} - -static Property cg3_properties[] = { - DEFINE_PROP_UINT32("vram-size", CG3State, vram_size, -1), - DEFINE_PROP_UINT16("width", CG3State, width, -1), - DEFINE_PROP_UINT16("height", CG3State, height, -1), - DEFINE_PROP_UINT16("depth", CG3State, depth, -1), - DEFINE_PROP_UINT64("prom-addr", CG3State, prom_addr, -1), - DEFINE_PROP_END_OF_LIST(), -}; - -static void cg3_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = cg3_realizefn; - dc->reset = cg3_reset; - dc->vmsd = &vmstate_cg3; - dc->props = cg3_properties; -} - -static const TypeInfo cg3_info = { - .name = TYPE_CG3, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(CG3State), - .instance_init = cg3_initfn, - .class_init = cg3_class_init, -}; - -static void cg3_register_types(void) -{ - type_register_static(&cg3_info); -} - -type_init(cg3_register_types) diff --git a/qemu/hw/display/cirrus_vga.c b/qemu/hw/display/cirrus_vga.c deleted file mode 100644 index 3d712d592..000000000 --- a/qemu/hw/display/cirrus_vga.c +++ /dev/null @@ -1,3091 +0,0 @@ -/* - * QEMU Cirrus CLGD 54xx VGA Emulator. - * - * Copyright (c) 2004 Fabrice Bellard - * Copyright (c) 2004 Makoto Suzuki (suzu) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/* - * Reference: Finn Thogersons' VGADOC4b - * available at http://home.worldonline.dk/~finth/ - */ -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "hw/hw.h" -#include "hw/pci/pci.h" -#include "ui/console.h" -#include "ui/pixel_ops.h" -#include "vga_int.h" -#include "hw/loader.h" - -/* - * TODO: - * - destination write mask support not complete (bits 5..7) - * - optimize linear mappings - * - optimize bitblt functions - */ - -//#define DEBUG_CIRRUS -//#define DEBUG_BITBLT - -/*************************************** - * - * definitions - * - ***************************************/ - -// ID -#define CIRRUS_ID_CLGD5422 (0x23<<2) -#define CIRRUS_ID_CLGD5426 (0x24<<2) -#define CIRRUS_ID_CLGD5424 (0x25<<2) -#define CIRRUS_ID_CLGD5428 (0x26<<2) -#define CIRRUS_ID_CLGD5430 (0x28<<2) -#define CIRRUS_ID_CLGD5434 (0x2A<<2) -#define CIRRUS_ID_CLGD5436 (0x2B<<2) -#define CIRRUS_ID_CLGD5446 (0x2E<<2) - -// sequencer 0x07 -#define CIRRUS_SR7_BPP_VGA 0x00 -#define CIRRUS_SR7_BPP_SVGA 0x01 -#define CIRRUS_SR7_BPP_MASK 0x0e -#define CIRRUS_SR7_BPP_8 0x00 -#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02 -#define CIRRUS_SR7_BPP_24 0x04 -#define CIRRUS_SR7_BPP_16 0x06 -#define CIRRUS_SR7_BPP_32 0x08 -#define CIRRUS_SR7_ISAADDR_MASK 0xe0 - -// sequencer 0x0f -#define CIRRUS_MEMSIZE_512k 0x08 -#define CIRRUS_MEMSIZE_1M 0x10 -#define CIRRUS_MEMSIZE_2M 0x18 -#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled. - -// sequencer 0x12 -#define CIRRUS_CURSOR_SHOW 0x01 -#define CIRRUS_CURSOR_HIDDENPEL 0x02 -#define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear - -// sequencer 0x17 -#define CIRRUS_BUSTYPE_VLBFAST 0x10 -#define CIRRUS_BUSTYPE_PCI 0x20 -#define CIRRUS_BUSTYPE_VLBSLOW 0x30 -#define CIRRUS_BUSTYPE_ISA 0x38 -#define CIRRUS_MMIO_ENABLE 0x04 -#define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared. -#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80 - -// control 0x0b -#define CIRRUS_BANKING_DUAL 0x01 -#define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k - -// control 0x30 -#define CIRRUS_BLTMODE_BACKWARDS 0x01 -#define CIRRUS_BLTMODE_MEMSYSDEST 0x02 -#define CIRRUS_BLTMODE_MEMSYSSRC 0x04 -#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08 -#define CIRRUS_BLTMODE_PATTERNCOPY 0x40 -#define CIRRUS_BLTMODE_COLOREXPAND 0x80 -#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30 -#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00 -#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10 -#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 -#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 - -// control 0x31 -#define CIRRUS_BLT_BUSY 0x01 -#define CIRRUS_BLT_START 0x02 -#define CIRRUS_BLT_RESET 0x04 -#define CIRRUS_BLT_FIFOUSED 0x10 -#define CIRRUS_BLT_AUTOSTART 0x80 - -// control 0x32 -#define CIRRUS_ROP_0 0x00 -#define CIRRUS_ROP_SRC_AND_DST 0x05 -#define CIRRUS_ROP_NOP 0x06 -#define CIRRUS_ROP_SRC_AND_NOTDST 0x09 -#define CIRRUS_ROP_NOTDST 0x0b -#define CIRRUS_ROP_SRC 0x0d -#define CIRRUS_ROP_1 0x0e -#define CIRRUS_ROP_NOTSRC_AND_DST 0x50 -#define CIRRUS_ROP_SRC_XOR_DST 0x59 -#define CIRRUS_ROP_SRC_OR_DST 0x6d -#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90 -#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95 -#define CIRRUS_ROP_SRC_OR_NOTDST 0xad -#define CIRRUS_ROP_NOTSRC 0xd0 -#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6 -#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda - -#define CIRRUS_ROP_NOP_INDEX 2 -#define CIRRUS_ROP_SRC_INDEX 5 - -// control 0x33 -#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 -#define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02 -#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 - -// memory-mapped IO -#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword -#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword -#define CIRRUS_MMIO_BLTWIDTH 0x08 // word -#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word -#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word -#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word -#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword -#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword -#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte -#define CIRRUS_MMIO_BLTMODE 0x18 // byte -#define CIRRUS_MMIO_BLTROP 0x1a // byte -#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte -#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c // word? -#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word? -#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24 // word -#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26 // word -#define CIRRUS_MMIO_LINEARDRAW_END_X 0x28 // word -#define CIRRUS_MMIO_LINEARDRAW_END_Y 0x2a // word -#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c // byte -#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d // byte -#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e // byte -#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f // byte -#define CIRRUS_MMIO_BRESENHAM_K1 0x30 // word -#define CIRRUS_MMIO_BRESENHAM_K3 0x32 // word -#define CIRRUS_MMIO_BRESENHAM_ERROR 0x34 // word -#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36 // word -#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38 // byte -#define CIRRUS_MMIO_LINEDRAW_MODE 0x39 // byte -#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte - -#define CIRRUS_PNPMMIO_SIZE 0x1000 - -struct CirrusVGAState; -typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s, - uint8_t * dst, const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight); -typedef void (*cirrus_fill_t)(struct CirrusVGAState *s, - uint8_t *dst, int dst_pitch, int width, int height); - -typedef struct CirrusVGAState { - VGACommonState vga; - - MemoryRegion cirrus_vga_io; - MemoryRegion cirrus_linear_io; - MemoryRegion cirrus_linear_bitblt_io; - MemoryRegion cirrus_mmio_io; - MemoryRegion pci_bar; - bool linear_vram; /* vga.vram mapped over cirrus_linear_io */ - MemoryRegion low_mem_container; /* container for 0xa0000-0xc0000 */ - MemoryRegion low_mem; /* always mapped, overridden by: */ - MemoryRegion cirrus_bank[2]; /* aliases at 0xa0000-0xb0000 */ - uint32_t cirrus_addr_mask; - uint32_t linear_mmio_mask; - uint8_t cirrus_shadow_gr0; - uint8_t cirrus_shadow_gr1; - uint8_t cirrus_hidden_dac_lockindex; - uint8_t cirrus_hidden_dac_data; - uint32_t cirrus_bank_base[2]; - uint32_t cirrus_bank_limit[2]; - uint8_t cirrus_hidden_palette[48]; - int cirrus_blt_pixelwidth; - int cirrus_blt_width; - int cirrus_blt_height; - int cirrus_blt_dstpitch; - int cirrus_blt_srcpitch; - uint32_t cirrus_blt_fgcol; - uint32_t cirrus_blt_bgcol; - uint32_t cirrus_blt_dstaddr; - uint32_t cirrus_blt_srcaddr; - uint8_t cirrus_blt_mode; - uint8_t cirrus_blt_modeext; - cirrus_bitblt_rop_t cirrus_rop; -#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */ - uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE]; - uint8_t *cirrus_srcptr; - uint8_t *cirrus_srcptr_end; - uint32_t cirrus_srccounter; - /* hwcursor display state */ - int last_hw_cursor_size; - int last_hw_cursor_x; - int last_hw_cursor_y; - int last_hw_cursor_y_start; - int last_hw_cursor_y_end; - int real_vram_size; /* XXX: suppress that */ - int device_id; - int bustype; -} CirrusVGAState; - -typedef struct PCICirrusVGAState { - PCIDevice dev; - CirrusVGAState cirrus_vga; -} PCICirrusVGAState; - -#define TYPE_PCI_CIRRUS_VGA "cirrus-vga" -#define PCI_CIRRUS_VGA(obj) \ - OBJECT_CHECK(PCICirrusVGAState, (obj), TYPE_PCI_CIRRUS_VGA) - -#define TYPE_ISA_CIRRUS_VGA "isa-cirrus-vga" -#define ISA_CIRRUS_VGA(obj) \ - OBJECT_CHECK(ISACirrusVGAState, (obj), TYPE_ISA_CIRRUS_VGA) - -typedef struct ISACirrusVGAState { - ISADevice parent_obj; - - CirrusVGAState cirrus_vga; -} ISACirrusVGAState; - -static uint8_t rop_to_index[256]; - -/*************************************** - * - * prototypes. - * - ***************************************/ - - -static void cirrus_bitblt_reset(CirrusVGAState *s); -static void cirrus_update_memory_access(CirrusVGAState *s); - -/*************************************** - * - * raster operations - * - ***************************************/ - -static bool blit_region_is_unsafe(struct CirrusVGAState *s, - int32_t pitch, int32_t addr) -{ - if (pitch < 0) { - int64_t min = addr - + ((int64_t)s->cirrus_blt_height-1) * pitch; - int32_t max = addr - + s->cirrus_blt_width; - if (min < 0 || max > s->vga.vram_size) { - return true; - } - } else { - int64_t max = addr - + ((int64_t)s->cirrus_blt_height-1) * pitch - + s->cirrus_blt_width; - if (max > s->vga.vram_size) { - return true; - } - } - return false; -} - -static bool blit_is_unsafe(struct CirrusVGAState *s) -{ - /* should be the case, see cirrus_bitblt_start */ - assert(s->cirrus_blt_width > 0); - assert(s->cirrus_blt_height > 0); - - if (s->cirrus_blt_width > CIRRUS_BLTBUFSIZE) { - return true; - } - - if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch, - s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) { - return true; - } - if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch, - s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) { - return true; - } - - return false; -} - -static void cirrus_bitblt_rop_nop(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ -} - -static void cirrus_bitblt_fill_nop(CirrusVGAState *s, - uint8_t *dst, - int dstpitch, int bltwidth,int bltheight) -{ -} - -#define ROP_NAME 0 -#define ROP_FN(d, s) 0 -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_and_dst -#define ROP_FN(d, s) (s) & (d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_and_notdst -#define ROP_FN(d, s) (s) & (~(d)) -#include "cirrus_vga_rop.h" - -#define ROP_NAME notdst -#define ROP_FN(d, s) ~(d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src -#define ROP_FN(d, s) s -#include "cirrus_vga_rop.h" - -#define ROP_NAME 1 -#define ROP_FN(d, s) ~0 -#include "cirrus_vga_rop.h" - -#define ROP_NAME notsrc_and_dst -#define ROP_FN(d, s) (~(s)) & (d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_xor_dst -#define ROP_FN(d, s) (s) ^ (d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_or_dst -#define ROP_FN(d, s) (s) | (d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME notsrc_or_notdst -#define ROP_FN(d, s) (~(s)) | (~(d)) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_notxor_dst -#define ROP_FN(d, s) ~((s) ^ (d)) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_or_notdst -#define ROP_FN(d, s) (s) | (~(d)) -#include "cirrus_vga_rop.h" - -#define ROP_NAME notsrc -#define ROP_FN(d, s) (~(s)) -#include "cirrus_vga_rop.h" - -#define ROP_NAME notsrc_or_dst -#define ROP_FN(d, s) (~(s)) | (d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME notsrc_and_notdst -#define ROP_FN(d, s) (~(s)) & (~(d)) -#include "cirrus_vga_rop.h" - -static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = { - cirrus_bitblt_rop_fwd_0, - cirrus_bitblt_rop_fwd_src_and_dst, - cirrus_bitblt_rop_nop, - cirrus_bitblt_rop_fwd_src_and_notdst, - cirrus_bitblt_rop_fwd_notdst, - cirrus_bitblt_rop_fwd_src, - cirrus_bitblt_rop_fwd_1, - cirrus_bitblt_rop_fwd_notsrc_and_dst, - cirrus_bitblt_rop_fwd_src_xor_dst, - cirrus_bitblt_rop_fwd_src_or_dst, - cirrus_bitblt_rop_fwd_notsrc_or_notdst, - cirrus_bitblt_rop_fwd_src_notxor_dst, - cirrus_bitblt_rop_fwd_src_or_notdst, - cirrus_bitblt_rop_fwd_notsrc, - cirrus_bitblt_rop_fwd_notsrc_or_dst, - cirrus_bitblt_rop_fwd_notsrc_and_notdst, -}; - -static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = { - cirrus_bitblt_rop_bkwd_0, - cirrus_bitblt_rop_bkwd_src_and_dst, - cirrus_bitblt_rop_nop, - cirrus_bitblt_rop_bkwd_src_and_notdst, - cirrus_bitblt_rop_bkwd_notdst, - cirrus_bitblt_rop_bkwd_src, - cirrus_bitblt_rop_bkwd_1, - cirrus_bitblt_rop_bkwd_notsrc_and_dst, - cirrus_bitblt_rop_bkwd_src_xor_dst, - cirrus_bitblt_rop_bkwd_src_or_dst, - cirrus_bitblt_rop_bkwd_notsrc_or_notdst, - cirrus_bitblt_rop_bkwd_src_notxor_dst, - cirrus_bitblt_rop_bkwd_src_or_notdst, - cirrus_bitblt_rop_bkwd_notsrc, - cirrus_bitblt_rop_bkwd_notsrc_or_dst, - cirrus_bitblt_rop_bkwd_notsrc_and_notdst, -}; - -#define TRANSP_ROP(name) {\ - name ## _8,\ - name ## _16,\ - } -#define TRANSP_NOP(func) {\ - func,\ - func,\ - } - -static const cirrus_bitblt_rop_t cirrus_fwd_transp_rop[16][2] = { - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_0), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_dst), - TRANSP_NOP(cirrus_bitblt_rop_nop), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_notdst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notdst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_1), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_dst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_xor_dst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_dst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_notdst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_notxor_dst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_notdst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_dst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_notdst), -}; - -static const cirrus_bitblt_rop_t cirrus_bkwd_transp_rop[16][2] = { - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_0), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_dst), - TRANSP_NOP(cirrus_bitblt_rop_nop), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_notdst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notdst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_1), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_dst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_xor_dst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_dst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_notdst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_notxor_dst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_notdst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_dst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_notdst), -}; - -#define ROP2(name) {\ - name ## _8,\ - name ## _16,\ - name ## _24,\ - name ## _32,\ - } - -#define ROP_NOP2(func) {\ - func,\ - func,\ - func,\ - func,\ - } - -static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = { - ROP2(cirrus_patternfill_0), - ROP2(cirrus_patternfill_src_and_dst), - ROP_NOP2(cirrus_bitblt_rop_nop), - ROP2(cirrus_patternfill_src_and_notdst), - ROP2(cirrus_patternfill_notdst), - ROP2(cirrus_patternfill_src), - ROP2(cirrus_patternfill_1), - ROP2(cirrus_patternfill_notsrc_and_dst), - ROP2(cirrus_patternfill_src_xor_dst), - ROP2(cirrus_patternfill_src_or_dst), - ROP2(cirrus_patternfill_notsrc_or_notdst), - ROP2(cirrus_patternfill_src_notxor_dst), - ROP2(cirrus_patternfill_src_or_notdst), - ROP2(cirrus_patternfill_notsrc), - ROP2(cirrus_patternfill_notsrc_or_dst), - ROP2(cirrus_patternfill_notsrc_and_notdst), -}; - -static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = { - ROP2(cirrus_colorexpand_transp_0), - ROP2(cirrus_colorexpand_transp_src_and_dst), - ROP_NOP2(cirrus_bitblt_rop_nop), - ROP2(cirrus_colorexpand_transp_src_and_notdst), - ROP2(cirrus_colorexpand_transp_notdst), - ROP2(cirrus_colorexpand_transp_src), - ROP2(cirrus_colorexpand_transp_1), - ROP2(cirrus_colorexpand_transp_notsrc_and_dst), - ROP2(cirrus_colorexpand_transp_src_xor_dst), - ROP2(cirrus_colorexpand_transp_src_or_dst), - ROP2(cirrus_colorexpand_transp_notsrc_or_notdst), - ROP2(cirrus_colorexpand_transp_src_notxor_dst), - ROP2(cirrus_colorexpand_transp_src_or_notdst), - ROP2(cirrus_colorexpand_transp_notsrc), - ROP2(cirrus_colorexpand_transp_notsrc_or_dst), - ROP2(cirrus_colorexpand_transp_notsrc_and_notdst), -}; - -static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = { - ROP2(cirrus_colorexpand_0), - ROP2(cirrus_colorexpand_src_and_dst), - ROP_NOP2(cirrus_bitblt_rop_nop), - ROP2(cirrus_colorexpand_src_and_notdst), - ROP2(cirrus_colorexpand_notdst), - ROP2(cirrus_colorexpand_src), - ROP2(cirrus_colorexpand_1), - ROP2(cirrus_colorexpand_notsrc_and_dst), - ROP2(cirrus_colorexpand_src_xor_dst), - ROP2(cirrus_colorexpand_src_or_dst), - ROP2(cirrus_colorexpand_notsrc_or_notdst), - ROP2(cirrus_colorexpand_src_notxor_dst), - ROP2(cirrus_colorexpand_src_or_notdst), - ROP2(cirrus_colorexpand_notsrc), - ROP2(cirrus_colorexpand_notsrc_or_dst), - ROP2(cirrus_colorexpand_notsrc_and_notdst), -}; - -static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = { - ROP2(cirrus_colorexpand_pattern_transp_0), - ROP2(cirrus_colorexpand_pattern_transp_src_and_dst), - ROP_NOP2(cirrus_bitblt_rop_nop), - ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst), - ROP2(cirrus_colorexpand_pattern_transp_notdst), - ROP2(cirrus_colorexpand_pattern_transp_src), - ROP2(cirrus_colorexpand_pattern_transp_1), - ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst), - ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst), - ROP2(cirrus_colorexpand_pattern_transp_src_or_dst), - ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst), - ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst), - ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst), - ROP2(cirrus_colorexpand_pattern_transp_notsrc), - ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst), - ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst), -}; - -static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = { - ROP2(cirrus_colorexpand_pattern_0), - ROP2(cirrus_colorexpand_pattern_src_and_dst), - ROP_NOP2(cirrus_bitblt_rop_nop), - ROP2(cirrus_colorexpand_pattern_src_and_notdst), - ROP2(cirrus_colorexpand_pattern_notdst), - ROP2(cirrus_colorexpand_pattern_src), - ROP2(cirrus_colorexpand_pattern_1), - ROP2(cirrus_colorexpand_pattern_notsrc_and_dst), - ROP2(cirrus_colorexpand_pattern_src_xor_dst), - ROP2(cirrus_colorexpand_pattern_src_or_dst), - ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst), - ROP2(cirrus_colorexpand_pattern_src_notxor_dst), - ROP2(cirrus_colorexpand_pattern_src_or_notdst), - ROP2(cirrus_colorexpand_pattern_notsrc), - ROP2(cirrus_colorexpand_pattern_notsrc_or_dst), - ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst), -}; - -static const cirrus_fill_t cirrus_fill[16][4] = { - ROP2(cirrus_fill_0), - ROP2(cirrus_fill_src_and_dst), - ROP_NOP2(cirrus_bitblt_fill_nop), - ROP2(cirrus_fill_src_and_notdst), - ROP2(cirrus_fill_notdst), - ROP2(cirrus_fill_src), - ROP2(cirrus_fill_1), - ROP2(cirrus_fill_notsrc_and_dst), - ROP2(cirrus_fill_src_xor_dst), - ROP2(cirrus_fill_src_or_dst), - ROP2(cirrus_fill_notsrc_or_notdst), - ROP2(cirrus_fill_src_notxor_dst), - ROP2(cirrus_fill_src_or_notdst), - ROP2(cirrus_fill_notsrc), - ROP2(cirrus_fill_notsrc_or_dst), - ROP2(cirrus_fill_notsrc_and_notdst), -}; - -static inline void cirrus_bitblt_fgcol(CirrusVGAState *s) -{ - unsigned int color; - switch (s->cirrus_blt_pixelwidth) { - case 1: - s->cirrus_blt_fgcol = s->cirrus_shadow_gr1; - break; - case 2: - color = s->cirrus_shadow_gr1 | (s->vga.gr[0x11] << 8); - s->cirrus_blt_fgcol = le16_to_cpu(color); - break; - case 3: - s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 | - (s->vga.gr[0x11] << 8) | (s->vga.gr[0x13] << 16); - break; - default: - case 4: - color = s->cirrus_shadow_gr1 | (s->vga.gr[0x11] << 8) | - (s->vga.gr[0x13] << 16) | (s->vga.gr[0x15] << 24); - s->cirrus_blt_fgcol = le32_to_cpu(color); - break; - } -} - -static inline void cirrus_bitblt_bgcol(CirrusVGAState *s) -{ - unsigned int color; - switch (s->cirrus_blt_pixelwidth) { - case 1: - s->cirrus_blt_bgcol = s->cirrus_shadow_gr0; - break; - case 2: - color = s->cirrus_shadow_gr0 | (s->vga.gr[0x10] << 8); - s->cirrus_blt_bgcol = le16_to_cpu(color); - break; - case 3: - s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 | - (s->vga.gr[0x10] << 8) | (s->vga.gr[0x12] << 16); - break; - default: - case 4: - color = s->cirrus_shadow_gr0 | (s->vga.gr[0x10] << 8) | - (s->vga.gr[0x12] << 16) | (s->vga.gr[0x14] << 24); - s->cirrus_blt_bgcol = le32_to_cpu(color); - break; - } -} - -static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, - int off_pitch, int bytesperline, - int lines) -{ - int y; - int off_cur; - int off_cur_end; - - for (y = 0; y < lines; y++) { - off_cur = off_begin; - off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask; - memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur); - off_begin += off_pitch; - } -} - -static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, - const uint8_t * src) -{ - uint8_t *dst; - - dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask); - - if (blit_is_unsafe(s)) - return 0; - - (*s->cirrus_rop) (s, dst, src, - s->cirrus_blt_dstpitch, 0, - s->cirrus_blt_width, s->cirrus_blt_height); - cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, - s->cirrus_blt_dstpitch, s->cirrus_blt_width, - s->cirrus_blt_height); - return 1; -} - -/* fill */ - -static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop) -{ - cirrus_fill_t rop_func; - - if (blit_is_unsafe(s)) { - return 0; - } - rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - rop_func(s, s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), - s->cirrus_blt_dstpitch, - s->cirrus_blt_width, s->cirrus_blt_height); - cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, - s->cirrus_blt_dstpitch, s->cirrus_blt_width, - s->cirrus_blt_height); - cirrus_bitblt_reset(s); - return 1; -} - -/*************************************** - * - * bitblt (video-to-video) - * - ***************************************/ - -static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) -{ - return cirrus_bitblt_common_patterncopy(s, - s->vga.vram_ptr + ((s->cirrus_blt_srcaddr & ~7) & - s->cirrus_addr_mask)); -} - -static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) -{ - int sx = 0, sy = 0; - int dx = 0, dy = 0; - int depth = 0; - int notify = 0; - - /* make sure to only copy if it's a plain copy ROP */ - if (*s->cirrus_rop == cirrus_bitblt_rop_fwd_src || - *s->cirrus_rop == cirrus_bitblt_rop_bkwd_src) { - - int width, height; - - depth = s->vga.get_bpp(&s->vga) / 8; - s->vga.get_resolution(&s->vga, &width, &height); - - /* extra x, y */ - sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth; - sy = (src / ABS(s->cirrus_blt_srcpitch)); - dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth; - dy = (dst / ABS(s->cirrus_blt_dstpitch)); - - /* normalize width */ - w /= depth; - - /* if we're doing a backward copy, we have to adjust - our x/y to be the upper left corner (instead of the lower - right corner) */ - if (s->cirrus_blt_dstpitch < 0) { - sx -= (s->cirrus_blt_width / depth) - 1; - dx -= (s->cirrus_blt_width / depth) - 1; - sy -= s->cirrus_blt_height - 1; - dy -= s->cirrus_blt_height - 1; - } - - /* are we in the visible portion of memory? */ - if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 && - (sx + w) <= width && (sy + h) <= height && - (dx + w) <= width && (dy + h) <= height) { - notify = 1; - } - } - - /* we have to flush all pending changes so that the copy - is generated at the appropriate moment in time */ - if (notify) - graphic_hw_update(s->vga.con); - - (*s->cirrus_rop) (s, s->vga.vram_ptr + - (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), - s->vga.vram_ptr + - (s->cirrus_blt_srcaddr & s->cirrus_addr_mask), - s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, - s->cirrus_blt_width, s->cirrus_blt_height); - - 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 */ - - cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, - s->cirrus_blt_dstpitch, s->cirrus_blt_width, - s->cirrus_blt_height); -} - -static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) -{ - if (blit_is_unsafe(s)) - return 0; - - cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr, - s->cirrus_blt_srcaddr - s->vga.start_addr, - s->cirrus_blt_width, s->cirrus_blt_height); - - return 1; -} - -/*************************************** - * - * bitblt (cpu-to-video) - * - ***************************************/ - -static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s) -{ - int copy_count; - uint8_t *end_ptr; - - if (s->cirrus_srccounter > 0) { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf); - the_end: - s->cirrus_srccounter = 0; - cirrus_bitblt_reset(s); - } else { - /* at least one scan line */ - do { - (*s->cirrus_rop)(s, s->vga.vram_ptr + - (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), - s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1); - cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, - s->cirrus_blt_width, 1); - s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch; - s->cirrus_srccounter -= s->cirrus_blt_srcpitch; - if (s->cirrus_srccounter <= 0) - goto the_end; - /* more bytes than needed can be transferred because of - word alignment, so we keep them for the next line */ - /* XXX: keep alignment to speed up transfer */ - end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; - copy_count = s->cirrus_srcptr_end - end_ptr; - memmove(s->cirrus_bltbuf, end_ptr, copy_count); - s->cirrus_srcptr = s->cirrus_bltbuf + copy_count; - s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; - } while (s->cirrus_srcptr >= s->cirrus_srcptr_end); - } - } -} - -/*************************************** - * - * bitblt wrapper - * - ***************************************/ - -static void cirrus_bitblt_reset(CirrusVGAState * s) -{ - int need_update; - - s->vga.gr[0x31] &= - ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED); - need_update = s->cirrus_srcptr != &s->cirrus_bltbuf[0] - || s->cirrus_srcptr_end != &s->cirrus_bltbuf[0]; - s->cirrus_srcptr = &s->cirrus_bltbuf[0]; - s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; - s->cirrus_srccounter = 0; - if (!need_update) - return; - cirrus_update_memory_access(s); -} - -static int cirrus_bitblt_cputovideo(CirrusVGAState * s) -{ - int w; - - s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; - s->cirrus_srcptr = &s->cirrus_bltbuf[0]; - s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; - - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { - s->cirrus_blt_srcpitch = 8; - } else { - /* XXX: check for 24 bpp */ - s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth; - } - s->cirrus_srccounter = s->cirrus_blt_srcpitch; - } else { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { - w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth; - if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) - s->cirrus_blt_srcpitch = ((w + 31) >> 5); - else - s->cirrus_blt_srcpitch = ((w + 7) >> 3); - } else { - /* always align input size to 32 bits */ - s->cirrus_blt_srcpitch = (s->cirrus_blt_width + 3) & ~3; - } - s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height; - } - s->cirrus_srcptr = s->cirrus_bltbuf; - s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; - cirrus_update_memory_access(s); - return 1; -} - -static int cirrus_bitblt_videotocpu(CirrusVGAState * s) -{ - /* XXX */ -#ifdef DEBUG_BITBLT - printf("cirrus: bitblt (video to cpu) is not implemented yet\n"); -#endif - return 0; -} - -static int cirrus_bitblt_videotovideo(CirrusVGAState * s) -{ - int ret; - - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - ret = cirrus_bitblt_videotovideo_patterncopy(s); - } else { - ret = cirrus_bitblt_videotovideo_copy(s); - } - if (ret) - cirrus_bitblt_reset(s); - return ret; -} - -static void cirrus_bitblt_start(CirrusVGAState * s) -{ - uint8_t blt_rop; - - s->vga.gr[0x31] |= CIRRUS_BLT_BUSY; - - s->cirrus_blt_width = (s->vga.gr[0x20] | (s->vga.gr[0x21] << 8)) + 1; - s->cirrus_blt_height = (s->vga.gr[0x22] | (s->vga.gr[0x23] << 8)) + 1; - s->cirrus_blt_dstpitch = (s->vga.gr[0x24] | (s->vga.gr[0x25] << 8)); - s->cirrus_blt_srcpitch = (s->vga.gr[0x26] | (s->vga.gr[0x27] << 8)); - s->cirrus_blt_dstaddr = - (s->vga.gr[0x28] | (s->vga.gr[0x29] << 8) | (s->vga.gr[0x2a] << 16)); - s->cirrus_blt_srcaddr = - (s->vga.gr[0x2c] | (s->vga.gr[0x2d] << 8) | (s->vga.gr[0x2e] << 16)); - s->cirrus_blt_mode = s->vga.gr[0x30]; - s->cirrus_blt_modeext = s->vga.gr[0x33]; - blt_rop = s->vga.gr[0x32]; - -#ifdef DEBUG_BITBLT - printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n", - blt_rop, - s->cirrus_blt_mode, - s->cirrus_blt_modeext, - s->cirrus_blt_width, - s->cirrus_blt_height, - s->cirrus_blt_dstpitch, - s->cirrus_blt_srcpitch, - s->cirrus_blt_dstaddr, - s->cirrus_blt_srcaddr, - s->vga.gr[0x2f]); -#endif - - switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { - case CIRRUS_BLTMODE_PIXELWIDTH8: - s->cirrus_blt_pixelwidth = 1; - break; - case CIRRUS_BLTMODE_PIXELWIDTH16: - s->cirrus_blt_pixelwidth = 2; - break; - case CIRRUS_BLTMODE_PIXELWIDTH24: - s->cirrus_blt_pixelwidth = 3; - break; - case CIRRUS_BLTMODE_PIXELWIDTH32: - s->cirrus_blt_pixelwidth = 4; - break; - default: -#ifdef DEBUG_BITBLT - printf("cirrus: bitblt - pixel width is unknown\n"); -#endif - goto bitblt_ignore; - } - s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK; - - if ((s-> - cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC | - CIRRUS_BLTMODE_MEMSYSDEST)) - == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) { -#ifdef DEBUG_BITBLT - printf("cirrus: bitblt - memory-to-memory copy is requested\n"); -#endif - goto bitblt_ignore; - } - - if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) && - (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | - CIRRUS_BLTMODE_TRANSPARENTCOMP | - CIRRUS_BLTMODE_PATTERNCOPY | - CIRRUS_BLTMODE_COLOREXPAND)) == - (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) { - cirrus_bitblt_fgcol(s); - cirrus_bitblt_solidfill(s, blt_rop); - } else { - if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND | - CIRRUS_BLTMODE_PATTERNCOPY)) == - CIRRUS_BLTMODE_COLOREXPAND) { - - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { - if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) - cirrus_bitblt_bgcol(s); - else - cirrus_bitblt_fgcol(s); - s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } else { - cirrus_bitblt_fgcol(s); - cirrus_bitblt_bgcol(s); - s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } - } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { - if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) - cirrus_bitblt_bgcol(s); - else - cirrus_bitblt_fgcol(s); - s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } else { - cirrus_bitblt_fgcol(s); - cirrus_bitblt_bgcol(s); - s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } - } else { - s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } - } else { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { - if (s->cirrus_blt_pixelwidth > 2) { - printf("src transparent without colorexpand must be 8bpp or 16bpp\n"); - goto bitblt_ignore; - } - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) { - s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch; - s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch; - s->cirrus_rop = cirrus_bkwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } else { - s->cirrus_rop = cirrus_fwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } - } else { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) { - s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch; - s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch; - s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]]; - } else { - s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]]; - } - } - } - // setup bitblt engine. - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) { - if (!cirrus_bitblt_cputovideo(s)) - goto bitblt_ignore; - } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) { - if (!cirrus_bitblt_videotocpu(s)) - goto bitblt_ignore; - } else { - if (!cirrus_bitblt_videotovideo(s)) - goto bitblt_ignore; - } - } - return; - bitblt_ignore:; - cirrus_bitblt_reset(s); -} - -static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value) -{ - unsigned old_value; - - old_value = s->vga.gr[0x31]; - s->vga.gr[0x31] = reg_value; - - if (((old_value & CIRRUS_BLT_RESET) != 0) && - ((reg_value & CIRRUS_BLT_RESET) == 0)) { - cirrus_bitblt_reset(s); - } else if (((old_value & CIRRUS_BLT_START) == 0) && - ((reg_value & CIRRUS_BLT_START) != 0)) { - cirrus_bitblt_start(s); - } -} - - -/*************************************** - * - * basic parameters - * - ***************************************/ - -static void cirrus_get_offsets(VGACommonState *s1, - uint32_t *pline_offset, - uint32_t *pstart_addr, - uint32_t *pline_compare) -{ - CirrusVGAState * s = container_of(s1, CirrusVGAState, vga); - uint32_t start_addr, line_offset, line_compare; - - line_offset = s->vga.cr[0x13] - | ((s->vga.cr[0x1b] & 0x10) << 4); - line_offset <<= 3; - *pline_offset = line_offset; - - start_addr = (s->vga.cr[0x0c] << 8) - | s->vga.cr[0x0d] - | ((s->vga.cr[0x1b] & 0x01) << 16) - | ((s->vga.cr[0x1b] & 0x0c) << 15) - | ((s->vga.cr[0x1d] & 0x80) << 12); - *pstart_addr = start_addr; - - line_compare = s->vga.cr[0x18] | - ((s->vga.cr[0x07] & 0x10) << 4) | - ((s->vga.cr[0x09] & 0x40) << 3); - *pline_compare = line_compare; -} - -static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s) -{ - uint32_t ret = 16; - - switch (s->cirrus_hidden_dac_data & 0xf) { - case 0: - ret = 15; - break; /* Sierra HiColor */ - case 1: - ret = 16; - break; /* XGA HiColor */ - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: invalid DAC value %x in 16bpp\n", - (s->cirrus_hidden_dac_data & 0xf)); -#endif - ret = 15; /* XXX */ - break; - } - return ret; -} - -static int cirrus_get_bpp(VGACommonState *s1) -{ - CirrusVGAState * s = container_of(s1, CirrusVGAState, vga); - uint32_t ret = 8; - - if ((s->vga.sr[0x07] & 0x01) != 0) { - /* Cirrus SVGA */ - switch (s->vga.sr[0x07] & CIRRUS_SR7_BPP_MASK) { - case CIRRUS_SR7_BPP_8: - ret = 8; - break; - case CIRRUS_SR7_BPP_16_DOUBLEVCLK: - ret = cirrus_get_bpp16_depth(s); - break; - case CIRRUS_SR7_BPP_24: - ret = 24; - break; - case CIRRUS_SR7_BPP_16: - ret = cirrus_get_bpp16_depth(s); - break; - case CIRRUS_SR7_BPP_32: - ret = 32; - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: unknown bpp - sr7=%x\n", s->vga.sr[0x7]); -#endif - ret = 8; - break; - } - } else { - /* VGA */ - ret = 0; - } - - return ret; -} - -static void cirrus_get_resolution(VGACommonState *s, int *pwidth, int *pheight) -{ - int width, height; - - width = (s->cr[0x01] + 1) * 8; - height = s->cr[0x12] | - ((s->cr[0x07] & 0x02) << 7) | - ((s->cr[0x07] & 0x40) << 3); - height = (height + 1); - /* interlace support */ - if (s->cr[0x1a] & 0x01) - height = height * 2; - *pwidth = width; - *pheight = height; -} - -/*************************************** - * - * bank memory - * - ***************************************/ - -static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index) -{ - unsigned offset; - unsigned limit; - - if ((s->vga.gr[0x0b] & 0x01) != 0) /* dual bank */ - offset = s->vga.gr[0x09 + bank_index]; - else /* single bank */ - offset = s->vga.gr[0x09]; - - if ((s->vga.gr[0x0b] & 0x20) != 0) - offset <<= 14; - else - offset <<= 12; - - if (s->real_vram_size <= offset) - limit = 0; - else - limit = s->real_vram_size - offset; - - if (((s->vga.gr[0x0b] & 0x01) == 0) && (bank_index != 0)) { - if (limit > 0x8000) { - offset += 0x8000; - limit -= 0x8000; - } else { - limit = 0; - } - } - - if (limit > 0) { - s->cirrus_bank_base[bank_index] = offset; - s->cirrus_bank_limit[bank_index] = limit; - } else { - s->cirrus_bank_base[bank_index] = 0; - s->cirrus_bank_limit[bank_index] = 0; - } -} - -/*************************************** - * - * I/O access between 0x3c4-0x3c5 - * - ***************************************/ - -static int cirrus_vga_read_sr(CirrusVGAState * s) -{ - switch (s->vga.sr_index) { - case 0x00: // Standard VGA - case 0x01: // Standard VGA - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - return s->vga.sr[s->vga.sr_index]; - case 0x06: // Unlock Cirrus extensions - return s->vga.sr[s->vga.sr_index]; - case 0x10: - case 0x30: - case 0x50: - case 0x70: // Graphics Cursor X - case 0x90: - case 0xb0: - case 0xd0: - case 0xf0: // Graphics Cursor X - return s->vga.sr[0x10]; - case 0x11: - case 0x31: - case 0x51: - case 0x71: // Graphics Cursor Y - case 0x91: - case 0xb1: - case 0xd1: - case 0xf1: // Graphics Cursor Y - return s->vga.sr[0x11]; - case 0x05: // ??? - case 0x07: // Extended Sequencer Mode - case 0x08: // EEPROM Control - case 0x09: // Scratch Register 0 - case 0x0a: // Scratch Register 1 - case 0x0b: // VCLK 0 - case 0x0c: // VCLK 1 - case 0x0d: // VCLK 2 - case 0x0e: // VCLK 3 - case 0x0f: // DRAM Control - case 0x12: // Graphics Cursor Attribute - case 0x13: // Graphics Cursor Pattern Address - case 0x14: // Scratch Register 2 - case 0x15: // Scratch Register 3 - case 0x16: // Performance Tuning Register - case 0x17: // Configuration Readback and Extended Control - case 0x18: // Signature Generator Control - case 0x19: // Signal Generator Result - case 0x1a: // Signal Generator Result - case 0x1b: // VCLK 0 Denominator & Post - case 0x1c: // VCLK 1 Denominator & Post - case 0x1d: // VCLK 2 Denominator & Post - case 0x1e: // VCLK 3 Denominator & Post - case 0x1f: // BIOS Write Enable and MCLK select -#ifdef DEBUG_CIRRUS - printf("cirrus: handled inport sr_index %02x\n", s->vga.sr_index); -#endif - return s->vga.sr[s->vga.sr_index]; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: inport sr_index %02x\n", s->vga.sr_index); -#endif - return 0xff; - break; - } -} - -static void cirrus_vga_write_sr(CirrusVGAState * s, uint32_t val) -{ - switch (s->vga.sr_index) { - case 0x00: // Standard VGA - case 0x01: // Standard VGA - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - s->vga.sr[s->vga.sr_index] = val & sr_mask[s->vga.sr_index]; - if (s->vga.sr_index == 1) - s->vga.update_retrace_info(&s->vga); - break; - case 0x06: // Unlock Cirrus extensions - val &= 0x17; - if (val == 0x12) { - s->vga.sr[s->vga.sr_index] = 0x12; - } else { - s->vga.sr[s->vga.sr_index] = 0x0f; - } - break; - case 0x10: - case 0x30: - case 0x50: - case 0x70: // Graphics Cursor X - case 0x90: - case 0xb0: - case 0xd0: - case 0xf0: // Graphics Cursor X - s->vga.sr[0x10] = val; - s->vga.hw_cursor_x = (val << 3) | (s->vga.sr_index >> 5); - break; - case 0x11: - case 0x31: - case 0x51: - case 0x71: // Graphics Cursor Y - case 0x91: - case 0xb1: - case 0xd1: - case 0xf1: // Graphics Cursor Y - s->vga.sr[0x11] = val; - s->vga.hw_cursor_y = (val << 3) | (s->vga.sr_index >> 5); - break; - case 0x07: // Extended Sequencer Mode - cirrus_update_memory_access(s); - case 0x08: // EEPROM Control - case 0x09: // Scratch Register 0 - case 0x0a: // Scratch Register 1 - case 0x0b: // VCLK 0 - case 0x0c: // VCLK 1 - case 0x0d: // VCLK 2 - case 0x0e: // VCLK 3 - case 0x0f: // DRAM Control - case 0x13: // Graphics Cursor Pattern Address - case 0x14: // Scratch Register 2 - case 0x15: // Scratch Register 3 - case 0x16: // Performance Tuning Register - case 0x18: // Signature Generator Control - case 0x19: // Signature Generator Result - case 0x1a: // Signature Generator Result - case 0x1b: // VCLK 0 Denominator & Post - case 0x1c: // VCLK 1 Denominator & Post - case 0x1d: // VCLK 2 Denominator & Post - case 0x1e: // VCLK 3 Denominator & Post - case 0x1f: // BIOS Write Enable and MCLK select - s->vga.sr[s->vga.sr_index] = val; -#ifdef DEBUG_CIRRUS - printf("cirrus: handled outport sr_index %02x, sr_value %02x\n", - s->vga.sr_index, val); -#endif - break; - case 0x12: // Graphics Cursor Attribute - s->vga.sr[0x12] = val; - s->vga.force_shadow = !!(val & CIRRUS_CURSOR_SHOW); -#ifdef DEBUG_CIRRUS - printf("cirrus: cursor ctl SR12=%02x (force shadow: %d)\n", - val, s->vga.force_shadow); -#endif - break; - case 0x17: // Configuration Readback and Extended Control - s->vga.sr[s->vga.sr_index] = (s->vga.sr[s->vga.sr_index] & 0x38) - | (val & 0xc7); - cirrus_update_memory_access(s); - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: outport sr_index %02x, sr_value %02x\n", - s->vga.sr_index, val); -#endif - break; - } -} - -/*************************************** - * - * I/O access at 0x3c6 - * - ***************************************/ - -static int cirrus_read_hidden_dac(CirrusVGAState * s) -{ - if (++s->cirrus_hidden_dac_lockindex == 5) { - s->cirrus_hidden_dac_lockindex = 0; - return s->cirrus_hidden_dac_data; - } - return 0xff; -} - -static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value) -{ - if (s->cirrus_hidden_dac_lockindex == 4) { - s->cirrus_hidden_dac_data = reg_value; -#if defined(DEBUG_CIRRUS) - printf("cirrus: outport hidden DAC, value %02x\n", reg_value); -#endif - } - s->cirrus_hidden_dac_lockindex = 0; -} - -/*************************************** - * - * I/O access at 0x3c9 - * - ***************************************/ - -static int cirrus_vga_read_palette(CirrusVGAState * s) -{ - int val; - - if ((s->vga.sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) { - val = s->cirrus_hidden_palette[(s->vga.dac_read_index & 0x0f) * 3 + - s->vga.dac_sub_index]; - } else { - val = s->vga.palette[s->vga.dac_read_index * 3 + s->vga.dac_sub_index]; - } - if (++s->vga.dac_sub_index == 3) { - s->vga.dac_sub_index = 0; - s->vga.dac_read_index++; - } - return val; -} - -static void cirrus_vga_write_palette(CirrusVGAState * s, int reg_value) -{ - s->vga.dac_cache[s->vga.dac_sub_index] = reg_value; - if (++s->vga.dac_sub_index == 3) { - if ((s->vga.sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) { - memcpy(&s->cirrus_hidden_palette[(s->vga.dac_write_index & 0x0f) * 3], - s->vga.dac_cache, 3); - } else { - memcpy(&s->vga.palette[s->vga.dac_write_index * 3], s->vga.dac_cache, 3); - } - /* XXX update cursor */ - s->vga.dac_sub_index = 0; - s->vga.dac_write_index++; - } -} - -/*************************************** - * - * I/O access between 0x3ce-0x3cf - * - ***************************************/ - -static int cirrus_vga_read_gr(CirrusVGAState * s, unsigned reg_index) -{ - switch (reg_index) { - case 0x00: // Standard VGA, BGCOLOR 0x000000ff - return s->cirrus_shadow_gr0; - case 0x01: // Standard VGA, FGCOLOR 0x000000ff - return s->cirrus_shadow_gr1; - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - case 0x06: // Standard VGA - case 0x07: // Standard VGA - case 0x08: // Standard VGA - return s->vga.gr[s->vga.gr_index]; - case 0x05: // Standard VGA, Cirrus extended mode - default: - break; - } - - if (reg_index < 0x3a) { - return s->vga.gr[reg_index]; - } else { -#ifdef DEBUG_CIRRUS - printf("cirrus: inport gr_index %02x\n", reg_index); -#endif - return 0xff; - } -} - -static void -cirrus_vga_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) -{ -#if defined(DEBUG_BITBLT) && 0 - printf("gr%02x: %02x\n", reg_index, reg_value); -#endif - switch (reg_index) { - case 0x00: // Standard VGA, BGCOLOR 0x000000ff - s->vga.gr[reg_index] = reg_value & gr_mask[reg_index]; - s->cirrus_shadow_gr0 = reg_value; - break; - case 0x01: // Standard VGA, FGCOLOR 0x000000ff - s->vga.gr[reg_index] = reg_value & gr_mask[reg_index]; - s->cirrus_shadow_gr1 = reg_value; - break; - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - case 0x06: // Standard VGA - case 0x07: // Standard VGA - case 0x08: // Standard VGA - s->vga.gr[reg_index] = reg_value & gr_mask[reg_index]; - break; - case 0x05: // Standard VGA, Cirrus extended mode - s->vga.gr[reg_index] = reg_value & 0x7f; - cirrus_update_memory_access(s); - break; - case 0x09: // bank offset #0 - case 0x0A: // bank offset #1 - s->vga.gr[reg_index] = reg_value; - cirrus_update_bank_ptr(s, 0); - cirrus_update_bank_ptr(s, 1); - cirrus_update_memory_access(s); - break; - case 0x0B: - s->vga.gr[reg_index] = reg_value; - cirrus_update_bank_ptr(s, 0); - cirrus_update_bank_ptr(s, 1); - cirrus_update_memory_access(s); - break; - case 0x10: // BGCOLOR 0x0000ff00 - case 0x11: // FGCOLOR 0x0000ff00 - case 0x12: // BGCOLOR 0x00ff0000 - case 0x13: // FGCOLOR 0x00ff0000 - case 0x14: // BGCOLOR 0xff000000 - case 0x15: // FGCOLOR 0xff000000 - case 0x20: // BLT WIDTH 0x0000ff - case 0x22: // BLT HEIGHT 0x0000ff - case 0x24: // BLT DEST PITCH 0x0000ff - case 0x26: // BLT SRC PITCH 0x0000ff - case 0x28: // BLT DEST ADDR 0x0000ff - case 0x29: // BLT DEST ADDR 0x00ff00 - case 0x2c: // BLT SRC ADDR 0x0000ff - case 0x2d: // BLT SRC ADDR 0x00ff00 - case 0x2f: // BLT WRITEMASK - case 0x30: // BLT MODE - case 0x32: // RASTER OP - case 0x33: // BLT MODEEXT - case 0x34: // BLT TRANSPARENT COLOR 0x00ff - case 0x35: // BLT TRANSPARENT COLOR 0xff00 - case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff - case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00 - s->vga.gr[reg_index] = reg_value; - break; - case 0x21: // BLT WIDTH 0x001f00 - case 0x23: // BLT HEIGHT 0x001f00 - case 0x25: // BLT DEST PITCH 0x001f00 - case 0x27: // BLT SRC PITCH 0x001f00 - s->vga.gr[reg_index] = reg_value & 0x1f; - break; - case 0x2a: // BLT DEST ADDR 0x3f0000 - s->vga.gr[reg_index] = reg_value & 0x3f; - /* if auto start mode, starts bit blt now */ - if (s->vga.gr[0x31] & CIRRUS_BLT_AUTOSTART) { - cirrus_bitblt_start(s); - } - break; - case 0x2e: // BLT SRC ADDR 0x3f0000 - s->vga.gr[reg_index] = reg_value & 0x3f; - break; - case 0x31: // BLT STATUS/START - cirrus_write_bitblt(s, reg_value); - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index, - reg_value); -#endif - break; - } -} - -/*************************************** - * - * I/O access between 0x3d4-0x3d5 - * - ***************************************/ - -static int cirrus_vga_read_cr(CirrusVGAState * s, unsigned reg_index) -{ - switch (reg_index) { - case 0x00: // Standard VGA - case 0x01: // Standard VGA - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - case 0x05: // Standard VGA - case 0x06: // Standard VGA - case 0x07: // Standard VGA - case 0x08: // Standard VGA - case 0x09: // Standard VGA - case 0x0a: // Standard VGA - case 0x0b: // Standard VGA - case 0x0c: // Standard VGA - case 0x0d: // Standard VGA - case 0x0e: // Standard VGA - case 0x0f: // Standard VGA - case 0x10: // Standard VGA - case 0x11: // Standard VGA - case 0x12: // Standard VGA - case 0x13: // Standard VGA - case 0x14: // Standard VGA - case 0x15: // Standard VGA - case 0x16: // Standard VGA - case 0x17: // Standard VGA - case 0x18: // Standard VGA - return s->vga.cr[s->vga.cr_index]; - case 0x24: // Attribute Controller Toggle Readback (R) - return (s->vga.ar_flip_flop << 7); - case 0x19: // Interlace End - case 0x1a: // Miscellaneous Control - case 0x1b: // Extended Display Control - case 0x1c: // Sync Adjust and Genlock - case 0x1d: // Overlay Extended Control - case 0x22: // Graphics Data Latches Readback (R) - case 0x25: // Part Status - case 0x27: // Part ID (R) - return s->vga.cr[s->vga.cr_index]; - case 0x26: // Attribute Controller Index Readback (R) - return s->vga.ar_index & 0x3f; - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: inport cr_index %02x\n", reg_index); -#endif - return 0xff; - } -} - -static void cirrus_vga_write_cr(CirrusVGAState * s, int reg_value) -{ - switch (s->vga.cr_index) { - case 0x00: // Standard VGA - case 0x01: // Standard VGA - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - case 0x05: // Standard VGA - case 0x06: // Standard VGA - case 0x07: // Standard VGA - case 0x08: // Standard VGA - case 0x09: // Standard VGA - case 0x0a: // Standard VGA - case 0x0b: // Standard VGA - case 0x0c: // Standard VGA - case 0x0d: // Standard VGA - case 0x0e: // Standard VGA - case 0x0f: // Standard VGA - case 0x10: // Standard VGA - case 0x11: // Standard VGA - case 0x12: // Standard VGA - case 0x13: // Standard VGA - case 0x14: // Standard VGA - case 0x15: // Standard VGA - case 0x16: // Standard VGA - case 0x17: // Standard VGA - case 0x18: // Standard VGA - /* handle CR0-7 protection */ - if ((s->vga.cr[0x11] & 0x80) && s->vga.cr_index <= 7) { - /* can always write bit 4 of CR7 */ - if (s->vga.cr_index == 7) - s->vga.cr[7] = (s->vga.cr[7] & ~0x10) | (reg_value & 0x10); - return; - } - s->vga.cr[s->vga.cr_index] = reg_value; - switch(s->vga.cr_index) { - case 0x00: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x11: - case 0x17: - s->vga.update_retrace_info(&s->vga); - break; - } - break; - case 0x19: // Interlace End - case 0x1a: // Miscellaneous Control - case 0x1b: // Extended Display Control - case 0x1c: // Sync Adjust and Genlock - case 0x1d: // Overlay Extended Control - s->vga.cr[s->vga.cr_index] = reg_value; -#ifdef DEBUG_CIRRUS - printf("cirrus: handled outport cr_index %02x, cr_value %02x\n", - s->vga.cr_index, reg_value); -#endif - break; - case 0x22: // Graphics Data Latches Readback (R) - case 0x24: // Attribute Controller Toggle Readback (R) - case 0x26: // Attribute Controller Index Readback (R) - case 0x27: // Part ID (R) - break; - case 0x25: // Part Status - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: outport cr_index %02x, cr_value %02x\n", - s->vga.cr_index, reg_value); -#endif - break; - } -} - -/*************************************** - * - * memory-mapped I/O (bitblt) - * - ***************************************/ - -static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address) -{ - int value = 0xff; - - switch (address) { - case (CIRRUS_MMIO_BLTBGCOLOR + 0): - value = cirrus_vga_read_gr(s, 0x00); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 1): - value = cirrus_vga_read_gr(s, 0x10); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 2): - value = cirrus_vga_read_gr(s, 0x12); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 3): - value = cirrus_vga_read_gr(s, 0x14); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 0): - value = cirrus_vga_read_gr(s, 0x01); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 1): - value = cirrus_vga_read_gr(s, 0x11); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 2): - value = cirrus_vga_read_gr(s, 0x13); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 3): - value = cirrus_vga_read_gr(s, 0x15); - break; - case (CIRRUS_MMIO_BLTWIDTH + 0): - value = cirrus_vga_read_gr(s, 0x20); - break; - case (CIRRUS_MMIO_BLTWIDTH + 1): - value = cirrus_vga_read_gr(s, 0x21); - break; - case (CIRRUS_MMIO_BLTHEIGHT + 0): - value = cirrus_vga_read_gr(s, 0x22); - break; - case (CIRRUS_MMIO_BLTHEIGHT + 1): - value = cirrus_vga_read_gr(s, 0x23); - break; - case (CIRRUS_MMIO_BLTDESTPITCH + 0): - value = cirrus_vga_read_gr(s, 0x24); - break; - case (CIRRUS_MMIO_BLTDESTPITCH + 1): - value = cirrus_vga_read_gr(s, 0x25); - break; - case (CIRRUS_MMIO_BLTSRCPITCH + 0): - value = cirrus_vga_read_gr(s, 0x26); - break; - case (CIRRUS_MMIO_BLTSRCPITCH + 1): - value = cirrus_vga_read_gr(s, 0x27); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 0): - value = cirrus_vga_read_gr(s, 0x28); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 1): - value = cirrus_vga_read_gr(s, 0x29); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 2): - value = cirrus_vga_read_gr(s, 0x2a); - break; - case (CIRRUS_MMIO_BLTSRCADDR + 0): - value = cirrus_vga_read_gr(s, 0x2c); - break; - case (CIRRUS_MMIO_BLTSRCADDR + 1): - value = cirrus_vga_read_gr(s, 0x2d); - break; - case (CIRRUS_MMIO_BLTSRCADDR + 2): - value = cirrus_vga_read_gr(s, 0x2e); - break; - case CIRRUS_MMIO_BLTWRITEMASK: - value = cirrus_vga_read_gr(s, 0x2f); - break; - case CIRRUS_MMIO_BLTMODE: - value = cirrus_vga_read_gr(s, 0x30); - break; - case CIRRUS_MMIO_BLTROP: - value = cirrus_vga_read_gr(s, 0x32); - break; - case CIRRUS_MMIO_BLTMODEEXT: - value = cirrus_vga_read_gr(s, 0x33); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0): - value = cirrus_vga_read_gr(s, 0x34); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1): - value = cirrus_vga_read_gr(s, 0x35); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0): - value = cirrus_vga_read_gr(s, 0x38); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1): - value = cirrus_vga_read_gr(s, 0x39); - break; - case CIRRUS_MMIO_BLTSTATUS: - value = cirrus_vga_read_gr(s, 0x31); - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: mmio read - address 0x%04x\n", address); -#endif - break; - } - - return (uint8_t) value; -} - -static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address, - uint8_t value) -{ - switch (address) { - case (CIRRUS_MMIO_BLTBGCOLOR + 0): - cirrus_vga_write_gr(s, 0x00, value); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 1): - cirrus_vga_write_gr(s, 0x10, value); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 2): - cirrus_vga_write_gr(s, 0x12, value); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 3): - cirrus_vga_write_gr(s, 0x14, value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 0): - cirrus_vga_write_gr(s, 0x01, value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 1): - cirrus_vga_write_gr(s, 0x11, value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 2): - cirrus_vga_write_gr(s, 0x13, value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 3): - cirrus_vga_write_gr(s, 0x15, value); - break; - case (CIRRUS_MMIO_BLTWIDTH + 0): - cirrus_vga_write_gr(s, 0x20, value); - break; - case (CIRRUS_MMIO_BLTWIDTH + 1): - cirrus_vga_write_gr(s, 0x21, value); - break; - case (CIRRUS_MMIO_BLTHEIGHT + 0): - cirrus_vga_write_gr(s, 0x22, value); - break; - case (CIRRUS_MMIO_BLTHEIGHT + 1): - cirrus_vga_write_gr(s, 0x23, value); - break; - case (CIRRUS_MMIO_BLTDESTPITCH + 0): - cirrus_vga_write_gr(s, 0x24, value); - break; - case (CIRRUS_MMIO_BLTDESTPITCH + 1): - cirrus_vga_write_gr(s, 0x25, value); - break; - case (CIRRUS_MMIO_BLTSRCPITCH + 0): - cirrus_vga_write_gr(s, 0x26, value); - break; - case (CIRRUS_MMIO_BLTSRCPITCH + 1): - cirrus_vga_write_gr(s, 0x27, value); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 0): - cirrus_vga_write_gr(s, 0x28, value); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 1): - cirrus_vga_write_gr(s, 0x29, value); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 2): - cirrus_vga_write_gr(s, 0x2a, value); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 3): - /* ignored */ - break; - case (CIRRUS_MMIO_BLTSRCADDR + 0): - cirrus_vga_write_gr(s, 0x2c, value); - break; - case (CIRRUS_MMIO_BLTSRCADDR + 1): - cirrus_vga_write_gr(s, 0x2d, value); - break; - case (CIRRUS_MMIO_BLTSRCADDR + 2): - cirrus_vga_write_gr(s, 0x2e, value); - break; - case CIRRUS_MMIO_BLTWRITEMASK: - cirrus_vga_write_gr(s, 0x2f, value); - break; - case CIRRUS_MMIO_BLTMODE: - cirrus_vga_write_gr(s, 0x30, value); - break; - case CIRRUS_MMIO_BLTROP: - cirrus_vga_write_gr(s, 0x32, value); - break; - case CIRRUS_MMIO_BLTMODEEXT: - cirrus_vga_write_gr(s, 0x33, value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0): - cirrus_vga_write_gr(s, 0x34, value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1): - cirrus_vga_write_gr(s, 0x35, value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0): - cirrus_vga_write_gr(s, 0x38, value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1): - cirrus_vga_write_gr(s, 0x39, value); - break; - case CIRRUS_MMIO_BLTSTATUS: - cirrus_vga_write_gr(s, 0x31, value); - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n", - address, value); -#endif - break; - } -} - -/*************************************** - * - * write mode 4/5 - * - ***************************************/ - -static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s, - unsigned mode, - unsigned offset, - uint32_t mem_value) -{ - int x; - unsigned val = mem_value; - uint8_t *dst; - - dst = s->vga.vram_ptr + (offset &= s->cirrus_addr_mask); - for (x = 0; x < 8; x++) { - if (val & 0x80) { - *dst = s->cirrus_shadow_gr1; - } else if (mode == 5) { - *dst = s->cirrus_shadow_gr0; - } - val <<= 1; - dst++; - } - memory_region_set_dirty(&s->vga.vram, offset, 8); -} - -static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s, - unsigned mode, - unsigned offset, - uint32_t mem_value) -{ - int x; - unsigned val = mem_value; - uint8_t *dst; - - dst = s->vga.vram_ptr + (offset &= s->cirrus_addr_mask); - for (x = 0; x < 8; x++) { - if (val & 0x80) { - *dst = s->cirrus_shadow_gr1; - *(dst + 1) = s->vga.gr[0x11]; - } else if (mode == 5) { - *dst = s->cirrus_shadow_gr0; - *(dst + 1) = s->vga.gr[0x10]; - } - val <<= 1; - dst += 2; - } - memory_region_set_dirty(&s->vga.vram, offset, 16); -} - -/*************************************** - * - * memory access between 0xa0000-0xbffff - * - ***************************************/ - -static uint64_t cirrus_vga_mem_read(void *opaque, - hwaddr addr, - uint32_t size) -{ - CirrusVGAState *s = opaque; - unsigned bank_index; - unsigned bank_offset; - uint32_t val; - - if ((s->vga.sr[0x07] & 0x01) == 0) { - return vga_mem_readb(&s->vga, addr); - } - - if (addr < 0x10000) { - /* XXX handle bitblt */ - /* video memory */ - bank_index = addr >> 15; - bank_offset = addr & 0x7fff; - if (bank_offset < s->cirrus_bank_limit[bank_index]) { - bank_offset += s->cirrus_bank_base[bank_index]; - if ((s->vga.gr[0x0B] & 0x14) == 0x14) { - bank_offset <<= 4; - } else if (s->vga.gr[0x0B] & 0x02) { - bank_offset <<= 3; - } - bank_offset &= s->cirrus_addr_mask; - val = *(s->vga.vram_ptr + bank_offset); - } else - val = 0xff; - } else if (addr >= 0x18000 && addr < 0x18100) { - /* memory-mapped I/O */ - val = 0xff; - if ((s->vga.sr[0x17] & 0x44) == 0x04) { - val = cirrus_mmio_blt_read(s, addr & 0xff); - } - } else { - val = 0xff; -#ifdef DEBUG_CIRRUS - printf("cirrus: mem_readb " TARGET_FMT_plx "\n", addr); -#endif - } - return val; -} - -static void cirrus_vga_mem_write(void *opaque, - hwaddr addr, - uint64_t mem_value, - uint32_t size) -{ - CirrusVGAState *s = opaque; - unsigned bank_index; - unsigned bank_offset; - unsigned mode; - - if ((s->vga.sr[0x07] & 0x01) == 0) { - vga_mem_writeb(&s->vga, addr, mem_value); - return; - } - - if (addr < 0x10000) { - if (s->cirrus_srcptr != s->cirrus_srcptr_end) { - /* bitblt */ - *s->cirrus_srcptr++ = (uint8_t) mem_value; - if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { - cirrus_bitblt_cputovideo_next(s); - } - } else { - /* video memory */ - bank_index = addr >> 15; - bank_offset = addr & 0x7fff; - if (bank_offset < s->cirrus_bank_limit[bank_index]) { - bank_offset += s->cirrus_bank_base[bank_index]; - if ((s->vga.gr[0x0B] & 0x14) == 0x14) { - bank_offset <<= 4; - } else if (s->vga.gr[0x0B] & 0x02) { - bank_offset <<= 3; - } - bank_offset &= s->cirrus_addr_mask; - mode = s->vga.gr[0x05] & 0x7; - if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) { - *(s->vga.vram_ptr + bank_offset) = mem_value; - memory_region_set_dirty(&s->vga.vram, bank_offset, - sizeof(mem_value)); - } else { - if ((s->vga.gr[0x0B] & 0x14) != 0x14) { - cirrus_mem_writeb_mode4and5_8bpp(s, mode, - bank_offset, - mem_value); - } else { - cirrus_mem_writeb_mode4and5_16bpp(s, mode, - bank_offset, - mem_value); - } - } - } - } - } else if (addr >= 0x18000 && addr < 0x18100) { - /* memory-mapped I/O */ - if ((s->vga.sr[0x17] & 0x44) == 0x04) { - cirrus_mmio_blt_write(s, addr & 0xff, mem_value); - } - } else { -#ifdef DEBUG_CIRRUS - printf("cirrus: mem_writeb " TARGET_FMT_plx " value 0x%02" PRIu64 "\n", addr, - mem_value); -#endif - } -} - -static const MemoryRegionOps cirrus_vga_mem_ops = { - .read = cirrus_vga_mem_read, - .write = cirrus_vga_mem_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -/*************************************** - * - * hardware cursor - * - ***************************************/ - -static inline void invalidate_cursor1(CirrusVGAState *s) -{ - if (s->last_hw_cursor_size) { - vga_invalidate_scanlines(&s->vga, - s->last_hw_cursor_y + s->last_hw_cursor_y_start, - s->last_hw_cursor_y + s->last_hw_cursor_y_end); - } -} - -static inline void cirrus_cursor_compute_yrange(CirrusVGAState *s) -{ - const uint8_t *src; - uint32_t content; - int y, y_min, y_max; - - src = s->vga.vram_ptr + s->real_vram_size - 16 * 1024; - if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) { - src += (s->vga.sr[0x13] & 0x3c) * 256; - y_min = 64; - y_max = -1; - for(y = 0; y < 64; y++) { - content = ((uint32_t *)src)[0] | - ((uint32_t *)src)[1] | - ((uint32_t *)src)[2] | - ((uint32_t *)src)[3]; - if (content) { - if (y < y_min) - y_min = y; - if (y > y_max) - y_max = y; - } - src += 16; - } - } else { - src += (s->vga.sr[0x13] & 0x3f) * 256; - y_min = 32; - y_max = -1; - for(y = 0; y < 32; y++) { - content = ((uint32_t *)src)[0] | - ((uint32_t *)(src + 128))[0]; - if (content) { - if (y < y_min) - y_min = y; - if (y > y_max) - y_max = y; - } - src += 4; - } - } - if (y_min > y_max) { - s->last_hw_cursor_y_start = 0; - s->last_hw_cursor_y_end = 0; - } else { - s->last_hw_cursor_y_start = y_min; - s->last_hw_cursor_y_end = y_max + 1; - } -} - -/* NOTE: we do not currently handle the cursor bitmap change, so we - update the cursor only if it moves. */ -static void cirrus_cursor_invalidate(VGACommonState *s1) -{ - CirrusVGAState *s = container_of(s1, CirrusVGAState, vga); - int size; - - if (!(s->vga.sr[0x12] & CIRRUS_CURSOR_SHOW)) { - size = 0; - } else { - if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) - size = 64; - else - size = 32; - } - /* invalidate last cursor and new cursor if any change */ - if (s->last_hw_cursor_size != size || - s->last_hw_cursor_x != s->vga.hw_cursor_x || - s->last_hw_cursor_y != s->vga.hw_cursor_y) { - - invalidate_cursor1(s); - - s->last_hw_cursor_size = size; - s->last_hw_cursor_x = s->vga.hw_cursor_x; - s->last_hw_cursor_y = s->vga.hw_cursor_y; - /* compute the real cursor min and max y */ - cirrus_cursor_compute_yrange(s); - invalidate_cursor1(s); - } -} - -static void vga_draw_cursor_line(uint8_t *d1, - const uint8_t *src1, - int poffset, int w, - unsigned int color0, - unsigned int color1, - unsigned int color_xor) -{ - const uint8_t *plane0, *plane1; - int x, b0, b1; - uint8_t *d; - - d = d1; - plane0 = src1; - plane1 = src1 + poffset; - for (x = 0; x < w; x++) { - b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1; - b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1; - switch (b0 | (b1 << 1)) { - case 0: - break; - case 1: - ((uint32_t *)d)[0] ^= color_xor; - break; - case 2: - ((uint32_t *)d)[0] = color0; - break; - case 3: - ((uint32_t *)d)[0] = color1; - break; - } - d += 4; - } -} - -static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y) -{ - CirrusVGAState *s = container_of(s1, CirrusVGAState, vga); - int w, h, x1, x2, poffset; - unsigned int color0, color1; - const uint8_t *palette, *src; - uint32_t content; - - if (!(s->vga.sr[0x12] & CIRRUS_CURSOR_SHOW)) - return; - /* fast test to see if the cursor intersects with the scan line */ - if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) { - h = 64; - } else { - h = 32; - } - if (scr_y < s->vga.hw_cursor_y || - scr_y >= (s->vga.hw_cursor_y + h)) { - return; - } - - src = s->vga.vram_ptr + s->real_vram_size - 16 * 1024; - if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) { - src += (s->vga.sr[0x13] & 0x3c) * 256; - src += (scr_y - s->vga.hw_cursor_y) * 16; - poffset = 8; - content = ((uint32_t *)src)[0] | - ((uint32_t *)src)[1] | - ((uint32_t *)src)[2] | - ((uint32_t *)src)[3]; - } else { - src += (s->vga.sr[0x13] & 0x3f) * 256; - src += (scr_y - s->vga.hw_cursor_y) * 4; - - - poffset = 128; - content = ((uint32_t *)src)[0] | - ((uint32_t *)(src + 128))[0]; - } - /* if nothing to draw, no need to continue */ - if (!content) - return; - w = h; - - x1 = s->vga.hw_cursor_x; - if (x1 >= s->vga.last_scr_width) - return; - x2 = s->vga.hw_cursor_x + w; - if (x2 > s->vga.last_scr_width) - x2 = s->vga.last_scr_width; - w = x2 - x1; - palette = s->cirrus_hidden_palette; - color0 = rgb_to_pixel32(c6_to_8(palette[0x0 * 3]), - c6_to_8(palette[0x0 * 3 + 1]), - c6_to_8(palette[0x0 * 3 + 2])); - color1 = rgb_to_pixel32(c6_to_8(palette[0xf * 3]), - c6_to_8(palette[0xf * 3 + 1]), - c6_to_8(palette[0xf * 3 + 2])); - d1 += x1 * 4; - vga_draw_cursor_line(d1, src, poffset, w, color0, color1, 0xffffff); -} - -/*************************************** - * - * LFB memory access - * - ***************************************/ - -static uint64_t cirrus_linear_read(void *opaque, hwaddr addr, - unsigned size) -{ - CirrusVGAState *s = opaque; - uint32_t ret; - - addr &= s->cirrus_addr_mask; - - if (((s->vga.sr[0x17] & 0x44) == 0x44) && - ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) { - /* memory-mapped I/O */ - ret = cirrus_mmio_blt_read(s, addr & 0xff); - } else if (0) { - /* XXX handle bitblt */ - ret = 0xff; - } else { - /* video memory */ - if ((s->vga.gr[0x0B] & 0x14) == 0x14) { - addr <<= 4; - } else if (s->vga.gr[0x0B] & 0x02) { - addr <<= 3; - } - addr &= s->cirrus_addr_mask; - ret = *(s->vga.vram_ptr + addr); - } - - return ret; -} - -static void cirrus_linear_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - CirrusVGAState *s = opaque; - unsigned mode; - - addr &= s->cirrus_addr_mask; - - if (((s->vga.sr[0x17] & 0x44) == 0x44) && - ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) { - /* memory-mapped I/O */ - cirrus_mmio_blt_write(s, addr & 0xff, val); - } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { - /* bitblt */ - *s->cirrus_srcptr++ = (uint8_t) val; - if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { - cirrus_bitblt_cputovideo_next(s); - } - } else { - /* video memory */ - if ((s->vga.gr[0x0B] & 0x14) == 0x14) { - addr <<= 4; - } else if (s->vga.gr[0x0B] & 0x02) { - addr <<= 3; - } - addr &= s->cirrus_addr_mask; - - mode = s->vga.gr[0x05] & 0x7; - if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) { - *(s->vga.vram_ptr + addr) = (uint8_t) val; - memory_region_set_dirty(&s->vga.vram, addr, 1); - } else { - if ((s->vga.gr[0x0B] & 0x14) != 0x14) { - cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val); - } else { - cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val); - } - } - } -} - -/*************************************** - * - * system to screen memory access - * - ***************************************/ - - -static uint64_t cirrus_linear_bitblt_read(void *opaque, - hwaddr addr, - unsigned size) -{ - CirrusVGAState *s = opaque; - uint32_t ret; - - /* XXX handle bitblt */ - (void)s; - ret = 0xff; - return ret; -} - -static void cirrus_linear_bitblt_write(void *opaque, - hwaddr addr, - uint64_t val, - unsigned size) -{ - CirrusVGAState *s = opaque; - - if (s->cirrus_srcptr != s->cirrus_srcptr_end) { - /* bitblt */ - *s->cirrus_srcptr++ = (uint8_t) val; - if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { - cirrus_bitblt_cputovideo_next(s); - } - } -} - -static const MemoryRegionOps cirrus_linear_bitblt_io_ops = { - .read = cirrus_linear_bitblt_read, - .write = cirrus_linear_bitblt_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void map_linear_vram_bank(CirrusVGAState *s, unsigned bank) -{ - MemoryRegion *mr = &s->cirrus_bank[bank]; - bool enabled = !(s->cirrus_srcptr != s->cirrus_srcptr_end) - && !((s->vga.sr[0x07] & 0x01) == 0) - && !((s->vga.gr[0x0B] & 0x14) == 0x14) - && !(s->vga.gr[0x0B] & 0x02); - - memory_region_set_enabled(mr, enabled); - memory_region_set_alias_offset(mr, s->cirrus_bank_base[bank]); -} - -static void map_linear_vram(CirrusVGAState *s) -{ - if (s->bustype == CIRRUS_BUSTYPE_PCI && !s->linear_vram) { - s->linear_vram = true; - memory_region_add_subregion_overlap(&s->pci_bar, 0, &s->vga.vram, 1); - } - map_linear_vram_bank(s, 0); - map_linear_vram_bank(s, 1); -} - -static void unmap_linear_vram(CirrusVGAState *s) -{ - if (s->bustype == CIRRUS_BUSTYPE_PCI && s->linear_vram) { - s->linear_vram = false; - memory_region_del_subregion(&s->pci_bar, &s->vga.vram); - } - memory_region_set_enabled(&s->cirrus_bank[0], false); - memory_region_set_enabled(&s->cirrus_bank[1], false); -} - -/* Compute the memory access functions */ -static void cirrus_update_memory_access(CirrusVGAState *s) -{ - unsigned mode; - - memory_region_transaction_begin(); - if ((s->vga.sr[0x17] & 0x44) == 0x44) { - goto generic_io; - } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { - goto generic_io; - } else { - if ((s->vga.gr[0x0B] & 0x14) == 0x14) { - goto generic_io; - } else if (s->vga.gr[0x0B] & 0x02) { - goto generic_io; - } - - mode = s->vga.gr[0x05] & 0x7; - if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) { - map_linear_vram(s); - } else { - generic_io: - unmap_linear_vram(s); - } - } - memory_region_transaction_commit(); -} - - -/* I/O ports */ - -static uint64_t cirrus_vga_ioport_read(void *opaque, hwaddr addr, - unsigned size) -{ - CirrusVGAState *c = opaque; - VGACommonState *s = &c->vga; - int val, index; - - addr += 0x3b0; - - if (vga_ioport_invalid(s, addr)) { - val = 0xff; - } else { - switch (addr) { - case 0x3c0: - if (s->ar_flip_flop == 0) { - val = s->ar_index; - } else { - val = 0; - } - break; - case 0x3c1: - index = s->ar_index & 0x1f; - if (index < 21) - val = s->ar[index]; - else - val = 0; - break; - case 0x3c2: - val = s->st00; - break; - case 0x3c4: - val = s->sr_index; - break; - case 0x3c5: - val = cirrus_vga_read_sr(c); - break; -#ifdef DEBUG_VGA_REG - printf("vga: read SR%x = 0x%02x\n", s->sr_index, val); -#endif - break; - case 0x3c6: - val = cirrus_read_hidden_dac(c); - break; - case 0x3c7: - val = s->dac_state; - break; - case 0x3c8: - val = s->dac_write_index; - c->cirrus_hidden_dac_lockindex = 0; - break; - case 0x3c9: - val = cirrus_vga_read_palette(c); - break; - case 0x3ca: - val = s->fcr; - break; - case 0x3cc: - val = s->msr; - break; - case 0x3ce: - val = s->gr_index; - break; - case 0x3cf: - val = cirrus_vga_read_gr(c, s->gr_index); -#ifdef DEBUG_VGA_REG - printf("vga: read GR%x = 0x%02x\n", s->gr_index, val); -#endif - break; - case 0x3b4: - case 0x3d4: - val = s->cr_index; - break; - case 0x3b5: - case 0x3d5: - val = cirrus_vga_read_cr(c, s->cr_index); -#ifdef DEBUG_VGA_REG - printf("vga: read CR%x = 0x%02x\n", s->cr_index, val); -#endif - break; - case 0x3ba: - case 0x3da: - /* just toggle to fool polling */ - val = s->st01 = s->retrace(s); - s->ar_flip_flop = 0; - break; - default: - val = 0x00; - break; - } - } -#if defined(DEBUG_VGA) - printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val); -#endif - return val; -} - -static void cirrus_vga_ioport_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - CirrusVGAState *c = opaque; - VGACommonState *s = &c->vga; - int index; - - addr += 0x3b0; - - /* check port range access depending on color/monochrome mode */ - if (vga_ioport_invalid(s, addr)) { - return; - } -#ifdef DEBUG_VGA - printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val); -#endif - - switch (addr) { - case 0x3c0: - if (s->ar_flip_flop == 0) { - val &= 0x3f; - s->ar_index = val; - } else { - index = s->ar_index & 0x1f; - switch (index) { - case 0x00 ... 0x0f: - s->ar[index] = val & 0x3f; - break; - case 0x10: - s->ar[index] = val & ~0x10; - break; - case 0x11: - s->ar[index] = val; - break; - case 0x12: - s->ar[index] = val & ~0xc0; - break; - case 0x13: - s->ar[index] = val & ~0xf0; - break; - case 0x14: - s->ar[index] = val & ~0xf0; - break; - default: - break; - } - } - s->ar_flip_flop ^= 1; - break; - case 0x3c2: - s->msr = val & ~0x10; - s->update_retrace_info(s); - break; - case 0x3c4: - s->sr_index = val; - break; - case 0x3c5: -#ifdef DEBUG_VGA_REG - printf("vga: write SR%x = 0x%02" PRIu64 "\n", s->sr_index, val); -#endif - cirrus_vga_write_sr(c, val); - break; - case 0x3c6: - cirrus_write_hidden_dac(c, val); - break; - case 0x3c7: - s->dac_read_index = val; - s->dac_sub_index = 0; - s->dac_state = 3; - break; - case 0x3c8: - s->dac_write_index = val; - s->dac_sub_index = 0; - s->dac_state = 0; - break; - case 0x3c9: - cirrus_vga_write_palette(c, val); - break; - case 0x3ce: - s->gr_index = val; - break; - case 0x3cf: -#ifdef DEBUG_VGA_REG - printf("vga: write GR%x = 0x%02" PRIu64 "\n", s->gr_index, val); -#endif - cirrus_vga_write_gr(c, s->gr_index, val); - break; - case 0x3b4: - case 0x3d4: - s->cr_index = val; - break; - case 0x3b5: - case 0x3d5: -#ifdef DEBUG_VGA_REG - printf("vga: write CR%x = 0x%02"PRIu64"\n", s->cr_index, val); -#endif - cirrus_vga_write_cr(c, val); - break; - case 0x3ba: - case 0x3da: - s->fcr = val & 0x10; - break; - } -} - -/*************************************** - * - * memory-mapped I/O access - * - ***************************************/ - -static uint64_t cirrus_mmio_read(void *opaque, hwaddr addr, - unsigned size) -{ - CirrusVGAState *s = opaque; - - if (addr >= 0x100) { - return cirrus_mmio_blt_read(s, addr - 0x100); - } else { - return cirrus_vga_ioport_read(s, addr + 0x10, size); - } -} - -static void cirrus_mmio_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - CirrusVGAState *s = opaque; - - if (addr >= 0x100) { - cirrus_mmio_blt_write(s, addr - 0x100, val); - } else { - cirrus_vga_ioport_write(s, addr + 0x10, val, size); - } -} - -static const MemoryRegionOps cirrus_mmio_io_ops = { - .read = cirrus_mmio_read, - .write = cirrus_mmio_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -/* load/save state */ - -static int cirrus_post_load(void *opaque, int version_id) -{ - CirrusVGAState *s = opaque; - - s->vga.gr[0x00] = s->cirrus_shadow_gr0 & 0x0f; - s->vga.gr[0x01] = s->cirrus_shadow_gr1 & 0x0f; - - cirrus_update_memory_access(s); - /* force refresh */ - s->vga.graphic_mode = -1; - cirrus_update_bank_ptr(s, 0); - cirrus_update_bank_ptr(s, 1); - return 0; -} - -static const VMStateDescription vmstate_cirrus_vga = { - .name = "cirrus_vga", - .version_id = 2, - .minimum_version_id = 1, - .post_load = cirrus_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32(vga.latch, CirrusVGAState), - VMSTATE_UINT8(vga.sr_index, CirrusVGAState), - VMSTATE_BUFFER(vga.sr, CirrusVGAState), - VMSTATE_UINT8(vga.gr_index, CirrusVGAState), - VMSTATE_UINT8(cirrus_shadow_gr0, CirrusVGAState), - VMSTATE_UINT8(cirrus_shadow_gr1, CirrusVGAState), - VMSTATE_BUFFER_START_MIDDLE(vga.gr, CirrusVGAState, 2), - VMSTATE_UINT8(vga.ar_index, CirrusVGAState), - VMSTATE_BUFFER(vga.ar, CirrusVGAState), - VMSTATE_INT32(vga.ar_flip_flop, CirrusVGAState), - VMSTATE_UINT8(vga.cr_index, CirrusVGAState), - VMSTATE_BUFFER(vga.cr, CirrusVGAState), - VMSTATE_UINT8(vga.msr, CirrusVGAState), - VMSTATE_UINT8(vga.fcr, CirrusVGAState), - VMSTATE_UINT8(vga.st00, CirrusVGAState), - VMSTATE_UINT8(vga.st01, CirrusVGAState), - VMSTATE_UINT8(vga.dac_state, CirrusVGAState), - VMSTATE_UINT8(vga.dac_sub_index, CirrusVGAState), - VMSTATE_UINT8(vga.dac_read_index, CirrusVGAState), - VMSTATE_UINT8(vga.dac_write_index, CirrusVGAState), - VMSTATE_BUFFER(vga.dac_cache, CirrusVGAState), - VMSTATE_BUFFER(vga.palette, CirrusVGAState), - VMSTATE_INT32(vga.bank_offset, CirrusVGAState), - VMSTATE_UINT8(cirrus_hidden_dac_lockindex, CirrusVGAState), - VMSTATE_UINT8(cirrus_hidden_dac_data, CirrusVGAState), - VMSTATE_UINT32(vga.hw_cursor_x, CirrusVGAState), - VMSTATE_UINT32(vga.hw_cursor_y, CirrusVGAState), - /* XXX: we do not save the bitblt state - we assume we do not save - the state when the blitter is active */ - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_pci_cirrus_vga = { - .name = "cirrus_vga", - .version_id = 2, - .minimum_version_id = 2, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(dev, PCICirrusVGAState), - VMSTATE_STRUCT(cirrus_vga, PCICirrusVGAState, 0, - vmstate_cirrus_vga, CirrusVGAState), - VMSTATE_END_OF_LIST() - } -}; - -/*************************************** - * - * initialize - * - ***************************************/ - -static void cirrus_reset(void *opaque) -{ - CirrusVGAState *s = opaque; - - vga_common_reset(&s->vga); - unmap_linear_vram(s); - s->vga.sr[0x06] = 0x0f; - if (s->device_id == CIRRUS_ID_CLGD5446) { - /* 4MB 64 bit memory config, always PCI */ - s->vga.sr[0x1F] = 0x2d; // MemClock - s->vga.gr[0x18] = 0x0f; // fastest memory configuration - s->vga.sr[0x0f] = 0x98; - s->vga.sr[0x17] = 0x20; - s->vga.sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */ - } else { - s->vga.sr[0x1F] = 0x22; // MemClock - s->vga.sr[0x0F] = CIRRUS_MEMSIZE_2M; - s->vga.sr[0x17] = s->bustype; - s->vga.sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ - } - s->vga.cr[0x27] = s->device_id; - - s->cirrus_hidden_dac_lockindex = 5; - s->cirrus_hidden_dac_data = 0; -} - -static const MemoryRegionOps cirrus_linear_io_ops = { - .read = cirrus_linear_read, - .write = cirrus_linear_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static const MemoryRegionOps cirrus_vga_io_ops = { - .read = cirrus_vga_ioport_read, - .write = cirrus_vga_ioport_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void cirrus_init_common(CirrusVGAState *s, Object *owner, - int device_id, int is_pci, - MemoryRegion *system_memory, - MemoryRegion *system_io) -{ - int i; - static int inited; - - if (!inited) { - inited = 1; - for(i = 0;i < 256; i++) - rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */ - rop_to_index[CIRRUS_ROP_0] = 0; - rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1; - rop_to_index[CIRRUS_ROP_NOP] = 2; - rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3; - rop_to_index[CIRRUS_ROP_NOTDST] = 4; - rop_to_index[CIRRUS_ROP_SRC] = 5; - rop_to_index[CIRRUS_ROP_1] = 6; - rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7; - rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8; - rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9; - rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10; - rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11; - rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12; - rop_to_index[CIRRUS_ROP_NOTSRC] = 13; - rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14; - rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15; - s->device_id = device_id; - if (is_pci) - s->bustype = CIRRUS_BUSTYPE_PCI; - else - s->bustype = CIRRUS_BUSTYPE_ISA; - } - - /* Register ioport 0x3b0 - 0x3df */ - memory_region_init_io(&s->cirrus_vga_io, owner, &cirrus_vga_io_ops, s, - "cirrus-io", 0x30); - memory_region_set_flush_coalesced(&s->cirrus_vga_io); - memory_region_add_subregion(system_io, 0x3b0, &s->cirrus_vga_io); - - memory_region_init(&s->low_mem_container, owner, - "cirrus-lowmem-container", - 0x20000); - - memory_region_init_io(&s->low_mem, owner, &cirrus_vga_mem_ops, s, - "cirrus-low-memory", 0x20000); - memory_region_add_subregion(&s->low_mem_container, 0, &s->low_mem); - for (i = 0; i < 2; ++i) { - static const char *names[] = { "vga.bank0", "vga.bank1" }; - MemoryRegion *bank = &s->cirrus_bank[i]; - memory_region_init_alias(bank, owner, names[i], &s->vga.vram, - 0, 0x8000); - memory_region_set_enabled(bank, false); - memory_region_add_subregion_overlap(&s->low_mem_container, i * 0x8000, - bank, 1); - } - memory_region_add_subregion_overlap(system_memory, - 0x000a0000, - &s->low_mem_container, - 1); - memory_region_set_coalescing(&s->low_mem); - - /* I/O handler for LFB */ - memory_region_init_io(&s->cirrus_linear_io, owner, &cirrus_linear_io_ops, s, - "cirrus-linear-io", s->vga.vram_size_mb - * 1024 * 1024); - memory_region_set_flush_coalesced(&s->cirrus_linear_io); - - /* I/O handler for LFB */ - memory_region_init_io(&s->cirrus_linear_bitblt_io, owner, - &cirrus_linear_bitblt_io_ops, - s, - "cirrus-bitblt-mmio", - 0x400000); - memory_region_set_flush_coalesced(&s->cirrus_linear_bitblt_io); - - /* I/O handler for memory-mapped I/O */ - memory_region_init_io(&s->cirrus_mmio_io, owner, &cirrus_mmio_io_ops, s, - "cirrus-mmio", CIRRUS_PNPMMIO_SIZE); - memory_region_set_flush_coalesced(&s->cirrus_mmio_io); - - s->real_vram_size = - (s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024; - - /* XXX: s->vga.vram_size must be a power of two */ - s->cirrus_addr_mask = s->real_vram_size - 1; - s->linear_mmio_mask = s->real_vram_size - 256; - - s->vga.get_bpp = cirrus_get_bpp; - s->vga.get_offsets = cirrus_get_offsets; - s->vga.get_resolution = cirrus_get_resolution; - s->vga.cursor_invalidate = cirrus_cursor_invalidate; - s->vga.cursor_draw_line = cirrus_cursor_draw_line; - - qemu_register_reset(cirrus_reset, s); -} - -/*************************************** - * - * ISA bus support - * - ***************************************/ - -static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp) -{ - ISADevice *isadev = ISA_DEVICE(dev); - ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev); - VGACommonState *s = &d->cirrus_vga.vga; - - /* follow real hardware, cirrus card emulated has 4 MB video memory. - Also accept 8 MB/16 MB for backward compatibility. */ - if (s->vram_size_mb != 4 && s->vram_size_mb != 8 && - s->vram_size_mb != 16) { - error_setg(errp, "Invalid cirrus_vga ram size '%u'", - s->vram_size_mb); - return; - } - vga_common_init(s, OBJECT(dev), true); - cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0, - isa_address_space(isadev), - isa_address_space_io(isadev)); - s->con = graphic_console_init(dev, 0, s->hw_ops, s); - rom_add_vga(VGABIOS_CIRRUS_FILENAME); - /* XXX ISA-LFB support */ - /* FIXME not qdev yet */ -} - -static Property isa_cirrus_vga_properties[] = { - DEFINE_PROP_UINT32("vgamem_mb", struct ISACirrusVGAState, - cirrus_vga.vga.vram_size_mb, 8), - DEFINE_PROP_END_OF_LIST(), -}; - -static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->vmsd = &vmstate_cirrus_vga; - dc->realize = isa_cirrus_vga_realizefn; - dc->props = isa_cirrus_vga_properties; - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); -} - -static const TypeInfo isa_cirrus_vga_info = { - .name = TYPE_ISA_CIRRUS_VGA, - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(ISACirrusVGAState), - .class_init = isa_cirrus_vga_class_init, -}; - -/*************************************** - * - * PCI bus support - * - ***************************************/ - -static void pci_cirrus_vga_realize(PCIDevice *dev, Error **errp) -{ - PCICirrusVGAState *d = PCI_CIRRUS_VGA(dev); - CirrusVGAState *s = &d->cirrus_vga; - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); - int16_t device_id = pc->device_id; - - /* follow real hardware, cirrus card emulated has 4 MB video memory. - Also accept 8 MB/16 MB for backward compatibility. */ - if (s->vga.vram_size_mb != 4 && s->vga.vram_size_mb != 8 && - s->vga.vram_size_mb != 16) { - error_setg(errp, "Invalid cirrus_vga ram size '%u'", - s->vga.vram_size_mb); - return; - } - /* setup VGA */ - vga_common_init(&s->vga, OBJECT(dev), true); - cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev), - pci_address_space_io(dev)); - s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga); - - /* setup PCI */ - - memory_region_init(&s->pci_bar, OBJECT(dev), "cirrus-pci-bar0", 0x2000000); - - /* XXX: add byte swapping apertures */ - memory_region_add_subregion(&s->pci_bar, 0, &s->cirrus_linear_io); - memory_region_add_subregion(&s->pci_bar, 0x1000000, - &s->cirrus_linear_bitblt_io); - - /* setup memory space */ - /* memory #0 LFB */ - /* memory #1 memory-mapped I/O */ - /* XXX: s->vga.vram_size must be a power of two */ - pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->pci_bar); - if (device_id == CIRRUS_ID_CLGD5446) { - pci_register_bar(&d->dev, 1, 0, &s->cirrus_mmio_io); - } -} - -static Property pci_vga_cirrus_properties[] = { - DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState, - cirrus_vga.vga.vram_size_mb, 8), - DEFINE_PROP_END_OF_LIST(), -}; - -static void cirrus_vga_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = pci_cirrus_vga_realize; - k->romfile = VGABIOS_CIRRUS_FILENAME; - k->vendor_id = PCI_VENDOR_ID_CIRRUS; - k->device_id = CIRRUS_ID_CLGD5446; - k->class_id = PCI_CLASS_DISPLAY_VGA; - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); - dc->desc = "Cirrus CLGD 54xx VGA"; - dc->vmsd = &vmstate_pci_cirrus_vga; - dc->props = pci_vga_cirrus_properties; - dc->hotpluggable = false; -} - -static const TypeInfo cirrus_vga_info = { - .name = TYPE_PCI_CIRRUS_VGA, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCICirrusVGAState), - .class_init = cirrus_vga_class_init, -}; - -static void cirrus_vga_register_types(void) -{ - type_register_static(&isa_cirrus_vga_info); - type_register_static(&cirrus_vga_info); -} - -type_init(cirrus_vga_register_types) diff --git a/qemu/hw/display/cirrus_vga_rop.h b/qemu/hw/display/cirrus_vga_rop.h deleted file mode 100644 index 0925a009f..000000000 --- a/qemu/hw/display/cirrus_vga_rop.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * QEMU Cirrus CLGD 54xx VGA Emulator. - * - * Copyright (c) 2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -static inline void glue(rop_8_,ROP_NAME)(uint8_t *dst, uint8_t src) -{ - *dst = ROP_FN(*dst, src); -} - -static inline void glue(rop_16_,ROP_NAME)(uint16_t *dst, uint16_t src) -{ - *dst = ROP_FN(*dst, src); -} - -static inline void glue(rop_32_,ROP_NAME)(uint32_t *dst, uint32_t src) -{ - *dst = ROP_FN(*dst, src); -} - -#define ROP_OP(d, s) glue(rop_8_,ROP_NAME)(d, s) -#define ROP_OP_16(d, s) glue(rop_16_,ROP_NAME)(d, s) -#define ROP_OP_32(d, s) glue(rop_32_,ROP_NAME)(d, s) -#undef ROP_FN - -static void -glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - dstpitch -= bltwidth; - srcpitch -= bltwidth; - - if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) { - return; - } - - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x++) { - ROP_OP(dst, *src); - dst++; - src++; - } - dst += dstpitch; - src += srcpitch; - } -} - -static void -glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - dstpitch += bltwidth; - srcpitch += bltwidth; - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x++) { - ROP_OP(dst, *src); - dst--; - src--; - } - dst += dstpitch; - src += srcpitch; - } -} - -static void -glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - uint8_t p; - dstpitch -= bltwidth; - srcpitch -= bltwidth; - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x++) { - p = *dst; - ROP_OP(&p, *src); - if (p != s->vga.gr[0x34]) *dst = p; - dst++; - src++; - } - dst += dstpitch; - src += srcpitch; - } -} - -static void -glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - uint8_t p; - dstpitch += bltwidth; - srcpitch += bltwidth; - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x++) { - p = *dst; - ROP_OP(&p, *src); - if (p != s->vga.gr[0x34]) *dst = p; - dst--; - src--; - } - dst += dstpitch; - src += srcpitch; - } -} - -static void -glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - uint8_t p1, p2; - dstpitch -= bltwidth; - srcpitch -= bltwidth; - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x+=2) { - p1 = *dst; - p2 = *(dst+1); - ROP_OP(&p1, *src); - ROP_OP(&p2, *(src + 1)); - if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { - *dst = p1; - *(dst+1) = p2; - } - dst+=2; - src+=2; - } - dst += dstpitch; - src += srcpitch; - } -} - -static void -glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - uint8_t p1, p2; - dstpitch += bltwidth; - srcpitch += bltwidth; - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x+=2) { - p1 = *(dst-1); - p2 = *dst; - ROP_OP(&p1, *(src - 1)); - ROP_OP(&p2, *src); - if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { - *(dst-1) = p1; - *dst = p2; - } - dst-=2; - src-=2; - } - dst += dstpitch; - src += srcpitch; - } -} - -#define DEPTH 8 -#include "cirrus_vga_rop2.h" - -#define DEPTH 16 -#include "cirrus_vga_rop2.h" - -#define DEPTH 24 -#include "cirrus_vga_rop2.h" - -#define DEPTH 32 -#include "cirrus_vga_rop2.h" - -#undef ROP_NAME -#undef ROP_OP -#undef ROP_OP_16 -#undef ROP_OP_32 diff --git a/qemu/hw/display/cirrus_vga_rop2.h b/qemu/hw/display/cirrus_vga_rop2.h deleted file mode 100644 index d28bcc6f2..000000000 --- a/qemu/hw/display/cirrus_vga_rop2.h +++ /dev/null @@ -1,281 +0,0 @@ -/* - * QEMU Cirrus CLGD 54xx VGA Emulator. - * - * Copyright (c) 2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if DEPTH == 8 -#define PUTPIXEL() ROP_OP(&d[0], col) -#elif DEPTH == 16 -#define PUTPIXEL() ROP_OP_16((uint16_t *)&d[0], col) -#elif DEPTH == 24 -#define PUTPIXEL() ROP_OP(&d[0], col); \ - ROP_OP(&d[1], (col >> 8)); \ - ROP_OP(&d[2], (col >> 16)) -#elif DEPTH == 32 -#define PUTPIXEL() ROP_OP_32(((uint32_t *)&d[0]), col) -#else -#error unsupported DEPTH -#endif - -static void -glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight) -{ - uint8_t *d; - int x, y, pattern_y, pattern_pitch, pattern_x; - unsigned int col; - const uint8_t *src1; -#if DEPTH == 24 - int skipleft = s->vga.gr[0x2f] & 0x1f; -#else - int skipleft = (s->vga.gr[0x2f] & 0x07) * (DEPTH / 8); -#endif - -#if DEPTH == 8 - pattern_pitch = 8; -#elif DEPTH == 16 - pattern_pitch = 16; -#else - pattern_pitch = 32; -#endif - pattern_y = s->cirrus_blt_srcaddr & 7; - for(y = 0; y < bltheight; y++) { - pattern_x = skipleft; - d = dst + skipleft; - src1 = src + pattern_y * pattern_pitch; - for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { -#if DEPTH == 8 - col = src1[pattern_x]; - pattern_x = (pattern_x + 1) & 7; -#elif DEPTH == 16 - col = ((uint16_t *)(src1 + pattern_x))[0]; - pattern_x = (pattern_x + 2) & 15; -#elif DEPTH == 24 - { - const uint8_t *src2 = src1 + pattern_x * 3; - col = src2[0] | (src2[1] << 8) | (src2[2] << 16); - pattern_x = (pattern_x + 1) & 7; - } -#else - col = ((uint32_t *)(src1 + pattern_x))[0]; - pattern_x = (pattern_x + 4) & 31; -#endif - PUTPIXEL(); - d += (DEPTH / 8); - } - pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; - } -} - -/* NOTE: srcpitch is ignored */ -static void -glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight) -{ - uint8_t *d; - int x, y; - unsigned bits, bits_xor; - unsigned int col; - unsigned bitmask; - unsigned index; -#if DEPTH == 24 - int dstskipleft = s->vga.gr[0x2f] & 0x1f; - int srcskipleft = dstskipleft / 3; -#else - int srcskipleft = s->vga.gr[0x2f] & 0x07; - int dstskipleft = srcskipleft * (DEPTH / 8); -#endif - - if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { - bits_xor = 0xff; - col = s->cirrus_blt_bgcol; - } else { - bits_xor = 0x00; - col = s->cirrus_blt_fgcol; - } - - for(y = 0; y < bltheight; y++) { - bitmask = 0x80 >> srcskipleft; - bits = *src++ ^ bits_xor; - d = dst + dstskipleft; - for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { - if ((bitmask & 0xff) == 0) { - bitmask = 0x80; - bits = *src++ ^ bits_xor; - } - index = (bits & bitmask); - if (index) { - PUTPIXEL(); - } - d += (DEPTH / 8); - bitmask >>= 1; - } - dst += dstpitch; - } -} - -static void -glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight) -{ - uint32_t colors[2]; - uint8_t *d; - int x, y; - unsigned bits; - unsigned int col; - unsigned bitmask; - int srcskipleft = s->vga.gr[0x2f] & 0x07; - int dstskipleft = srcskipleft * (DEPTH / 8); - - colors[0] = s->cirrus_blt_bgcol; - colors[1] = s->cirrus_blt_fgcol; - for(y = 0; y < bltheight; y++) { - bitmask = 0x80 >> srcskipleft; - bits = *src++; - d = dst + dstskipleft; - for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { - if ((bitmask & 0xff) == 0) { - bitmask = 0x80; - bits = *src++; - } - col = colors[!!(bits & bitmask)]; - PUTPIXEL(); - d += (DEPTH / 8); - bitmask >>= 1; - } - dst += dstpitch; - } -} - -static void -glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight) -{ - uint8_t *d; - int x, y, bitpos, pattern_y; - unsigned int bits, bits_xor; - unsigned int col; -#if DEPTH == 24 - int dstskipleft = s->vga.gr[0x2f] & 0x1f; - int srcskipleft = dstskipleft / 3; -#else - int srcskipleft = s->vga.gr[0x2f] & 0x07; - int dstskipleft = srcskipleft * (DEPTH / 8); -#endif - - if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { - bits_xor = 0xff; - col = s->cirrus_blt_bgcol; - } else { - bits_xor = 0x00; - col = s->cirrus_blt_fgcol; - } - pattern_y = s->cirrus_blt_srcaddr & 7; - - for(y = 0; y < bltheight; y++) { - bits = src[pattern_y] ^ bits_xor; - bitpos = 7 - srcskipleft; - d = dst + dstskipleft; - for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { - if ((bits >> bitpos) & 1) { - PUTPIXEL(); - } - d += (DEPTH / 8); - bitpos = (bitpos - 1) & 7; - } - pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; - } -} - -static void -glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight) -{ - uint32_t colors[2]; - uint8_t *d; - int x, y, bitpos, pattern_y; - unsigned int bits; - unsigned int col; - int srcskipleft = s->vga.gr[0x2f] & 0x07; - int dstskipleft = srcskipleft * (DEPTH / 8); - - colors[0] = s->cirrus_blt_bgcol; - colors[1] = s->cirrus_blt_fgcol; - pattern_y = s->cirrus_blt_srcaddr & 7; - - for(y = 0; y < bltheight; y++) { - bits = src[pattern_y]; - bitpos = 7 - srcskipleft; - d = dst + dstskipleft; - for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { - col = colors[(bits >> bitpos) & 1]; - PUTPIXEL(); - d += (DEPTH / 8); - bitpos = (bitpos - 1) & 7; - } - pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; - } -} - -static void -glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) - (CirrusVGAState *s, - uint8_t *dst, int dst_pitch, - int width, int height) -{ - uint8_t *d, *d1; - uint32_t col; - int x, y; - - col = s->cirrus_blt_fgcol; - - d1 = dst; - for(y = 0; y < height; y++) { - d = d1; - for(x = 0; x < width; x += (DEPTH / 8)) { - PUTPIXEL(); - d += (DEPTH / 8); - } - d1 += dst_pitch; - } -} - -#undef DEPTH -#undef PUTPIXEL diff --git a/qemu/hw/display/exynos4210_fimd.c b/qemu/hw/display/exynos4210_fimd.c deleted file mode 100644 index 728eb214a..000000000 --- a/qemu/hw/display/exynos4210_fimd.c +++ /dev/null @@ -1,1952 +0,0 @@ -/* - * Samsung exynos4210 Display Controller (FIMD) - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. - * All rights reserved. - * Based on LCD controller for Samsung S5PC1xx-based board emulation - * by Kirill Batuzov - * - * Contributed by Mitsyanko Igor - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "hw/sysbus.h" -#include "ui/console.h" -#include "ui/pixel_ops.h" -#include "qemu/bswap.h" - -/* Debug messages configuration */ -#define EXYNOS4210_FIMD_DEBUG 0 -#define EXYNOS4210_FIMD_MODE_TRACE 0 - -#if EXYNOS4210_FIMD_DEBUG == 0 - #define DPRINT_L1(fmt, args...) do { } while (0) - #define DPRINT_L2(fmt, args...) do { } while (0) - #define DPRINT_ERROR(fmt, args...) do { } while (0) -#elif EXYNOS4210_FIMD_DEBUG == 1 - #define DPRINT_L1(fmt, args...) \ - do {fprintf(stderr, "QEMU FIMD: "fmt, ## args); } while (0) - #define DPRINT_L2(fmt, args...) do { } while (0) - #define DPRINT_ERROR(fmt, args...) \ - do {fprintf(stderr, "QEMU FIMD ERROR: "fmt, ## args); } while (0) -#else - #define DPRINT_L1(fmt, args...) \ - do {fprintf(stderr, "QEMU FIMD: "fmt, ## args); } while (0) - #define DPRINT_L2(fmt, args...) \ - do {fprintf(stderr, "QEMU FIMD: "fmt, ## args); } while (0) - #define DPRINT_ERROR(fmt, args...) \ - do {fprintf(stderr, "QEMU FIMD ERROR: "fmt, ## args); } while (0) -#endif - -#if EXYNOS4210_FIMD_MODE_TRACE == 0 - #define DPRINT_TRACE(fmt, args...) do { } while (0) -#else - #define DPRINT_TRACE(fmt, args...) \ - do {fprintf(stderr, "QEMU FIMD: "fmt, ## args); } while (0) -#endif - -#define NUM_OF_WINDOWS 5 -#define FIMD_REGS_SIZE 0x4114 - -/* Video main control registers */ -#define FIMD_VIDCON0 0x0000 -#define FIMD_VIDCON1 0x0004 -#define FIMD_VIDCON2 0x0008 -#define FIMD_VIDCON3 0x000C -#define FIMD_VIDCON0_ENVID_F (1 << 0) -#define FIMD_VIDCON0_ENVID (1 << 1) -#define FIMD_VIDCON0_ENVID_MASK ((1 << 0) | (1 << 1)) -#define FIMD_VIDCON1_ROMASK 0x07FFE000 - -/* Video time control registers */ -#define FIMD_VIDTCON_START 0x10 -#define FIMD_VIDTCON_END 0x1C -#define FIMD_VIDTCON2_SIZE_MASK 0x07FF -#define FIMD_VIDTCON2_HOR_SHIFT 0 -#define FIMD_VIDTCON2_VER_SHIFT 11 - -/* Window control registers */ -#define FIMD_WINCON_START 0x0020 -#define FIMD_WINCON_END 0x0030 -#define FIMD_WINCON_ROMASK 0x82200000 -#define FIMD_WINCON_ENWIN (1 << 0) -#define FIMD_WINCON_BLD_PIX (1 << 6) -#define FIMD_WINCON_ALPHA_MUL (1 << 7) -#define FIMD_WINCON_ALPHA_SEL (1 << 1) -#define FIMD_WINCON_SWAP 0x078000 -#define FIMD_WINCON_SWAP_SHIFT 15 -#define FIMD_WINCON_SWAP_WORD 0x1 -#define FIMD_WINCON_SWAP_HWORD 0x2 -#define FIMD_WINCON_SWAP_BYTE 0x4 -#define FIMD_WINCON_SWAP_BITS 0x8 -#define FIMD_WINCON_BUFSTAT_L (1 << 21) -#define FIMD_WINCON_BUFSTAT_H (1 << 31) -#define FIMD_WINCON_BUFSTATUS ((1 << 21) | (1 << 31)) -#define FIMD_WINCON_BUF0_STAT ((0 << 21) | (0 << 31)) -#define FIMD_WINCON_BUF1_STAT ((1 << 21) | (0 << 31)) -#define FIMD_WINCON_BUF2_STAT ((0 << 21) | (1 << 31)) -#define FIMD_WINCON_BUFSELECT ((1 << 20) | (1 << 30)) -#define FIMD_WINCON_BUF0_SEL ((0 << 20) | (0 << 30)) -#define FIMD_WINCON_BUF1_SEL ((1 << 20) | (0 << 30)) -#define FIMD_WINCON_BUF2_SEL ((0 << 20) | (1 << 30)) -#define FIMD_WINCON_BUFMODE (1 << 14) -#define IS_PALETTIZED_MODE(w) (w->wincon & 0xC) -#define PAL_MODE_WITH_ALPHA(x) ((x) == 7) -#define WIN_BPP_MODE(w) ((w->wincon >> 2) & 0xF) -#define WIN_BPP_MODE_WITH_ALPHA(w) \ - (WIN_BPP_MODE(w) == 0xD || WIN_BPP_MODE(w) == 0xE) - -/* Shadow control register */ -#define FIMD_SHADOWCON 0x0034 -#define FIMD_WINDOW_PROTECTED(s, w) ((s) & (1 << (10 + (w)))) -/* Channel mapping control register */ -#define FIMD_WINCHMAP 0x003C - -/* Window position control registers */ -#define FIMD_VIDOSD_START 0x0040 -#define FIMD_VIDOSD_END 0x0088 -#define FIMD_VIDOSD_COORD_MASK 0x07FF -#define FIMD_VIDOSD_HOR_SHIFT 11 -#define FIMD_VIDOSD_VER_SHIFT 0 -#define FIMD_VIDOSD_ALPHA_AEN0 0xFFF000 -#define FIMD_VIDOSD_AEN0_SHIFT 12 -#define FIMD_VIDOSD_ALPHA_AEN1 0x000FFF - -/* Frame buffer address registers */ -#define FIMD_VIDWADD0_START 0x00A0 -#define FIMD_VIDWADD0_END 0x00C4 -#define FIMD_VIDWADD0_END 0x00C4 -#define FIMD_VIDWADD1_START 0x00D0 -#define FIMD_VIDWADD1_END 0x00F4 -#define FIMD_VIDWADD2_START 0x0100 -#define FIMD_VIDWADD2_END 0x0110 -#define FIMD_VIDWADD2_PAGEWIDTH 0x1FFF -#define FIMD_VIDWADD2_OFFSIZE 0x1FFF -#define FIMD_VIDWADD2_OFFSIZE_SHIFT 13 -#define FIMD_VIDW0ADD0_B2 0x20A0 -#define FIMD_VIDW4ADD0_B2 0x20C0 - -/* Video interrupt control registers */ -#define FIMD_VIDINTCON0 0x130 -#define FIMD_VIDINTCON1 0x134 - -/* Window color key registers */ -#define FIMD_WKEYCON_START 0x140 -#define FIMD_WKEYCON_END 0x15C -#define FIMD_WKEYCON0_COMPKEY 0x00FFFFFF -#define FIMD_WKEYCON0_CTL_SHIFT 24 -#define FIMD_WKEYCON0_DIRCON (1 << 24) -#define FIMD_WKEYCON0_KEYEN (1 << 25) -#define FIMD_WKEYCON0_KEYBLEN (1 << 26) -/* Window color key alpha control register */ -#define FIMD_WKEYALPHA_START 0x160 -#define FIMD_WKEYALPHA_END 0x16C - -/* Dithering control register */ -#define FIMD_DITHMODE 0x170 - -/* Window alpha control registers */ -#define FIMD_VIDALPHA_ALPHA_LOWER 0x000F0F0F -#define FIMD_VIDALPHA_ALPHA_UPPER 0x00F0F0F0 -#define FIMD_VIDWALPHA_START 0x21C -#define FIMD_VIDWALPHA_END 0x240 - -/* Window color map registers */ -#define FIMD_WINMAP_START 0x180 -#define FIMD_WINMAP_END 0x190 -#define FIMD_WINMAP_EN (1 << 24) -#define FIMD_WINMAP_COLOR_MASK 0x00FFFFFF - -/* Window palette control registers */ -#define FIMD_WPALCON_HIGH 0x019C -#define FIMD_WPALCON_LOW 0x01A0 -#define FIMD_WPALCON_UPDATEEN (1 << 9) -#define FIMD_WPAL_W0PAL_L 0x07 -#define FIMD_WPAL_W0PAL_L_SHT 0 -#define FIMD_WPAL_W1PAL_L 0x07 -#define FIMD_WPAL_W1PAL_L_SHT 3 -#define FIMD_WPAL_W2PAL_L 0x01 -#define FIMD_WPAL_W2PAL_L_SHT 6 -#define FIMD_WPAL_W2PAL_H 0x06 -#define FIMD_WPAL_W2PAL_H_SHT 8 -#define FIMD_WPAL_W3PAL_L 0x01 -#define FIMD_WPAL_W3PAL_L_SHT 7 -#define FIMD_WPAL_W3PAL_H 0x06 -#define FIMD_WPAL_W3PAL_H_SHT 12 -#define FIMD_WPAL_W4PAL_L 0x01 -#define FIMD_WPAL_W4PAL_L_SHT 8 -#define FIMD_WPAL_W4PAL_H 0x06 -#define FIMD_WPAL_W4PAL_H_SHT 16 - -/* Trigger control registers */ -#define FIMD_TRIGCON 0x01A4 -#define FIMD_TRIGCON_ROMASK 0x00000004 - -/* LCD I80 Interface Control */ -#define FIMD_I80IFCON_START 0x01B0 -#define FIMD_I80IFCON_END 0x01BC -/* Color gain control register */ -#define FIMD_COLORGAINCON 0x01C0 -/* LCD i80 Interface Command Control */ -#define FIMD_LDI_CMDCON0 0x01D0 -#define FIMD_LDI_CMDCON1 0x01D4 -/* I80 System Interface Manual Command Control */ -#define FIMD_SIFCCON0 0x01E0 -#define FIMD_SIFCCON2 0x01E8 - -/* Hue Control Registers */ -#define FIMD_HUECOEFCR_START 0x01EC -#define FIMD_HUECOEFCR_END 0x01F4 -#define FIMD_HUECOEFCB_START 0x01FC -#define FIMD_HUECOEFCB_END 0x0208 -#define FIMD_HUEOFFSET 0x020C - -/* Video interrupt control registers */ -#define FIMD_VIDINT_INTFIFOPEND (1 << 0) -#define FIMD_VIDINT_INTFRMPEND (1 << 1) -#define FIMD_VIDINT_INTI80PEND (1 << 2) -#define FIMD_VIDINT_INTEN (1 << 0) -#define FIMD_VIDINT_INTFIFOEN (1 << 1) -#define FIMD_VIDINT_INTFRMEN (1 << 12) -#define FIMD_VIDINT_I80IFDONE (1 << 17) - -/* Window blend equation control registers */ -#define FIMD_BLENDEQ_START 0x0244 -#define FIMD_BLENDEQ_END 0x0250 -#define FIMD_BLENDCON 0x0260 -#define FIMD_ALPHA_8BIT (1 << 0) -#define FIMD_BLENDEQ_COEF_MASK 0xF - -/* Window RTQOS Control Registers */ -#define FIMD_WRTQOSCON_START 0x0264 -#define FIMD_WRTQOSCON_END 0x0274 - -/* LCD I80 Interface Command */ -#define FIMD_I80IFCMD_START 0x0280 -#define FIMD_I80IFCMD_END 0x02AC - -/* Shadow windows control registers */ -#define FIMD_SHD_ADD0_START 0x40A0 -#define FIMD_SHD_ADD0_END 0x40C0 -#define FIMD_SHD_ADD1_START 0x40D0 -#define FIMD_SHD_ADD1_END 0x40F0 -#define FIMD_SHD_ADD2_START 0x4100 -#define FIMD_SHD_ADD2_END 0x4110 - -/* Palette memory */ -#define FIMD_PAL_MEM_START 0x2400 -#define FIMD_PAL_MEM_END 0x37FC -/* Palette memory aliases for windows 0 and 1 */ -#define FIMD_PALMEM_AL_START 0x0400 -#define FIMD_PALMEM_AL_END 0x0BFC - -typedef struct { - uint8_t r, g, b; - /* D[31..24]dummy, D[23..16]rAlpha, D[15..8]gAlpha, D[7..0]bAlpha */ - uint32_t a; -} rgba; -#define RGBA_SIZE 7 - -typedef void pixel_to_rgb_func(uint32_t pixel, rgba *p); -typedef struct Exynos4210fimdWindow Exynos4210fimdWindow; - -struct Exynos4210fimdWindow { - uint32_t wincon; /* Window control register */ - uint32_t buf_start[3]; /* Start address for video frame buffer */ - uint32_t buf_end[3]; /* End address for video frame buffer */ - uint32_t keycon[2]; /* Window color key registers */ - uint32_t keyalpha; /* Color key alpha control register */ - uint32_t winmap; /* Window color map register */ - uint32_t blendeq; /* Window blending equation control register */ - uint32_t rtqoscon; /* Window RTQOS Control Registers */ - uint32_t palette[256]; /* Palette RAM */ - uint32_t shadow_buf_start; /* Start address of shadow frame buffer */ - uint32_t shadow_buf_end; /* End address of shadow frame buffer */ - uint32_t shadow_buf_size; /* Virtual shadow screen width */ - - pixel_to_rgb_func *pixel_to_rgb; - void (*draw_line)(Exynos4210fimdWindow *w, uint8_t *src, uint8_t *dst, - bool blend); - uint32_t (*get_alpha)(Exynos4210fimdWindow *w, uint32_t pix_a); - uint16_t lefttop_x, lefttop_y; /* VIDOSD0 register */ - uint16_t rightbot_x, rightbot_y; /* VIDOSD1 register */ - uint32_t osdsize; /* VIDOSD2&3 register */ - uint32_t alpha_val[2]; /* VIDOSD2&3, VIDWALPHA registers */ - uint16_t virtpage_width; /* VIDWADD2 register */ - uint16_t virtpage_offsize; /* VIDWADD2 register */ - MemoryRegionSection mem_section; /* RAM fragment containing framebuffer */ - uint8_t *host_fb_addr; /* Host pointer to window's framebuffer */ - hwaddr fb_len; /* Framebuffer length */ -}; - -#define TYPE_EXYNOS4210_FIMD "exynos4210.fimd" -#define EXYNOS4210_FIMD(obj) \ - OBJECT_CHECK(Exynos4210fimdState, (obj), TYPE_EXYNOS4210_FIMD) - -typedef struct { - SysBusDevice parent_obj; - - MemoryRegion iomem; - QemuConsole *console; - qemu_irq irq[3]; - - uint32_t vidcon[4]; /* Video main control registers 0-3 */ - uint32_t vidtcon[4]; /* Video time control registers 0-3 */ - uint32_t shadowcon; /* Window shadow control register */ - uint32_t winchmap; /* Channel mapping control register */ - uint32_t vidintcon[2]; /* Video interrupt control registers */ - uint32_t dithmode; /* Dithering control register */ - uint32_t wpalcon[2]; /* Window palette control registers */ - uint32_t trigcon; /* Trigger control register */ - uint32_t i80ifcon[4]; /* I80 interface control registers */ - uint32_t colorgaincon; /* Color gain control register */ - uint32_t ldi_cmdcon[2]; /* LCD I80 interface command control */ - uint32_t sifccon[3]; /* I80 System Interface Manual Command Control */ - uint32_t huecoef_cr[4]; /* Hue control registers */ - uint32_t huecoef_cb[4]; /* Hue control registers */ - uint32_t hueoffset; /* Hue offset control register */ - uint32_t blendcon; /* Blending control register */ - uint32_t i80ifcmd[12]; /* LCD I80 Interface Command */ - - Exynos4210fimdWindow window[5]; /* Window-specific registers */ - uint8_t *ifb; /* Internal frame buffer */ - bool invalidate; /* Image needs to be redrawn */ - bool enabled; /* Display controller is enabled */ -} Exynos4210fimdState; - -/* Perform byte/halfword/word swap of data according to WINCON */ -static inline void fimd_swap_data(unsigned int swap_ctl, uint64_t *data) -{ - int i; - uint64_t res; - uint64_t x = *data; - - if (swap_ctl & FIMD_WINCON_SWAP_BITS) { - res = 0; - for (i = 0; i < 64; i++) { - if (x & (1ULL << (63 - i))) { - res |= (1ULL << i); - } - } - x = res; - } - - if (swap_ctl & FIMD_WINCON_SWAP_BYTE) { - x = bswap64(x); - } - - if (swap_ctl & FIMD_WINCON_SWAP_HWORD) { - x = ((x & 0x000000000000FFFFULL) << 48) | - ((x & 0x00000000FFFF0000ULL) << 16) | - ((x & 0x0000FFFF00000000ULL) >> 16) | - ((x & 0xFFFF000000000000ULL) >> 48); - } - - if (swap_ctl & FIMD_WINCON_SWAP_WORD) { - x = ((x & 0x00000000FFFFFFFFULL) << 32) | - ((x & 0xFFFFFFFF00000000ULL) >> 32); - } - - *data = x; -} - -/* Conversion routines of Pixel data from frame buffer area to internal RGBA - * pixel representation. - * Every color component internally represented as 8-bit value. If original - * data has less than 8 bit for component, data is extended to 8 bit. For - * example, if blue component has only two possible values 0 and 1 it will be - * extended to 0 and 0xFF */ - -/* One bit for alpha representation */ -#define DEF_PIXEL_TO_RGB_A1(N, R, G, B) \ -static void N(uint32_t pixel, rgba *p) \ -{ \ - p->b = ((pixel & ((1 << (B)) - 1)) << (8 - (B))) | \ - ((pixel >> (2 * (B) - 8)) & ((1 << (8 - (B))) - 1)); \ - pixel >>= (B); \ - p->g = (pixel & ((1 << (G)) - 1)) << (8 - (G)) | \ - ((pixel >> (2 * (G) - 8)) & ((1 << (8 - (G))) - 1)); \ - pixel >>= (G); \ - p->r = (pixel & ((1 << (R)) - 1)) << (8 - (R)) | \ - ((pixel >> (2 * (R) - 8)) & ((1 << (8 - (R))) - 1)); \ - pixel >>= (R); \ - p->a = (pixel & 0x1); \ -} - -DEF_PIXEL_TO_RGB_A1(pixel_a444_to_rgb, 4, 4, 4) -DEF_PIXEL_TO_RGB_A1(pixel_a555_to_rgb, 5, 5, 5) -DEF_PIXEL_TO_RGB_A1(pixel_a666_to_rgb, 6, 6, 6) -DEF_PIXEL_TO_RGB_A1(pixel_a665_to_rgb, 6, 6, 5) -DEF_PIXEL_TO_RGB_A1(pixel_a888_to_rgb, 8, 8, 8) -DEF_PIXEL_TO_RGB_A1(pixel_a887_to_rgb, 8, 8, 7) - -/* Alpha component is always zero */ -#define DEF_PIXEL_TO_RGB_A0(N, R, G, B) \ -static void N(uint32_t pixel, rgba *p) \ -{ \ - p->b = ((pixel & ((1 << (B)) - 1)) << (8 - (B))) | \ - ((pixel >> (2 * (B) - 8)) & ((1 << (8 - (B))) - 1)); \ - pixel >>= (B); \ - p->g = (pixel & ((1 << (G)) - 1)) << (8 - (G)) | \ - ((pixel >> (2 * (G) - 8)) & ((1 << (8 - (G))) - 1)); \ - pixel >>= (G); \ - p->r = (pixel & ((1 << (R)) - 1)) << (8 - (R)) | \ - ((pixel >> (2 * (R) - 8)) & ((1 << (8 - (R))) - 1)); \ - p->a = 0x0; \ -} - -DEF_PIXEL_TO_RGB_A0(pixel_565_to_rgb, 5, 6, 5) -DEF_PIXEL_TO_RGB_A0(pixel_555_to_rgb, 5, 5, 5) -DEF_PIXEL_TO_RGB_A0(pixel_666_to_rgb, 6, 6, 6) -DEF_PIXEL_TO_RGB_A0(pixel_888_to_rgb, 8, 8, 8) - -/* Alpha component has some meaningful value */ -#define DEF_PIXEL_TO_RGB_A(N, R, G, B, A) \ -static void N(uint32_t pixel, rgba *p) \ -{ \ - p->b = ((pixel & ((1 << (B)) - 1)) << (8 - (B))) | \ - ((pixel >> (2 * (B) - 8)) & ((1 << (8 - (B))) - 1)); \ - pixel >>= (B); \ - p->g = (pixel & ((1 << (G)) - 1)) << (8 - (G)) | \ - ((pixel >> (2 * (G) - 8)) & ((1 << (8 - (G))) - 1)); \ - pixel >>= (G); \ - p->r = (pixel & ((1 << (R)) - 1)) << (8 - (R)) | \ - ((pixel >> (2 * (R) - 8)) & ((1 << (8 - (R))) - 1)); \ - pixel >>= (R); \ - p->a = (pixel & ((1 << (A)) - 1)) << (8 - (A)) | \ - ((pixel >> (2 * (A) - 8)) & ((1 << (8 - (A))) - 1)); \ - p->a = p->a | (p->a << 8) | (p->a << 16); \ -} - -DEF_PIXEL_TO_RGB_A(pixel_4444_to_rgb, 4, 4, 4, 4) -DEF_PIXEL_TO_RGB_A(pixel_8888_to_rgb, 8, 8, 8, 8) - -/* Lookup table to extent 2-bit color component to 8 bit */ -static const uint8_t pixel_lutable_2b[4] = { - 0x0, 0x55, 0xAA, 0xFF -}; -/* Lookup table to extent 3-bit color component to 8 bit */ -static const uint8_t pixel_lutable_3b[8] = { - 0x0, 0x24, 0x49, 0x6D, 0x92, 0xB6, 0xDB, 0xFF -}; -/* Special case for a232 bpp mode */ -static void pixel_a232_to_rgb(uint32_t pixel, rgba *p) -{ - p->b = pixel_lutable_2b[(pixel & 0x3)]; - pixel >>= 2; - p->g = pixel_lutable_3b[(pixel & 0x7)]; - pixel >>= 3; - p->r = pixel_lutable_2b[(pixel & 0x3)]; - pixel >>= 2; - p->a = (pixel & 0x1); -} - -/* Special case for (5+1, 5+1, 5+1) mode. Data bit 15 is common LSB - * for all three color components */ -static void pixel_1555_to_rgb(uint32_t pixel, rgba *p) -{ - uint8_t comm = (pixel >> 15) & 1; - p->b = ((((pixel & 0x1F) << 1) | comm) << 2) | ((pixel >> 3) & 0x3); - pixel >>= 5; - p->g = ((((pixel & 0x1F) << 1) | comm) << 2) | ((pixel >> 3) & 0x3); - pixel >>= 5; - p->r = ((((pixel & 0x1F) << 1) | comm) << 2) | ((pixel >> 3) & 0x3); - p->a = 0x0; -} - -/* Put/get pixel to/from internal LCD Controller framebuffer */ - -static int put_pixel_ifb(const rgba p, uint8_t *d) -{ - *(uint8_t *)d++ = p.r; - *(uint8_t *)d++ = p.g; - *(uint8_t *)d++ = p.b; - *(uint32_t *)d = p.a; - return RGBA_SIZE; -} - -static int get_pixel_ifb(const uint8_t *s, rgba *p) -{ - p->r = *(uint8_t *)s++; - p->g = *(uint8_t *)s++; - p->b = *(uint8_t *)s++; - p->a = (*(uint32_t *)s) & 0x00FFFFFF; - return RGBA_SIZE; -} - -static pixel_to_rgb_func *palette_data_format[8] = { - [0] = pixel_565_to_rgb, - [1] = pixel_a555_to_rgb, - [2] = pixel_666_to_rgb, - [3] = pixel_a665_to_rgb, - [4] = pixel_a666_to_rgb, - [5] = pixel_888_to_rgb, - [6] = pixel_a888_to_rgb, - [7] = pixel_8888_to_rgb -}; - -/* Returns Index in palette data formats table for given window number WINDOW */ -static uint32_t -exynos4210_fimd_palette_format(Exynos4210fimdState *s, int window) -{ - uint32_t ret; - - switch (window) { - case 0: - ret = (s->wpalcon[1] >> FIMD_WPAL_W0PAL_L_SHT) & FIMD_WPAL_W0PAL_L; - if (ret != 7) { - ret = 6 - ret; - } - break; - case 1: - ret = (s->wpalcon[1] >> FIMD_WPAL_W1PAL_L_SHT) & FIMD_WPAL_W1PAL_L; - if (ret != 7) { - ret = 6 - ret; - } - break; - case 2: - ret = ((s->wpalcon[0] >> FIMD_WPAL_W2PAL_H_SHT) & FIMD_WPAL_W2PAL_H) | - ((s->wpalcon[1] >> FIMD_WPAL_W2PAL_L_SHT) & FIMD_WPAL_W2PAL_L); - break; - case 3: - ret = ((s->wpalcon[0] >> FIMD_WPAL_W3PAL_H_SHT) & FIMD_WPAL_W3PAL_H) | - ((s->wpalcon[1] >> FIMD_WPAL_W3PAL_L_SHT) & FIMD_WPAL_W3PAL_L); - break; - case 4: - ret = ((s->wpalcon[0] >> FIMD_WPAL_W4PAL_H_SHT) & FIMD_WPAL_W4PAL_H) | - ((s->wpalcon[1] >> FIMD_WPAL_W4PAL_L_SHT) & FIMD_WPAL_W4PAL_L); - break; - default: - hw_error("exynos4210.fimd: incorrect window number %d\n", window); - ret = 0; - break; - } - return ret; -} - -#define FIMD_1_MINUS_COLOR(x) \ - ((0xFF - ((x) & 0xFF)) | (0xFF00 - ((x) & 0xFF00)) | \ - (0xFF0000 - ((x) & 0xFF0000))) -#define EXTEND_LOWER_HALFBYTE(x) (((x) & 0xF0F0F) | (((x) << 4) & 0xF0F0F0)) -#define EXTEND_UPPER_HALFBYTE(x) (((x) & 0xF0F0F0) | (((x) >> 4) & 0xF0F0F)) - -/* Multiply three lower bytes of two 32-bit words with each other. - * Each byte with values 0-255 is considered as a number with possible values - * in a range [0 - 1] */ -static inline uint32_t fimd_mult_each_byte(uint32_t a, uint32_t b) -{ - uint32_t tmp; - uint32_t ret; - - ret = ((tmp = (((a & 0xFF) * (b & 0xFF)) / 0xFF)) > 0xFF) ? 0xFF : tmp; - ret |= ((tmp = ((((a >> 8) & 0xFF) * ((b >> 8) & 0xFF)) / 0xFF)) > 0xFF) ? - 0xFF00 : tmp << 8; - ret |= ((tmp = ((((a >> 16) & 0xFF) * ((b >> 16) & 0xFF)) / 0xFF)) > 0xFF) ? - 0xFF0000 : tmp << 16; - return ret; -} - -/* For each corresponding bytes of two 32-bit words: (a*b + c*d) - * Byte values 0-255 are mapped to a range [0 .. 1] */ -static inline uint32_t -fimd_mult_and_sum_each_byte(uint32_t a, uint32_t b, uint32_t c, uint32_t d) -{ - uint32_t tmp; - uint32_t ret; - - ret = ((tmp = (((a & 0xFF) * (b & 0xFF) + (c & 0xFF) * (d & 0xFF)) / 0xFF)) - > 0xFF) ? 0xFF : tmp; - ret |= ((tmp = ((((a >> 8) & 0xFF) * ((b >> 8) & 0xFF) + ((c >> 8) & 0xFF) * - ((d >> 8) & 0xFF)) / 0xFF)) > 0xFF) ? 0xFF00 : tmp << 8; - ret |= ((tmp = ((((a >> 16) & 0xFF) * ((b >> 16) & 0xFF) + - ((c >> 16) & 0xFF) * ((d >> 16) & 0xFF)) / 0xFF)) > 0xFF) ? - 0xFF0000 : tmp << 16; - return ret; -} - -/* These routines cover all possible sources of window's transparent factor - * used in blending equation. Choice of routine is affected by WPALCON - * registers, BLENDCON register and window's WINCON register */ - -static uint32_t fimd_get_alpha_pix(Exynos4210fimdWindow *w, uint32_t pix_a) -{ - return pix_a; -} - -static uint32_t -fimd_get_alpha_pix_extlow(Exynos4210fimdWindow *w, uint32_t pix_a) -{ - return EXTEND_LOWER_HALFBYTE(pix_a); -} - -static uint32_t -fimd_get_alpha_pix_exthigh(Exynos4210fimdWindow *w, uint32_t pix_a) -{ - return EXTEND_UPPER_HALFBYTE(pix_a); -} - -static uint32_t fimd_get_alpha_mult(Exynos4210fimdWindow *w, uint32_t pix_a) -{ - return fimd_mult_each_byte(pix_a, w->alpha_val[0]); -} - -static uint32_t fimd_get_alpha_mult_ext(Exynos4210fimdWindow *w, uint32_t pix_a) -{ - return fimd_mult_each_byte(EXTEND_LOWER_HALFBYTE(pix_a), - EXTEND_UPPER_HALFBYTE(w->alpha_val[0])); -} - -static uint32_t fimd_get_alpha_aen(Exynos4210fimdWindow *w, uint32_t pix_a) -{ - return w->alpha_val[pix_a]; -} - -static uint32_t fimd_get_alpha_aen_ext(Exynos4210fimdWindow *w, uint32_t pix_a) -{ - return EXTEND_UPPER_HALFBYTE(w->alpha_val[pix_a]); -} - -static uint32_t fimd_get_alpha_sel(Exynos4210fimdWindow *w, uint32_t pix_a) -{ - return w->alpha_val[(w->wincon & FIMD_WINCON_ALPHA_SEL) ? 1 : 0]; -} - -static uint32_t fimd_get_alpha_sel_ext(Exynos4210fimdWindow *w, uint32_t pix_a) -{ - return EXTEND_UPPER_HALFBYTE(w->alpha_val[(w->wincon & - FIMD_WINCON_ALPHA_SEL) ? 1 : 0]); -} - -/* Updates currently active alpha value get function for specified window */ -static void fimd_update_get_alpha(Exynos4210fimdState *s, int win) -{ - Exynos4210fimdWindow *w = &s->window[win]; - const bool alpha_is_8bit = s->blendcon & FIMD_ALPHA_8BIT; - - if (w->wincon & FIMD_WINCON_BLD_PIX) { - if ((w->wincon & FIMD_WINCON_ALPHA_SEL) && WIN_BPP_MODE_WITH_ALPHA(w)) { - /* In this case, alpha component contains meaningful value */ - if (w->wincon & FIMD_WINCON_ALPHA_MUL) { - w->get_alpha = alpha_is_8bit ? - fimd_get_alpha_mult : fimd_get_alpha_mult_ext; - } else { - w->get_alpha = alpha_is_8bit ? - fimd_get_alpha_pix : fimd_get_alpha_pix_extlow; - } - } else { - if (IS_PALETTIZED_MODE(w) && - PAL_MODE_WITH_ALPHA(exynos4210_fimd_palette_format(s, win))) { - /* Alpha component has 8-bit numeric value */ - w->get_alpha = alpha_is_8bit ? - fimd_get_alpha_pix : fimd_get_alpha_pix_exthigh; - } else { - /* Alpha has only two possible values (AEN) */ - w->get_alpha = alpha_is_8bit ? - fimd_get_alpha_aen : fimd_get_alpha_aen_ext; - } - } - } else { - w->get_alpha = alpha_is_8bit ? fimd_get_alpha_sel : - fimd_get_alpha_sel_ext; - } -} - -/* Blends current window's (w) pixel (foreground pixel *ret) with background - * window (w_blend) pixel p_bg according to formula: - * NEW_COLOR = a_coef x FG_PIXEL_COLOR + b_coef x BG_PIXEL_COLOR - * NEW_ALPHA = p_coef x FG_ALPHA + q_coef x BG_ALPHA - */ -static void -exynos4210_fimd_blend_pixel(Exynos4210fimdWindow *w, rgba p_bg, rgba *ret) -{ - rgba p_fg = *ret; - uint32_t bg_color = ((p_bg.r & 0xFF) << 16) | ((p_bg.g & 0xFF) << 8) | - (p_bg.b & 0xFF); - uint32_t fg_color = ((p_fg.r & 0xFF) << 16) | ((p_fg.g & 0xFF) << 8) | - (p_fg.b & 0xFF); - uint32_t alpha_fg = p_fg.a; - int i; - /* It is possible that blending equation parameters a and b do not - * depend on window BLENEQ register. Account for this with first_coef */ - enum { A_COEF = 0, B_COEF = 1, P_COEF = 2, Q_COEF = 3, COEF_NUM = 4}; - uint32_t first_coef = A_COEF; - uint32_t blend_param[COEF_NUM]; - - if (w->keycon[0] & FIMD_WKEYCON0_KEYEN) { - uint32_t colorkey = (w->keycon[1] & - ~(w->keycon[0] & FIMD_WKEYCON0_COMPKEY)) & FIMD_WKEYCON0_COMPKEY; - - if ((w->keycon[0] & FIMD_WKEYCON0_DIRCON) && - (bg_color & ~(w->keycon[0] & FIMD_WKEYCON0_COMPKEY)) == colorkey) { - /* Foreground pixel is displayed */ - if (w->keycon[0] & FIMD_WKEYCON0_KEYBLEN) { - alpha_fg = w->keyalpha; - blend_param[A_COEF] = alpha_fg; - blend_param[B_COEF] = FIMD_1_MINUS_COLOR(alpha_fg); - } else { - alpha_fg = 0; - blend_param[A_COEF] = 0xFFFFFF; - blend_param[B_COEF] = 0x0; - } - first_coef = P_COEF; - } else if ((w->keycon[0] & FIMD_WKEYCON0_DIRCON) == 0 && - (fg_color & ~(w->keycon[0] & FIMD_WKEYCON0_COMPKEY)) == colorkey) { - /* Background pixel is displayed */ - if (w->keycon[0] & FIMD_WKEYCON0_KEYBLEN) { - alpha_fg = w->keyalpha; - blend_param[A_COEF] = alpha_fg; - blend_param[B_COEF] = FIMD_1_MINUS_COLOR(alpha_fg); - } else { - alpha_fg = 0; - blend_param[A_COEF] = 0x0; - blend_param[B_COEF] = 0xFFFFFF; - } - first_coef = P_COEF; - } - } - - for (i = first_coef; i < COEF_NUM; i++) { - switch ((w->blendeq >> i * 6) & FIMD_BLENDEQ_COEF_MASK) { - case 0: - blend_param[i] = 0; - break; - case 1: - blend_param[i] = 0xFFFFFF; - break; - case 2: - blend_param[i] = alpha_fg; - break; - case 3: - blend_param[i] = FIMD_1_MINUS_COLOR(alpha_fg); - break; - case 4: - blend_param[i] = p_bg.a; - break; - case 5: - blend_param[i] = FIMD_1_MINUS_COLOR(p_bg.a); - break; - case 6: - blend_param[i] = w->alpha_val[0]; - break; - case 10: - blend_param[i] = fg_color; - break; - case 11: - blend_param[i] = FIMD_1_MINUS_COLOR(fg_color); - break; - case 12: - blend_param[i] = bg_color; - break; - case 13: - blend_param[i] = FIMD_1_MINUS_COLOR(bg_color); - break; - default: - hw_error("exynos4210.fimd: blend equation coef illegal value\n"); - break; - } - } - - fg_color = fimd_mult_and_sum_each_byte(bg_color, blend_param[B_COEF], - fg_color, blend_param[A_COEF]); - ret->b = fg_color & 0xFF; - fg_color >>= 8; - ret->g = fg_color & 0xFF; - fg_color >>= 8; - ret->r = fg_color & 0xFF; - ret->a = fimd_mult_and_sum_each_byte(alpha_fg, blend_param[P_COEF], - p_bg.a, blend_param[Q_COEF]); -} - -/* These routines read data from video frame buffer in system RAM, convert - * this data to display controller internal representation, if necessary, - * perform pixel blending with data, currently presented in internal buffer. - * Result is stored in display controller internal frame buffer. */ - -/* Draw line with index in palette table in RAM frame buffer data */ -#define DEF_DRAW_LINE_PALETTE(N) \ -static void glue(draw_line_palette_, N)(Exynos4210fimdWindow *w, uint8_t *src, \ - uint8_t *dst, bool blend) \ -{ \ - int width = w->rightbot_x - w->lefttop_x + 1; \ - uint8_t *ifb = dst; \ - uint8_t swap = (w->wincon & FIMD_WINCON_SWAP) >> FIMD_WINCON_SWAP_SHIFT; \ - uint64_t data; \ - rgba p, p_old; \ - int i; \ - do { \ - memcpy(&data, src, sizeof(data)); \ - src += 8; \ - fimd_swap_data(swap, &data); \ - for (i = (64 / (N) - 1); i >= 0; i--) { \ - w->pixel_to_rgb(w->palette[(data >> ((N) * i)) & \ - ((1ULL << (N)) - 1)], &p); \ - p.a = w->get_alpha(w, p.a); \ - if (blend) { \ - ifb += get_pixel_ifb(ifb, &p_old); \ - exynos4210_fimd_blend_pixel(w, p_old, &p); \ - } \ - dst += put_pixel_ifb(p, dst); \ - } \ - width -= (64 / (N)); \ - } while (width > 0); \ -} - -/* Draw line with direct color value in RAM frame buffer data */ -#define DEF_DRAW_LINE_NOPALETTE(N) \ -static void glue(draw_line_, N)(Exynos4210fimdWindow *w, uint8_t *src, \ - uint8_t *dst, bool blend) \ -{ \ - int width = w->rightbot_x - w->lefttop_x + 1; \ - uint8_t *ifb = dst; \ - uint8_t swap = (w->wincon & FIMD_WINCON_SWAP) >> FIMD_WINCON_SWAP_SHIFT; \ - uint64_t data; \ - rgba p, p_old; \ - int i; \ - do { \ - memcpy(&data, src, sizeof(data)); \ - src += 8; \ - fimd_swap_data(swap, &data); \ - for (i = (64 / (N) - 1); i >= 0; i--) { \ - w->pixel_to_rgb((data >> ((N) * i)) & ((1ULL << (N)) - 1), &p); \ - p.a = w->get_alpha(w, p.a); \ - if (blend) { \ - ifb += get_pixel_ifb(ifb, &p_old); \ - exynos4210_fimd_blend_pixel(w, p_old, &p); \ - } \ - dst += put_pixel_ifb(p, dst); \ - } \ - width -= (64 / (N)); \ - } while (width > 0); \ -} - -DEF_DRAW_LINE_PALETTE(1) -DEF_DRAW_LINE_PALETTE(2) -DEF_DRAW_LINE_PALETTE(4) -DEF_DRAW_LINE_PALETTE(8) -DEF_DRAW_LINE_NOPALETTE(8) /* 8bpp mode has palette and non-palette versions */ -DEF_DRAW_LINE_NOPALETTE(16) -DEF_DRAW_LINE_NOPALETTE(32) - -/* Special draw line routine for window color map case */ -static void draw_line_mapcolor(Exynos4210fimdWindow *w, uint8_t *src, - uint8_t *dst, bool blend) -{ - rgba p, p_old; - uint8_t *ifb = dst; - int width = w->rightbot_x - w->lefttop_x + 1; - uint32_t map_color = w->winmap & FIMD_WINMAP_COLOR_MASK; - - do { - pixel_888_to_rgb(map_color, &p); - p.a = w->get_alpha(w, p.a); - if (blend) { - ifb += get_pixel_ifb(ifb, &p_old); - exynos4210_fimd_blend_pixel(w, p_old, &p); - } - dst += put_pixel_ifb(p, dst); - } while (--width); -} - -/* Write RGB to QEMU's GraphicConsole framebuffer */ - -static int put_to_qemufb_pixel8(const rgba p, uint8_t *d) -{ - uint32_t pixel = rgb_to_pixel8(p.r, p.g, p.b); - *(uint8_t *)d = pixel; - return 1; -} - -static int put_to_qemufb_pixel15(const rgba p, uint8_t *d) -{ - uint32_t pixel = rgb_to_pixel15(p.r, p.g, p.b); - *(uint16_t *)d = pixel; - return 2; -} - -static int put_to_qemufb_pixel16(const rgba p, uint8_t *d) -{ - uint32_t pixel = rgb_to_pixel16(p.r, p.g, p.b); - *(uint16_t *)d = pixel; - return 2; -} - -static int put_to_qemufb_pixel24(const rgba p, uint8_t *d) -{ - uint32_t pixel = rgb_to_pixel24(p.r, p.g, p.b); - *(uint8_t *)d++ = (pixel >> 0) & 0xFF; - *(uint8_t *)d++ = (pixel >> 8) & 0xFF; - *(uint8_t *)d++ = (pixel >> 16) & 0xFF; - return 3; -} - -static int put_to_qemufb_pixel32(const rgba p, uint8_t *d) -{ - uint32_t pixel = rgb_to_pixel24(p.r, p.g, p.b); - *(uint32_t *)d = pixel; - return 4; -} - -/* Routine to copy pixel from internal buffer to QEMU buffer */ -static int (*put_pixel_toqemu)(const rgba p, uint8_t *pixel); -static inline void fimd_update_putpix_qemu(int bpp) -{ - switch (bpp) { - case 8: - put_pixel_toqemu = put_to_qemufb_pixel8; - break; - case 15: - put_pixel_toqemu = put_to_qemufb_pixel15; - break; - case 16: - put_pixel_toqemu = put_to_qemufb_pixel16; - break; - case 24: - put_pixel_toqemu = put_to_qemufb_pixel24; - break; - case 32: - put_pixel_toqemu = put_to_qemufb_pixel32; - break; - default: - hw_error("exynos4210.fimd: unsupported BPP (%d)", bpp); - break; - } -} - -/* Routine to copy a line from internal frame buffer to QEMU display */ -static void fimd_copy_line_toqemu(int width, uint8_t *src, uint8_t *dst) -{ - rgba p; - - do { - src += get_pixel_ifb(src, &p); - dst += put_pixel_toqemu(p, dst); - } while (--width); -} - -/* Parse BPPMODE_F = WINCON1[5:2] bits */ -static void exynos4210_fimd_update_win_bppmode(Exynos4210fimdState *s, int win) -{ - Exynos4210fimdWindow *w = &s->window[win]; - - if (w->winmap & FIMD_WINMAP_EN) { - w->draw_line = draw_line_mapcolor; - return; - } - - switch (WIN_BPP_MODE(w)) { - case 0: - w->draw_line = draw_line_palette_1; - w->pixel_to_rgb = - palette_data_format[exynos4210_fimd_palette_format(s, win)]; - break; - case 1: - w->draw_line = draw_line_palette_2; - w->pixel_to_rgb = - palette_data_format[exynos4210_fimd_palette_format(s, win)]; - break; - case 2: - w->draw_line = draw_line_palette_4; - w->pixel_to_rgb = - palette_data_format[exynos4210_fimd_palette_format(s, win)]; - break; - case 3: - w->draw_line = draw_line_palette_8; - w->pixel_to_rgb = - palette_data_format[exynos4210_fimd_palette_format(s, win)]; - break; - case 4: - w->draw_line = draw_line_8; - w->pixel_to_rgb = pixel_a232_to_rgb; - break; - case 5: - w->draw_line = draw_line_16; - w->pixel_to_rgb = pixel_565_to_rgb; - break; - case 6: - w->draw_line = draw_line_16; - w->pixel_to_rgb = pixel_a555_to_rgb; - break; - case 7: - w->draw_line = draw_line_16; - w->pixel_to_rgb = pixel_1555_to_rgb; - break; - case 8: - w->draw_line = draw_line_32; - w->pixel_to_rgb = pixel_666_to_rgb; - break; - case 9: - w->draw_line = draw_line_32; - w->pixel_to_rgb = pixel_a665_to_rgb; - break; - case 10: - w->draw_line = draw_line_32; - w->pixel_to_rgb = pixel_a666_to_rgb; - break; - case 11: - w->draw_line = draw_line_32; - w->pixel_to_rgb = pixel_888_to_rgb; - break; - case 12: - w->draw_line = draw_line_32; - w->pixel_to_rgb = pixel_a887_to_rgb; - break; - case 13: - w->draw_line = draw_line_32; - if ((w->wincon & FIMD_WINCON_BLD_PIX) && (w->wincon & - FIMD_WINCON_ALPHA_SEL)) { - w->pixel_to_rgb = pixel_8888_to_rgb; - } else { - w->pixel_to_rgb = pixel_a888_to_rgb; - } - break; - case 14: - w->draw_line = draw_line_16; - if ((w->wincon & FIMD_WINCON_BLD_PIX) && (w->wincon & - FIMD_WINCON_ALPHA_SEL)) { - w->pixel_to_rgb = pixel_4444_to_rgb; - } else { - w->pixel_to_rgb = pixel_a444_to_rgb; - } - break; - case 15: - w->draw_line = draw_line_16; - w->pixel_to_rgb = pixel_555_to_rgb; - break; - } -} - -#if EXYNOS4210_FIMD_MODE_TRACE > 0 -static const char *exynos4210_fimd_get_bppmode(int mode_code) -{ - switch (mode_code) { - case 0: - return "1 bpp"; - case 1: - return "2 bpp"; - case 2: - return "4 bpp"; - case 3: - return "8 bpp (palettized)"; - case 4: - return "8 bpp (non-palettized, A: 1-R:2-G:3-B:2)"; - case 5: - return "16 bpp (non-palettized, R:5-G:6-B:5)"; - case 6: - return "16 bpp (non-palettized, A:1-R:5-G:5-B:5)"; - case 7: - return "16 bpp (non-palettized, I :1-R:5-G:5-B:5)"; - case 8: - return "Unpacked 18 bpp (non-palettized, R:6-G:6-B:6)"; - case 9: - return "Unpacked 18bpp (non-palettized,A:1-R:6-G:6-B:5)"; - case 10: - return "Unpacked 19bpp (non-palettized,A:1-R:6-G:6-B:6)"; - case 11: - return "Unpacked 24 bpp (non-palettized R:8-G:8-B:8)"; - case 12: - return "Unpacked 24 bpp (non-palettized A:1-R:8-G:8-B:7)"; - case 13: - return "Unpacked 25 bpp (non-palettized A:1-R:8-G:8-B:8)"; - case 14: - return "Unpacked 13 bpp (non-palettized A:1-R:4-G:4-B:4)"; - case 15: - return "Unpacked 15 bpp (non-palettized R:5-G:5-B:5)"; - default: - return "Non-existing bpp mode"; - } -} - -static inline void exynos4210_fimd_trace_bppmode(Exynos4210fimdState *s, - int win_num, uint32_t val) -{ - Exynos4210fimdWindow *w = &s->window[win_num]; - - if (w->winmap & FIMD_WINMAP_EN) { - printf("QEMU FIMD: Window %d is mapped with MAPCOLOR=0x%x\n", - win_num, w->winmap & 0xFFFFFF); - return; - } - - if ((val != 0xFFFFFFFF) && ((w->wincon >> 2) & 0xF) == ((val >> 2) & 0xF)) { - return; - } - printf("QEMU FIMD: Window %d BPP mode set to %s\n", win_num, - exynos4210_fimd_get_bppmode((val >> 2) & 0xF)); -} -#else -static inline void exynos4210_fimd_trace_bppmode(Exynos4210fimdState *s, - int win_num, uint32_t val) -{ - -} -#endif - -static inline int fimd_get_buffer_id(Exynos4210fimdWindow *w) -{ - switch (w->wincon & FIMD_WINCON_BUFSTATUS) { - case FIMD_WINCON_BUF0_STAT: - return 0; - case FIMD_WINCON_BUF1_STAT: - return 1; - case FIMD_WINCON_BUF2_STAT: - return 2; - default: - DPRINT_ERROR("Non-existent buffer index\n"); - return 0; - } -} - -static void exynos4210_fimd_invalidate(void *opaque) -{ - Exynos4210fimdState *s = (Exynos4210fimdState *)opaque; - s->invalidate = true; -} - -/* Updates specified window's MemorySection based on values of WINCON, - * VIDOSDA, VIDOSDB, VIDWADDx and SHADOWCON registers */ -static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(s); - Exynos4210fimdWindow *w = &s->window[win]; - hwaddr fb_start_addr, fb_mapped_len; - - if (!s->enabled || !(w->wincon & FIMD_WINCON_ENWIN) || - FIMD_WINDOW_PROTECTED(s->shadowcon, win)) { - return; - } - - if (w->host_fb_addr) { - cpu_physical_memory_unmap(w->host_fb_addr, w->fb_len, 0, 0); - w->host_fb_addr = NULL; - w->fb_len = 0; - } - - fb_start_addr = w->buf_start[fimd_get_buffer_id(w)]; - /* Total number of bytes of virtual screen used by current window */ - w->fb_len = fb_mapped_len = (w->virtpage_width + w->virtpage_offsize) * - (w->rightbot_y - w->lefttop_y + 1); - - /* TODO: add .exit and unref the region there. Not needed yet since sysbus - * does not support hot-unplug. - */ - if (w->mem_section.mr) { - memory_region_set_log(w->mem_section.mr, false, DIRTY_MEMORY_VGA); - memory_region_unref(w->mem_section.mr); - } - - w->mem_section = memory_region_find(sysbus_address_space(sbd), - fb_start_addr, w->fb_len); - assert(w->mem_section.mr); - assert(w->mem_section.offset_within_address_space == fb_start_addr); - DPRINT_TRACE("Window %u framebuffer changed: address=0x%08x, len=0x%x\n", - win, fb_start_addr, w->fb_len); - - if (int128_get64(w->mem_section.size) != w->fb_len || - !memory_region_is_ram(w->mem_section.mr)) { - DPRINT_ERROR("Failed to find window %u framebuffer region\n", win); - goto error_return; - } - - w->host_fb_addr = cpu_physical_memory_map(fb_start_addr, &fb_mapped_len, 0); - if (!w->host_fb_addr) { - DPRINT_ERROR("Failed to map window %u framebuffer\n", win); - goto error_return; - } - - if (fb_mapped_len != w->fb_len) { - DPRINT_ERROR("Window %u mapped framebuffer length is less then " - "expected\n", win); - cpu_physical_memory_unmap(w->host_fb_addr, fb_mapped_len, 0, 0); - goto error_return; - } - memory_region_set_log(w->mem_section.mr, true, DIRTY_MEMORY_VGA); - exynos4210_fimd_invalidate(s); - return; - -error_return: - memory_region_unref(w->mem_section.mr); - w->mem_section.mr = NULL; - w->mem_section.size = int128_zero(); - w->host_fb_addr = NULL; - w->fb_len = 0; -} - -static void exynos4210_fimd_enable(Exynos4210fimdState *s, bool enabled) -{ - if (enabled && !s->enabled) { - unsigned w; - s->enabled = true; - for (w = 0; w < NUM_OF_WINDOWS; w++) { - fimd_update_memory_section(s, w); - } - } - s->enabled = enabled; - DPRINT_TRACE("display controller %s\n", enabled ? "enabled" : "disabled"); -} - -static inline uint32_t unpack_upper_4(uint32_t x) -{ - return ((x & 0xF00) << 12) | ((x & 0xF0) << 8) | ((x & 0xF) << 4); -} - -static inline uint32_t pack_upper_4(uint32_t x) -{ - return (((x & 0xF00000) >> 12) | ((x & 0xF000) >> 8) | - ((x & 0xF0) >> 4)) & 0xFFF; -} - -static void exynos4210_fimd_update_irq(Exynos4210fimdState *s) -{ - if (!(s->vidintcon[0] & FIMD_VIDINT_INTEN)) { - qemu_irq_lower(s->irq[0]); - qemu_irq_lower(s->irq[1]); - qemu_irq_lower(s->irq[2]); - return; - } - if ((s->vidintcon[0] & FIMD_VIDINT_INTFIFOEN) && - (s->vidintcon[1] & FIMD_VIDINT_INTFIFOPEND)) { - qemu_irq_raise(s->irq[0]); - } else { - qemu_irq_lower(s->irq[0]); - } - if ((s->vidintcon[0] & FIMD_VIDINT_INTFRMEN) && - (s->vidintcon[1] & FIMD_VIDINT_INTFRMPEND)) { - qemu_irq_raise(s->irq[1]); - } else { - qemu_irq_lower(s->irq[1]); - } - if ((s->vidintcon[0] & FIMD_VIDINT_I80IFDONE) && - (s->vidintcon[1] & FIMD_VIDINT_INTI80PEND)) { - qemu_irq_raise(s->irq[2]); - } else { - qemu_irq_lower(s->irq[2]); - } -} - -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 || surface_width(surface) != width || - surface_height(surface) != height) { - DPRINT_L1("Resolution changed from %ux%u to %ux%u\n", - 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); - exynos4210_fimd_invalidate(s); - } -} - -static void exynos4210_fimd_update(void *opaque) -{ - Exynos4210fimdState *s = (Exynos4210fimdState *)opaque; - DisplaySurface *surface; - Exynos4210fimdWindow *w; - int i, line; - hwaddr fb_line_addr, inc_size; - int scrn_height; - int first_line = -1, last_line = -1, scrn_width; - bool blend = false; - uint8_t *host_fb_addr; - bool is_dirty = false; - const int global_width = (s->vidtcon[2] & FIMD_VIDTCON2_SIZE_MASK) + 1; - const int global_height = ((s->vidtcon[2] >> FIMD_VIDTCON2_VER_SHIFT) & - FIMD_VIDTCON2_SIZE_MASK) + 1; - - if (!s || !s->console || !s->enabled || - surface_bits_per_pixel(qemu_console_surface(s->console)) == 0) { - return; - } - exynos4210_update_resolution(s); - surface = qemu_console_surface(s->console); - - for (i = 0; i < NUM_OF_WINDOWS; i++) { - w = &s->window[i]; - if ((w->wincon & FIMD_WINCON_ENWIN) && w->host_fb_addr) { - scrn_height = w->rightbot_y - w->lefttop_y + 1; - scrn_width = w->virtpage_width; - /* Total width of virtual screen page in bytes */ - inc_size = scrn_width + w->virtpage_offsize; - memory_region_sync_dirty_bitmap(w->mem_section.mr); - host_fb_addr = w->host_fb_addr; - fb_line_addr = w->mem_section.offset_within_region; - - for (line = 0; line < scrn_height; line++) { - is_dirty = memory_region_get_dirty(w->mem_section.mr, - fb_line_addr, scrn_width, DIRTY_MEMORY_VGA); - - if (s->invalidate || is_dirty) { - if (first_line == -1) { - first_line = line; - } - last_line = line; - w->draw_line(w, host_fb_addr, s->ifb + - w->lefttop_x * RGBA_SIZE + (w->lefttop_y + line) * - global_width * RGBA_SIZE, blend); - } - host_fb_addr += inc_size; - fb_line_addr += inc_size; - is_dirty = false; - } - memory_region_reset_dirty(w->mem_section.mr, - w->mem_section.offset_within_region, - w->fb_len, DIRTY_MEMORY_VGA); - blend = true; - } - } - - /* Copy resulting image to QEMU_CONSOLE. */ - if (first_line >= 0) { - uint8_t *d; - int bpp; - - bpp = surface_bits_per_pixel(surface); - fimd_update_putpix_qemu(bpp); - bpp = (bpp + 1) >> 3; - 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); - } - dpy_gfx_update(s->console, 0, 0, global_width, global_height); - } - s->invalidate = false; - s->vidintcon[1] |= FIMD_VIDINT_INTFRMPEND; - if ((s->vidcon[0] & FIMD_VIDCON0_ENVID_F) == 0) { - exynos4210_fimd_enable(s, false); - } - exynos4210_fimd_update_irq(s); -} - -static void exynos4210_fimd_reset(DeviceState *d) -{ - Exynos4210fimdState *s = EXYNOS4210_FIMD(d); - unsigned w; - - DPRINT_TRACE("Display controller reset\n"); - /* Set all display controller registers to 0 */ - memset(&s->vidcon, 0, (uint8_t *)&s->window - (uint8_t *)&s->vidcon); - for (w = 0; w < NUM_OF_WINDOWS; w++) { - memset(&s->window[w], 0, sizeof(Exynos4210fimdWindow)); - s->window[w].blendeq = 0xC2; - exynos4210_fimd_update_win_bppmode(s, w); - exynos4210_fimd_trace_bppmode(s, w, 0xFFFFFFFF); - fimd_update_get_alpha(s, w); - } - - g_free(s->ifb); - s->ifb = NULL; - - exynos4210_fimd_invalidate(s); - exynos4210_fimd_enable(s, false); - /* Some registers have non-zero initial values */ - s->winchmap = 0x7D517D51; - s->colorgaincon = 0x10040100; - s->huecoef_cr[0] = s->huecoef_cr[3] = 0x01000100; - s->huecoef_cb[0] = s->huecoef_cb[3] = 0x01000100; - s->hueoffset = 0x01800080; -} - -static void exynos4210_fimd_write(void *opaque, hwaddr offset, - uint64_t val, unsigned size) -{ - Exynos4210fimdState *s = (Exynos4210fimdState *)opaque; - unsigned w, i; - uint32_t old_value; - - DPRINT_L2("write offset 0x%08x, value=%llu(0x%08llx)\n", offset, - (long long unsigned int)val, (long long unsigned int)val); - - switch (offset) { - case FIMD_VIDCON0: - if ((val & FIMD_VIDCON0_ENVID_MASK) == FIMD_VIDCON0_ENVID_MASK) { - exynos4210_fimd_enable(s, true); - } else { - if ((val & FIMD_VIDCON0_ENVID) == 0) { - exynos4210_fimd_enable(s, false); - } - } - s->vidcon[0] = val; - break; - case FIMD_VIDCON1: - /* Leave read-only bits as is */ - val = (val & (~FIMD_VIDCON1_ROMASK)) | - (s->vidcon[1] & FIMD_VIDCON1_ROMASK); - s->vidcon[1] = val; - break; - case FIMD_VIDCON2 ... FIMD_VIDCON3: - s->vidcon[(offset) >> 2] = val; - break; - case FIMD_VIDTCON_START ... FIMD_VIDTCON_END: - s->vidtcon[(offset - FIMD_VIDTCON_START) >> 2] = val; - break; - case FIMD_WINCON_START ... FIMD_WINCON_END: - w = (offset - FIMD_WINCON_START) >> 2; - /* Window's current buffer ID */ - i = fimd_get_buffer_id(&s->window[w]); - old_value = s->window[w].wincon; - val = (val & ~FIMD_WINCON_ROMASK) | - (s->window[w].wincon & FIMD_WINCON_ROMASK); - if (w == 0) { - /* Window 0 wincon ALPHA_MUL bit must always be 0 */ - val &= ~FIMD_WINCON_ALPHA_MUL; - } - exynos4210_fimd_trace_bppmode(s, w, val); - switch (val & FIMD_WINCON_BUFSELECT) { - case FIMD_WINCON_BUF0_SEL: - val &= ~FIMD_WINCON_BUFSTATUS; - break; - case FIMD_WINCON_BUF1_SEL: - val = (val & ~FIMD_WINCON_BUFSTAT_H) | FIMD_WINCON_BUFSTAT_L; - break; - case FIMD_WINCON_BUF2_SEL: - if (val & FIMD_WINCON_BUFMODE) { - val = (val & ~FIMD_WINCON_BUFSTAT_L) | FIMD_WINCON_BUFSTAT_H; - } - break; - default: - break; - } - s->window[w].wincon = val; - exynos4210_fimd_update_win_bppmode(s, w); - fimd_update_get_alpha(s, w); - if ((i != fimd_get_buffer_id(&s->window[w])) || - (!(old_value & FIMD_WINCON_ENWIN) && (s->window[w].wincon & - FIMD_WINCON_ENWIN))) { - fimd_update_memory_section(s, w); - } - break; - case FIMD_SHADOWCON: - old_value = s->shadowcon; - s->shadowcon = val; - for (w = 0; w < NUM_OF_WINDOWS; w++) { - if (FIMD_WINDOW_PROTECTED(old_value, w) && - !FIMD_WINDOW_PROTECTED(s->shadowcon, w)) { - fimd_update_memory_section(s, w); - } - } - break; - case FIMD_WINCHMAP: - s->winchmap = val; - break; - case FIMD_VIDOSD_START ... FIMD_VIDOSD_END: - w = (offset - FIMD_VIDOSD_START) >> 4; - i = ((offset - FIMD_VIDOSD_START) & 0xF) >> 2; - switch (i) { - case 0: - old_value = s->window[w].lefttop_y; - s->window[w].lefttop_x = (val >> FIMD_VIDOSD_HOR_SHIFT) & - FIMD_VIDOSD_COORD_MASK; - s->window[w].lefttop_y = (val >> FIMD_VIDOSD_VER_SHIFT) & - FIMD_VIDOSD_COORD_MASK; - if (s->window[w].lefttop_y != old_value) { - fimd_update_memory_section(s, w); - } - break; - case 1: - old_value = s->window[w].rightbot_y; - s->window[w].rightbot_x = (val >> FIMD_VIDOSD_HOR_SHIFT) & - FIMD_VIDOSD_COORD_MASK; - s->window[w].rightbot_y = (val >> FIMD_VIDOSD_VER_SHIFT) & - FIMD_VIDOSD_COORD_MASK; - if (s->window[w].rightbot_y != old_value) { - fimd_update_memory_section(s, w); - } - break; - case 2: - if (w == 0) { - s->window[w].osdsize = val; - } else { - s->window[w].alpha_val[0] = - unpack_upper_4((val & FIMD_VIDOSD_ALPHA_AEN0) >> - FIMD_VIDOSD_AEN0_SHIFT) | - (s->window[w].alpha_val[0] & FIMD_VIDALPHA_ALPHA_LOWER); - s->window[w].alpha_val[1] = - unpack_upper_4(val & FIMD_VIDOSD_ALPHA_AEN1) | - (s->window[w].alpha_val[1] & FIMD_VIDALPHA_ALPHA_LOWER); - } - break; - case 3: - if (w != 1 && w != 2) { - DPRINT_ERROR("Bad write offset 0x%08x\n", offset); - return; - } - s->window[w].osdsize = val; - break; - } - break; - case FIMD_VIDWADD0_START ... FIMD_VIDWADD0_END: - w = (offset - FIMD_VIDWADD0_START) >> 3; - i = ((offset - FIMD_VIDWADD0_START) >> 2) & 1; - if (i == fimd_get_buffer_id(&s->window[w]) && - s->window[w].buf_start[i] != val) { - s->window[w].buf_start[i] = val; - fimd_update_memory_section(s, w); - break; - } - s->window[w].buf_start[i] = val; - break; - case FIMD_VIDWADD1_START ... FIMD_VIDWADD1_END: - w = (offset - FIMD_VIDWADD1_START) >> 3; - i = ((offset - FIMD_VIDWADD1_START) >> 2) & 1; - s->window[w].buf_end[i] = val; - break; - case FIMD_VIDWADD2_START ... FIMD_VIDWADD2_END: - w = (offset - FIMD_VIDWADD2_START) >> 2; - if (((val & FIMD_VIDWADD2_PAGEWIDTH) != s->window[w].virtpage_width) || - (((val >> FIMD_VIDWADD2_OFFSIZE_SHIFT) & FIMD_VIDWADD2_OFFSIZE) != - s->window[w].virtpage_offsize)) { - s->window[w].virtpage_width = val & FIMD_VIDWADD2_PAGEWIDTH; - s->window[w].virtpage_offsize = - (val >> FIMD_VIDWADD2_OFFSIZE_SHIFT) & FIMD_VIDWADD2_OFFSIZE; - fimd_update_memory_section(s, w); - } - break; - case FIMD_VIDINTCON0: - s->vidintcon[0] = val; - break; - case FIMD_VIDINTCON1: - s->vidintcon[1] &= ~(val & 7); - exynos4210_fimd_update_irq(s); - break; - case FIMD_WKEYCON_START ... FIMD_WKEYCON_END: - w = ((offset - FIMD_WKEYCON_START) >> 3) + 1; - i = ((offset - FIMD_WKEYCON_START) >> 2) & 1; - s->window[w].keycon[i] = val; - break; - case FIMD_WKEYALPHA_START ... FIMD_WKEYALPHA_END: - w = ((offset - FIMD_WKEYALPHA_START) >> 2) + 1; - s->window[w].keyalpha = val; - break; - case FIMD_DITHMODE: - s->dithmode = val; - break; - case FIMD_WINMAP_START ... FIMD_WINMAP_END: - w = (offset - FIMD_WINMAP_START) >> 2; - old_value = s->window[w].winmap; - s->window[w].winmap = val; - if ((val & FIMD_WINMAP_EN) ^ (old_value & FIMD_WINMAP_EN)) { - exynos4210_fimd_invalidate(s); - exynos4210_fimd_update_win_bppmode(s, w); - exynos4210_fimd_trace_bppmode(s, w, 0xFFFFFFFF); - exynos4210_fimd_update(s); - } - break; - case FIMD_WPALCON_HIGH ... FIMD_WPALCON_LOW: - i = (offset - FIMD_WPALCON_HIGH) >> 2; - s->wpalcon[i] = val; - if (s->wpalcon[1] & FIMD_WPALCON_UPDATEEN) { - for (w = 0; w < NUM_OF_WINDOWS; w++) { - exynos4210_fimd_update_win_bppmode(s, w); - fimd_update_get_alpha(s, w); - } - } - break; - case FIMD_TRIGCON: - val = (val & ~FIMD_TRIGCON_ROMASK) | (s->trigcon & FIMD_TRIGCON_ROMASK); - s->trigcon = val; - break; - case FIMD_I80IFCON_START ... FIMD_I80IFCON_END: - s->i80ifcon[(offset - FIMD_I80IFCON_START) >> 2] = val; - break; - case FIMD_COLORGAINCON: - s->colorgaincon = val; - break; - case FIMD_LDI_CMDCON0 ... FIMD_LDI_CMDCON1: - s->ldi_cmdcon[(offset - FIMD_LDI_CMDCON0) >> 2] = val; - break; - case FIMD_SIFCCON0 ... FIMD_SIFCCON2: - i = (offset - FIMD_SIFCCON0) >> 2; - if (i != 2) { - s->sifccon[i] = val; - } - break; - case FIMD_HUECOEFCR_START ... FIMD_HUECOEFCR_END: - i = (offset - FIMD_HUECOEFCR_START) >> 2; - s->huecoef_cr[i] = val; - break; - case FIMD_HUECOEFCB_START ... FIMD_HUECOEFCB_END: - i = (offset - FIMD_HUECOEFCB_START) >> 2; - s->huecoef_cb[i] = val; - break; - case FIMD_HUEOFFSET: - s->hueoffset = val; - break; - case FIMD_VIDWALPHA_START ... FIMD_VIDWALPHA_END: - w = ((offset - FIMD_VIDWALPHA_START) >> 3); - i = ((offset - FIMD_VIDWALPHA_START) >> 2) & 1; - if (w == 0) { - s->window[w].alpha_val[i] = val; - } else { - s->window[w].alpha_val[i] = (val & FIMD_VIDALPHA_ALPHA_LOWER) | - (s->window[w].alpha_val[i] & FIMD_VIDALPHA_ALPHA_UPPER); - } - break; - case FIMD_BLENDEQ_START ... FIMD_BLENDEQ_END: - s->window[(offset - FIMD_BLENDEQ_START) >> 2].blendeq = val; - break; - case FIMD_BLENDCON: - old_value = s->blendcon; - s->blendcon = val; - if ((s->blendcon & FIMD_ALPHA_8BIT) != (old_value & FIMD_ALPHA_8BIT)) { - for (w = 0; w < NUM_OF_WINDOWS; w++) { - fimd_update_get_alpha(s, w); - } - } - break; - case FIMD_WRTQOSCON_START ... FIMD_WRTQOSCON_END: - s->window[(offset - FIMD_WRTQOSCON_START) >> 2].rtqoscon = val; - break; - case FIMD_I80IFCMD_START ... FIMD_I80IFCMD_END: - s->i80ifcmd[(offset - FIMD_I80IFCMD_START) >> 2] = val; - break; - case FIMD_VIDW0ADD0_B2 ... FIMD_VIDW4ADD0_B2: - if (offset & 0x0004) { - DPRINT_ERROR("bad write offset 0x%08x\n", offset); - break; - } - w = (offset - FIMD_VIDW0ADD0_B2) >> 3; - if (fimd_get_buffer_id(&s->window[w]) == 2 && - s->window[w].buf_start[2] != val) { - s->window[w].buf_start[2] = val; - fimd_update_memory_section(s, w); - break; - } - s->window[w].buf_start[2] = val; - break; - case FIMD_SHD_ADD0_START ... FIMD_SHD_ADD0_END: - if (offset & 0x0004) { - DPRINT_ERROR("bad write offset 0x%08x\n", offset); - break; - } - s->window[(offset - FIMD_SHD_ADD0_START) >> 3].shadow_buf_start = val; - break; - case FIMD_SHD_ADD1_START ... FIMD_SHD_ADD1_END: - if (offset & 0x0004) { - DPRINT_ERROR("bad write offset 0x%08x\n", offset); - break; - } - s->window[(offset - FIMD_SHD_ADD1_START) >> 3].shadow_buf_end = val; - break; - case FIMD_SHD_ADD2_START ... FIMD_SHD_ADD2_END: - s->window[(offset - FIMD_SHD_ADD2_START) >> 2].shadow_buf_size = val; - break; - case FIMD_PAL_MEM_START ... FIMD_PAL_MEM_END: - w = (offset - FIMD_PAL_MEM_START) >> 10; - i = ((offset - FIMD_PAL_MEM_START) >> 2) & 0xFF; - s->window[w].palette[i] = val; - break; - case FIMD_PALMEM_AL_START ... FIMD_PALMEM_AL_END: - /* Palette memory aliases for windows 0 and 1 */ - w = (offset - FIMD_PALMEM_AL_START) >> 10; - i = ((offset - FIMD_PALMEM_AL_START) >> 2) & 0xFF; - s->window[w].palette[i] = val; - break; - default: - DPRINT_ERROR("bad write offset 0x%08x\n", offset); - break; - } -} - -static uint64_t exynos4210_fimd_read(void *opaque, hwaddr offset, - unsigned size) -{ - Exynos4210fimdState *s = (Exynos4210fimdState *)opaque; - int w, i; - uint32_t ret = 0; - - DPRINT_L2("read offset 0x%08x\n", offset); - - switch (offset) { - case FIMD_VIDCON0 ... FIMD_VIDCON3: - return s->vidcon[(offset - FIMD_VIDCON0) >> 2]; - case FIMD_VIDTCON_START ... FIMD_VIDTCON_END: - return s->vidtcon[(offset - FIMD_VIDTCON_START) >> 2]; - case FIMD_WINCON_START ... FIMD_WINCON_END: - return s->window[(offset - FIMD_WINCON_START) >> 2].wincon; - case FIMD_SHADOWCON: - return s->shadowcon; - case FIMD_WINCHMAP: - return s->winchmap; - case FIMD_VIDOSD_START ... FIMD_VIDOSD_END: - w = (offset - FIMD_VIDOSD_START) >> 4; - i = ((offset - FIMD_VIDOSD_START) & 0xF) >> 2; - switch (i) { - case 0: - ret = ((s->window[w].lefttop_x & FIMD_VIDOSD_COORD_MASK) << - FIMD_VIDOSD_HOR_SHIFT) | - (s->window[w].lefttop_y & FIMD_VIDOSD_COORD_MASK); - break; - case 1: - ret = ((s->window[w].rightbot_x & FIMD_VIDOSD_COORD_MASK) << - FIMD_VIDOSD_HOR_SHIFT) | - (s->window[w].rightbot_y & FIMD_VIDOSD_COORD_MASK); - break; - case 2: - if (w == 0) { - ret = s->window[w].osdsize; - } else { - ret = (pack_upper_4(s->window[w].alpha_val[0]) << - FIMD_VIDOSD_AEN0_SHIFT) | - pack_upper_4(s->window[w].alpha_val[1]); - } - break; - case 3: - if (w != 1 && w != 2) { - DPRINT_ERROR("bad read offset 0x%08x\n", offset); - return 0xBAADBAAD; - } - ret = s->window[w].osdsize; - break; - } - return ret; - case FIMD_VIDWADD0_START ... FIMD_VIDWADD0_END: - w = (offset - FIMD_VIDWADD0_START) >> 3; - i = ((offset - FIMD_VIDWADD0_START) >> 2) & 1; - return s->window[w].buf_start[i]; - case FIMD_VIDWADD1_START ... FIMD_VIDWADD1_END: - w = (offset - FIMD_VIDWADD1_START) >> 3; - i = ((offset - FIMD_VIDWADD1_START) >> 2) & 1; - return s->window[w].buf_end[i]; - case FIMD_VIDWADD2_START ... FIMD_VIDWADD2_END: - w = (offset - FIMD_VIDWADD2_START) >> 2; - return s->window[w].virtpage_width | (s->window[w].virtpage_offsize << - FIMD_VIDWADD2_OFFSIZE_SHIFT); - case FIMD_VIDINTCON0 ... FIMD_VIDINTCON1: - return s->vidintcon[(offset - FIMD_VIDINTCON0) >> 2]; - case FIMD_WKEYCON_START ... FIMD_WKEYCON_END: - w = ((offset - FIMD_WKEYCON_START) >> 3) + 1; - i = ((offset - FIMD_WKEYCON_START) >> 2) & 1; - return s->window[w].keycon[i]; - case FIMD_WKEYALPHA_START ... FIMD_WKEYALPHA_END: - w = ((offset - FIMD_WKEYALPHA_START) >> 2) + 1; - return s->window[w].keyalpha; - case FIMD_DITHMODE: - return s->dithmode; - case FIMD_WINMAP_START ... FIMD_WINMAP_END: - return s->window[(offset - FIMD_WINMAP_START) >> 2].winmap; - case FIMD_WPALCON_HIGH ... FIMD_WPALCON_LOW: - return s->wpalcon[(offset - FIMD_WPALCON_HIGH) >> 2]; - case FIMD_TRIGCON: - return s->trigcon; - case FIMD_I80IFCON_START ... FIMD_I80IFCON_END: - return s->i80ifcon[(offset - FIMD_I80IFCON_START) >> 2]; - case FIMD_COLORGAINCON: - return s->colorgaincon; - case FIMD_LDI_CMDCON0 ... FIMD_LDI_CMDCON1: - return s->ldi_cmdcon[(offset - FIMD_LDI_CMDCON0) >> 2]; - case FIMD_SIFCCON0 ... FIMD_SIFCCON2: - i = (offset - FIMD_SIFCCON0) >> 2; - return s->sifccon[i]; - case FIMD_HUECOEFCR_START ... FIMD_HUECOEFCR_END: - i = (offset - FIMD_HUECOEFCR_START) >> 2; - return s->huecoef_cr[i]; - case FIMD_HUECOEFCB_START ... FIMD_HUECOEFCB_END: - i = (offset - FIMD_HUECOEFCB_START) >> 2; - return s->huecoef_cb[i]; - case FIMD_HUEOFFSET: - return s->hueoffset; - case FIMD_VIDWALPHA_START ... FIMD_VIDWALPHA_END: - w = ((offset - FIMD_VIDWALPHA_START) >> 3); - i = ((offset - FIMD_VIDWALPHA_START) >> 2) & 1; - return s->window[w].alpha_val[i] & - (w == 0 ? 0xFFFFFF : FIMD_VIDALPHA_ALPHA_LOWER); - case FIMD_BLENDEQ_START ... FIMD_BLENDEQ_END: - return s->window[(offset - FIMD_BLENDEQ_START) >> 2].blendeq; - case FIMD_BLENDCON: - return s->blendcon; - case FIMD_WRTQOSCON_START ... FIMD_WRTQOSCON_END: - return s->window[(offset - FIMD_WRTQOSCON_START) >> 2].rtqoscon; - case FIMD_I80IFCMD_START ... FIMD_I80IFCMD_END: - return s->i80ifcmd[(offset - FIMD_I80IFCMD_START) >> 2]; - case FIMD_VIDW0ADD0_B2 ... FIMD_VIDW4ADD0_B2: - if (offset & 0x0004) { - break; - } - return s->window[(offset - FIMD_VIDW0ADD0_B2) >> 3].buf_start[2]; - case FIMD_SHD_ADD0_START ... FIMD_SHD_ADD0_END: - if (offset & 0x0004) { - break; - } - return s->window[(offset - FIMD_SHD_ADD0_START) >> 3].shadow_buf_start; - case FIMD_SHD_ADD1_START ... FIMD_SHD_ADD1_END: - if (offset & 0x0004) { - break; - } - return s->window[(offset - FIMD_SHD_ADD1_START) >> 3].shadow_buf_end; - case FIMD_SHD_ADD2_START ... FIMD_SHD_ADD2_END: - return s->window[(offset - FIMD_SHD_ADD2_START) >> 2].shadow_buf_size; - case FIMD_PAL_MEM_START ... FIMD_PAL_MEM_END: - w = (offset - FIMD_PAL_MEM_START) >> 10; - i = ((offset - FIMD_PAL_MEM_START) >> 2) & 0xFF; - return s->window[w].palette[i]; - case FIMD_PALMEM_AL_START ... FIMD_PALMEM_AL_END: - /* Palette aliases for win 0,1 */ - w = (offset - FIMD_PALMEM_AL_START) >> 10; - i = ((offset - FIMD_PALMEM_AL_START) >> 2) & 0xFF; - return s->window[w].palette[i]; - } - - DPRINT_ERROR("bad read offset 0x%08x\n", offset); - return 0xBAADBAAD; -} - -static const MemoryRegionOps exynos4210_fimd_mmio_ops = { - .read = exynos4210_fimd_read, - .write = exynos4210_fimd_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - .unaligned = false - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static int exynos4210_fimd_load(void *opaque, int version_id) -{ - Exynos4210fimdState *s = (Exynos4210fimdState *)opaque; - int w; - - if (version_id != 1) { - return -EINVAL; - } - - for (w = 0; w < NUM_OF_WINDOWS; w++) { - exynos4210_fimd_update_win_bppmode(s, w); - fimd_update_get_alpha(s, w); - fimd_update_memory_section(s, w); - } - - /* Redraw the whole screen */ - exynos4210_update_resolution(s); - exynos4210_fimd_invalidate(s); - exynos4210_fimd_enable(s, (s->vidcon[0] & FIMD_VIDCON0_ENVID_MASK) == - FIMD_VIDCON0_ENVID_MASK); - return 0; -} - -static const VMStateDescription exynos4210_fimd_window_vmstate = { - .name = "exynos4210.fimd_window", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(wincon, Exynos4210fimdWindow), - VMSTATE_UINT32_ARRAY(buf_start, Exynos4210fimdWindow, 3), - VMSTATE_UINT32_ARRAY(buf_end, Exynos4210fimdWindow, 3), - VMSTATE_UINT32_ARRAY(keycon, Exynos4210fimdWindow, 2), - VMSTATE_UINT32(keyalpha, Exynos4210fimdWindow), - VMSTATE_UINT32(winmap, Exynos4210fimdWindow), - VMSTATE_UINT32(blendeq, Exynos4210fimdWindow), - VMSTATE_UINT32(rtqoscon, Exynos4210fimdWindow), - VMSTATE_UINT32_ARRAY(palette, Exynos4210fimdWindow, 256), - VMSTATE_UINT32(shadow_buf_start, Exynos4210fimdWindow), - VMSTATE_UINT32(shadow_buf_end, Exynos4210fimdWindow), - VMSTATE_UINT32(shadow_buf_size, Exynos4210fimdWindow), - VMSTATE_UINT16(lefttop_x, Exynos4210fimdWindow), - VMSTATE_UINT16(lefttop_y, Exynos4210fimdWindow), - VMSTATE_UINT16(rightbot_x, Exynos4210fimdWindow), - VMSTATE_UINT16(rightbot_y, Exynos4210fimdWindow), - VMSTATE_UINT32(osdsize, Exynos4210fimdWindow), - VMSTATE_UINT32_ARRAY(alpha_val, Exynos4210fimdWindow, 2), - VMSTATE_UINT16(virtpage_width, Exynos4210fimdWindow), - VMSTATE_UINT16(virtpage_offsize, Exynos4210fimdWindow), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription exynos4210_fimd_vmstate = { - .name = "exynos4210.fimd", - .version_id = 1, - .minimum_version_id = 1, - .post_load = exynos4210_fimd_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(vidcon, Exynos4210fimdState, 4), - VMSTATE_UINT32_ARRAY(vidtcon, Exynos4210fimdState, 4), - VMSTATE_UINT32(shadowcon, Exynos4210fimdState), - VMSTATE_UINT32(winchmap, Exynos4210fimdState), - VMSTATE_UINT32_ARRAY(vidintcon, Exynos4210fimdState, 2), - VMSTATE_UINT32(dithmode, Exynos4210fimdState), - VMSTATE_UINT32_ARRAY(wpalcon, Exynos4210fimdState, 2), - VMSTATE_UINT32(trigcon, Exynos4210fimdState), - VMSTATE_UINT32_ARRAY(i80ifcon, Exynos4210fimdState, 4), - VMSTATE_UINT32(colorgaincon, Exynos4210fimdState), - VMSTATE_UINT32_ARRAY(ldi_cmdcon, Exynos4210fimdState, 2), - VMSTATE_UINT32_ARRAY(sifccon, Exynos4210fimdState, 3), - VMSTATE_UINT32_ARRAY(huecoef_cr, Exynos4210fimdState, 4), - VMSTATE_UINT32_ARRAY(huecoef_cb, Exynos4210fimdState, 4), - VMSTATE_UINT32(hueoffset, Exynos4210fimdState), - VMSTATE_UINT32_ARRAY(i80ifcmd, Exynos4210fimdState, 12), - VMSTATE_UINT32(blendcon, Exynos4210fimdState), - VMSTATE_STRUCT_ARRAY(window, Exynos4210fimdState, 5, 1, - exynos4210_fimd_window_vmstate, Exynos4210fimdWindow), - VMSTATE_END_OF_LIST() - } -}; - -static const GraphicHwOps exynos4210_fimd_ops = { - .invalidate = exynos4210_fimd_invalidate, - .gfx_update = exynos4210_fimd_update, -}; - -static int exynos4210_fimd_init(SysBusDevice *dev) -{ - Exynos4210fimdState *s = EXYNOS4210_FIMD(dev); - - s->ifb = NULL; - - sysbus_init_irq(dev, &s->irq[0]); - sysbus_init_irq(dev, &s->irq[1]); - sysbus_init_irq(dev, &s->irq[2]); - - memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_fimd_mmio_ops, s, - "exynos4210.fimd", FIMD_REGS_SIZE); - sysbus_init_mmio(dev, &s->iomem); - s->console = graphic_console_init(DEVICE(dev), 0, &exynos4210_fimd_ops, s); - - return 0; -} - -static void exynos4210_fimd_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - dc->vmsd = &exynos4210_fimd_vmstate; - dc->reset = exynos4210_fimd_reset; - k->init = exynos4210_fimd_init; -} - -static const TypeInfo exynos4210_fimd_info = { - .name = TYPE_EXYNOS4210_FIMD, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(Exynos4210fimdState), - .class_init = exynos4210_fimd_class_init, -}; - -static void exynos4210_fimd_register_types(void) -{ - type_register_static(&exynos4210_fimd_info); -} - -type_init(exynos4210_fimd_register_types) diff --git a/qemu/hw/display/framebuffer.c b/qemu/hw/display/framebuffer.c deleted file mode 100644 index df51358e7..000000000 --- a/qemu/hw/display/framebuffer.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Framebuffer device helper routines - * - * Copyright (c) 2009 CodeSourcery - * Written by Paul Brook - * - * This code is licensed under the GNU GPLv2. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -/* TODO: - - Do something similar for framebuffers with local ram - - Handle rotation here instead of hacking dest_pitch - - Use common pixel conversion routines instead of per-device drawfn - - Remove all DisplayState knowledge from devices. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "ui/console.h" -#include "framebuffer.h" - -void framebuffer_update_memory_section( - MemoryRegionSection *mem_section, - MemoryRegion *root, - hwaddr base, - unsigned rows, - unsigned src_width) -{ - hwaddr src_len = (hwaddr)rows * src_width; - - if (mem_section->mr) { - memory_region_set_log(mem_section->mr, false, DIRTY_MEMORY_VGA); - memory_region_unref(mem_section->mr); - mem_section->mr = NULL; - } - - *mem_section = memory_region_find(root, base, src_len); - if (!mem_section->mr) { - return; - } - - if (int128_get64(mem_section->size) < src_len || - !memory_region_is_ram(mem_section->mr)) { - memory_region_unref(mem_section->mr); - mem_section->mr = NULL; - return; - } - - memory_region_set_log(mem_section->mr, true, DIRTY_MEMORY_VGA); -} - -/* Render an image from a shared memory framebuffer. */ -void framebuffer_update_display( - DisplaySurface *ds, - MemoryRegionSection *mem_section, - int cols, /* Width in pixels. */ - int rows, /* Height in pixels. */ - int src_width, /* Length of source line, in bytes. */ - int dest_row_pitch, /* Bytes between adjacent horizontal output pixels. */ - int dest_col_pitch, /* Bytes between adjacent vertical output pixels. */ - int invalidate, /* nonzero to redraw the whole image. */ - drawfn fn, - void *opaque, - int *first_row, /* Input and output. */ - int *last_row /* Output only */) -{ - hwaddr src_len; - uint8_t *dest; - uint8_t *src; - int first, last = 0; - int dirty; - int i; - ram_addr_t addr; - MemoryRegion *mem; - - i = *first_row; - *first_row = -1; - src_len = src_width * rows; - - mem = mem_section->mr; - if (!mem) { - return; - } - memory_region_sync_dirty_bitmap(mem); - - addr = mem_section->offset_within_region; - src = memory_region_get_ram_ptr(mem) + addr; - - dest = surface_data(ds); - if (dest_col_pitch < 0) { - dest -= dest_col_pitch * (cols - 1); - } - if (dest_row_pitch < 0) { - dest -= dest_row_pitch * (rows - 1); - } - first = -1; - - addr += i * src_width; - src += i * src_width; - dest += i * dest_row_pitch; - - for (; i < rows; i++) { - dirty = memory_region_get_dirty(mem, addr, src_width, - DIRTY_MEMORY_VGA); - if (dirty || invalidate) { - fn(opaque, dest, src, cols, dest_col_pitch); - if (first == -1) - first = i; - last = i; - } - addr += src_width; - src += src_width; - dest += dest_row_pitch; - } - if (first < 0) { - return; - } - memory_region_reset_dirty(mem, mem_section->offset_within_region, src_len, - DIRTY_MEMORY_VGA); - *first_row = first; - *last_row = last; -} diff --git a/qemu/hw/display/framebuffer.h b/qemu/hw/display/framebuffer.h deleted file mode 100644 index 38fa0dcec..000000000 --- a/qemu/hw/display/framebuffer.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef QEMU_FRAMEBUFFER_H -#define QEMU_FRAMEBUFFER_H - -#include "exec/memory.h" - -/* Framebuffer device helper routines. */ - -typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int); - -/* framebuffer_update_memory_section: Update framebuffer - * #MemoryRegionSection, for example if the framebuffer is switched to - * a different memory area. - * - * @mem_section: Output #MemoryRegionSection, to be passed to - * framebuffer_update_display(). - * @root: #MemoryRegion within which the framebuffer lies - * @base: Base address of the framebuffer within @root. - * @rows: Height of the screen. - * @src_width: Number of bytes in framebuffer memory between two rows. - */ -void framebuffer_update_memory_section( - MemoryRegionSection *mem_section, - MemoryRegion *root, - hwaddr base, - unsigned rows, - unsigned src_width); - -/* framebuffer_update_display: Draw the framebuffer on a surface. - * - * @ds: #DisplaySurface to draw to. - * @mem_section: #MemoryRegionSection provided by - * framebuffer_update_memory_section(). - * @cols: Width the screen. - * @rows: Height of the screen. - * @src_width: Number of bytes in framebuffer memory between two rows. - * @dest_row_pitch: Number of bytes in the surface data between two rows. - * Negative if the framebuffer is stored in the opposite order (e.g. - * bottom-to-top) compared to the framebuffer. - * @dest_col_pitch: Number of bytes in the surface data between two pixels. - * Negative if the framebuffer is stored in the opposite order (e.g. - * right-to-left) compared to the framebuffer. - * @invalidate: True if the function should redraw the whole screen - * without checking the DIRTY_MEMORY_VGA dirty bitmap. - * @fn: Drawing function to be called for each row that has to be drawn. - * @opaque: Opaque pointer passed to @fn. - * @first_row: Pointer to an integer, receives the number of the first row - * that was drawn (either the first dirty row, or 0 if @invalidate is true). - * @last_row: Pointer to an integer, receives the number of the last row that - * was drawn (either the last dirty row, or @rows-1 if @invalidate is true). - */ -void framebuffer_update_display( - DisplaySurface *ds, - MemoryRegionSection *mem_section, - int cols, - int rows, - int src_width, - int dest_row_pitch, - int dest_col_pitch, - int invalidate, - drawfn fn, - void *opaque, - int *first_row, - int *last_row); - -#endif diff --git a/qemu/hw/display/g364fb.c b/qemu/hw/display/g364fb.c deleted file mode 100644 index 70ef2c745..000000000 --- a/qemu/hw/display/g364fb.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * QEMU G364 framebuffer Emulator. - * - * Copyright (c) 2007-2011 Herve Poussineau - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "qemu/error-report.h" -#include "ui/console.h" -#include "ui/pixel_ops.h" -#include "trace.h" -#include "hw/sysbus.h" - -typedef struct G364State { - /* hardware */ - uint8_t *vram; - uint32_t vram_size; - qemu_irq irq; - MemoryRegion mem_vram; - MemoryRegion mem_ctrl; - /* registers */ - uint8_t color_palette[256][3]; - uint8_t cursor_palette[3][3]; - uint16_t cursor[512]; - uint32_t cursor_position; - uint32_t ctla; - uint32_t top_of_screen; - uint32_t width, height; /* in pixels */ - /* display refresh support */ - QemuConsole *con; - int depth; - int blanked; -} G364State; - -#define REG_BOOT 0x000000 -#define REG_DISPLAY 0x000118 -#define REG_VDISPLAY 0x000150 -#define REG_CTLA 0x000300 -#define REG_TOP 0x000400 -#define REG_CURS_PAL 0x000508 -#define REG_CURS_POS 0x000638 -#define REG_CLR_PAL 0x000800 -#define REG_CURS_PAT 0x001000 -#define REG_RESET 0x100000 - -#define CTLA_FORCE_BLANK 0x00000400 -#define CTLA_NO_CURSOR 0x00800000 - -#define G364_PAGE_SIZE 4096 - -static inline int check_dirty(G364State *s, ram_addr_t page) -{ - return memory_region_get_dirty(&s->mem_vram, page, G364_PAGE_SIZE, - DIRTY_MEMORY_VGA); -} - -static inline void reset_dirty(G364State *s, - ram_addr_t page_min, ram_addr_t page_max) -{ - memory_region_reset_dirty(&s->mem_vram, - page_min, - page_max + G364_PAGE_SIZE - page_min - 1, - DIRTY_MEMORY_VGA); -} - -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; - ram_addr_t page, page_min, page_max; - int x, y; - int xmin, xmax; - int ymin, ymax; - int xcursor, ycursor; - unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned int b); - - switch (surface_bits_per_pixel(surface)) { - case 8: - rgb_to_pixel = rgb_to_pixel8; - w = 1; - break; - case 15: - rgb_to_pixel = rgb_to_pixel15; - w = 2; - break; - case 16: - rgb_to_pixel = rgb_to_pixel16; - w = 2; - break; - case 32: - rgb_to_pixel = rgb_to_pixel32; - w = 4; - break; - default: - hw_error("g364: unknown host depth %d", - surface_bits_per_pixel(surface)); - return; - } - - page = 0; - page_min = (ram_addr_t)-1; - page_max = 0; - - x = y = 0; - xmin = s->width; - xmax = 0; - ymin = s->height; - ymax = 0; - - if (!(s->ctla & CTLA_NO_CURSOR)) { - xcursor = s->cursor_position >> 12; - ycursor = s->cursor_position & 0xfff; - } else { - xcursor = ycursor = -65; - } - - vram = s->vram + s->top_of_screen; - /* XXX: out of range in vram? */ - data_display = dd = surface_data(surface); - while (y < s->height) { - if (check_dirty(s, page)) { - if (y < ymin) - ymin = ymax = y; - if (page_min == (ram_addr_t)-1) - page_min = page; - page_max = page; - if (x < xmin) - xmin = x; - for (i = 0; i < G364_PAGE_SIZE; i++) { - uint8_t index; - unsigned int color; - if (unlikely((y >= ycursor && y < ycursor + 64) && - (x >= xcursor && x < xcursor + 64))) { - /* pointer area */ - int xdiff = x - xcursor; - uint16_t curs = s->cursor[(y - ycursor) * 8 + xdiff / 8]; - int op = (curs >> ((xdiff & 7) * 2)) & 3; - if (likely(op == 0)) { - /* transparent */ - index = *vram; - color = (*rgb_to_pixel)( - s->color_palette[index][0], - s->color_palette[index][1], - s->color_palette[index][2]); - } else { - /* get cursor color */ - index = op - 1; - color = (*rgb_to_pixel)( - s->cursor_palette[index][0], - s->cursor_palette[index][1], - s->cursor_palette[index][2]); - } - } else { - /* normal area */ - index = *vram; - color = (*rgb_to_pixel)( - s->color_palette[index][0], - s->color_palette[index][1], - s->color_palette[index][2]); - } - memcpy(dd, &color, w); - dd += w; - x++; - vram++; - if (x == s->width) { - xmax = s->width - 1; - y++; - if (y == s->height) { - ymax = s->height - 1; - goto done; - } - data_display = dd = data_display + surface_stride(surface); - xmin = 0; - x = 0; - } - } - if (x > xmax) - xmax = x; - if (y > ymax) - ymax = y; - } else { - int dy; - if (page_min != (ram_addr_t)-1) { - reset_dirty(s, page_min, page_max); - page_min = (ram_addr_t)-1; - page_max = 0; - dpy_gfx_update(s->con, xmin, ymin, - xmax - xmin + 1, ymax - ymin + 1); - xmin = s->width; - xmax = 0; - ymin = s->height; - ymax = 0; - } - x += G364_PAGE_SIZE; - dy = x / s->width; - x = x % s->width; - y += dy; - vram += G364_PAGE_SIZE; - data_display += dy * surface_stride(surface); - dd = data_display + x * w; - } - page += G364_PAGE_SIZE; - } - -done: - if (page_min != (ram_addr_t)-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; - - if (s->blanked) { - /* Screen is already blank. No need to redraw it */ - return; - } - - w = s->width * surface_bytes_per_pixel(surface); - d = surface_data(surface); - for (i = 0; i < s->height; i++) { - memset(d, 0, w); - d += surface_stride(surface); - } - - 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 != surface_width(surface) || - s->height != surface_height(surface)) { - qemu_console_resize(s->con, s->width, s->height); - } - - memory_region_sync_dirty_bitmap(&s->mem_vram); - if (s->ctla & CTLA_FORCE_BLANK) { - g364fb_draw_blank(s); - } else if (s->depth == 8) { - g364fb_draw_graphic8(s); - } else { - error_report("g364: unknown guest depth %d", s->depth); - } - - qemu_irq_raise(s->irq); -} - -static inline void g364fb_invalidate_display(void *opaque) -{ - G364State *s = opaque; - - s->blanked = 0; - memory_region_set_dirty(&s->mem_vram, 0, s->vram_size); -} - -static void g364fb_reset(G364State *s) -{ - qemu_irq_lower(s->irq); - - memset(s->color_palette, 0, sizeof(s->color_palette)); - memset(s->cursor_palette, 0, sizeof(s->cursor_palette)); - memset(s->cursor, 0, sizeof(s->cursor)); - s->cursor_position = 0; - s->ctla = 0; - s->top_of_screen = 0; - s->width = s->height = 0; - memset(s->vram, 0, s->vram_size); - g364fb_invalidate_display(s); -} - -/* called for accesses to io ports */ -static uint64_t g364fb_ctrl_read(void *opaque, - hwaddr addr, - unsigned int size) -{ - G364State *s = opaque; - uint32_t val; - - if (addr >= REG_CURS_PAT && addr < REG_CURS_PAT + 0x1000) { - /* cursor pattern */ - int idx = (addr - REG_CURS_PAT) >> 3; - val = s->cursor[idx]; - } else if (addr >= REG_CURS_PAL && addr < REG_CURS_PAL + 0x18) { - /* cursor palette */ - int idx = (addr - REG_CURS_PAL) >> 3; - val = ((uint32_t)s->cursor_palette[idx][0] << 16); - val |= ((uint32_t)s->cursor_palette[idx][1] << 8); - val |= ((uint32_t)s->cursor_palette[idx][2] << 0); - } else { - switch (addr) { - case REG_DISPLAY: - val = s->width / 4; - break; - case REG_VDISPLAY: - val = s->height * 2; - break; - case REG_CTLA: - val = s->ctla; - break; - default: - { - error_report("g364: invalid read at [" TARGET_FMT_plx "]", - addr); - val = 0; - break; - } - } - } - - trace_g364fb_read(addr, val); - - return val; -} - -static void g364fb_update_depth(G364State *s) -{ - static const int depths[8] = { 1, 2, 4, 8, 15, 16, 0 }; - s->depth = depths[(s->ctla & 0x00700000) >> 20]; -} - -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 * surface_stride(surface); - end = (ymax + 1) * surface_stride(surface); - - memory_region_set_dirty(&s->mem_vram, start, end - start); -} - -static void g364fb_ctrl_write(void *opaque, - hwaddr addr, - uint64_t val, - unsigned int size) -{ - G364State *s = opaque; - - trace_g364fb_write(addr, val); - - if (addr >= REG_CLR_PAL && addr < REG_CLR_PAL + 0x800) { - /* color palette */ - int idx = (addr - REG_CLR_PAL) >> 3; - s->color_palette[idx][0] = (val >> 16) & 0xff; - s->color_palette[idx][1] = (val >> 8) & 0xff; - s->color_palette[idx][2] = val & 0xff; - g364fb_invalidate_display(s); - } else if (addr >= REG_CURS_PAT && addr < REG_CURS_PAT + 0x1000) { - /* cursor pattern */ - int idx = (addr - REG_CURS_PAT) >> 3; - s->cursor[idx] = val; - g364fb_invalidate_display(s); - } else if (addr >= REG_CURS_PAL && addr < REG_CURS_PAL + 0x18) { - /* cursor palette */ - int idx = (addr - REG_CURS_PAL) >> 3; - s->cursor_palette[idx][0] = (val >> 16) & 0xff; - s->cursor_palette[idx][1] = (val >> 8) & 0xff; - s->cursor_palette[idx][2] = val & 0xff; - g364fb_invalidate_display(s); - } else { - switch (addr) { - case REG_BOOT: /* Boot timing */ - case 0x00108: /* Line timing: half sync */ - case 0x00110: /* Line timing: back porch */ - case 0x00120: /* Line timing: short display */ - case 0x00128: /* Frame timing: broad pulse */ - case 0x00130: /* Frame timing: v sync */ - case 0x00138: /* Frame timing: v preequalise */ - case 0x00140: /* Frame timing: v postequalise */ - case 0x00148: /* Frame timing: v blank */ - case 0x00158: /* Line timing: line time */ - case 0x00160: /* Frame store: line start */ - case 0x00168: /* vram cycle: mem init */ - case 0x00170: /* vram cycle: transfer delay */ - case 0x00200: /* vram cycle: mask register */ - /* ignore */ - break; - case REG_TOP: - s->top_of_screen = val; - g364fb_invalidate_display(s); - break; - case REG_DISPLAY: - s->width = val * 4; - break; - case REG_VDISPLAY: - s->height = val / 2; - break; - case REG_CTLA: - s->ctla = val; - g364fb_update_depth(s); - g364fb_invalidate_display(s); - break; - case REG_CURS_POS: - g364_invalidate_cursor_position(s); - s->cursor_position = val; - g364_invalidate_cursor_position(s); - break; - case REG_RESET: - g364fb_reset(s); - break; - default: - error_report("g364: invalid write of 0x%" PRIx64 - " at [" TARGET_FMT_plx "]", val, addr); - break; - } - } - qemu_irq_lower(s->irq); -} - -static const MemoryRegionOps g364fb_ctrl_ops = { - .read = g364fb_ctrl_read, - .write = g364fb_ctrl_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl.min_access_size = 4, - .impl.max_access_size = 4, -}; - -static int g364fb_post_load(void *opaque, int version_id) -{ - G364State *s = opaque; - - /* force refresh */ - g364fb_update_depth(s); - g364fb_invalidate_display(s); - - return 0; -} - -static const VMStateDescription vmstate_g364fb = { - .name = "g364fb", - .version_id = 1, - .minimum_version_id = 1, - .post_load = g364fb_post_load, - .fields = (VMStateField[]) { - VMSTATE_VBUFFER_UINT32(vram, G364State, 1, NULL, 0, vram_size), - VMSTATE_BUFFER_UNSAFE(color_palette, G364State, 0, 256 * 3), - VMSTATE_BUFFER_UNSAFE(cursor_palette, G364State, 0, 9), - VMSTATE_UINT16_ARRAY(cursor, G364State, 512), - VMSTATE_UINT32(cursor_position, G364State), - VMSTATE_UINT32(ctla, G364State), - VMSTATE_UINT32(top_of_screen, G364State), - VMSTATE_UINT32(width, G364State), - VMSTATE_UINT32(height, G364State), - VMSTATE_END_OF_LIST() - } -}; - -static const GraphicHwOps g364fb_ops = { - .invalidate = g364fb_invalidate_display, - .gfx_update = g364fb_update_display, -}; - -static void g364fb_init(DeviceState *dev, G364State *s) -{ - s->vram = g_malloc0(s->vram_size); - - s->con = graphic_console_init(dev, 0, &g364fb_ops, s); - - memory_region_init_io(&s->mem_ctrl, NULL, &g364fb_ctrl_ops, s, "ctrl", 0x180000); - memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram", - s->vram_size, s->vram); - vmstate_register_ram(&s->mem_vram, dev); - memory_region_set_log(&s->mem_vram, true, DIRTY_MEMORY_VGA); -} - -#define TYPE_G364 "sysbus-g364" -#define G364(obj) OBJECT_CHECK(G364SysBusState, (obj), TYPE_G364) - -typedef struct { - SysBusDevice parent_obj; - - G364State g364; -} G364SysBusState; - -static int g364fb_sysbus_init(SysBusDevice *sbd) -{ - DeviceState *dev = DEVICE(sbd); - G364SysBusState *sbs = G364(dev); - G364State *s = &sbs->g364; - - g364fb_init(dev, s); - sysbus_init_irq(sbd, &s->irq); - sysbus_init_mmio(sbd, &s->mem_ctrl); - sysbus_init_mmio(sbd, &s->mem_vram); - - return 0; -} - -static void g364fb_sysbus_reset(DeviceState *d) -{ - G364SysBusState *s = G364(d); - - g364fb_reset(&s->g364); -} - -static Property g364fb_sysbus_properties[] = { - DEFINE_PROP_UINT32("vram_size", G364SysBusState, g364.vram_size, - 8 * 1024 * 1024), - DEFINE_PROP_END_OF_LIST(), -}; - -static void g364fb_sysbus_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = g364fb_sysbus_init; - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); - dc->desc = "G364 framebuffer"; - dc->reset = g364fb_sysbus_reset; - dc->vmsd = &vmstate_g364fb; - dc->props = g364fb_sysbus_properties; -} - -static const TypeInfo g364fb_sysbus_info = { - .name = TYPE_G364, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(G364SysBusState), - .class_init = g364fb_sysbus_class_init, -}; - -static void g364fb_register_types(void) -{ - type_register_static(&g364fb_sysbus_info); -} - -type_init(g364fb_register_types) diff --git a/qemu/hw/display/jazz_led.c b/qemu/hw/display/jazz_led.c deleted file mode 100644 index 09dcdb46a..000000000 --- a/qemu/hw/display/jazz_led.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * QEMU JAZZ LED emulator. - * - * Copyright (c) 2007-2012 Herve Poussineau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "ui/console.h" -#include "ui/pixel_ops.h" -#include "trace.h" -#include "hw/sysbus.h" - -typedef enum { - REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2, -} screen_state_t; - -#define TYPE_JAZZ_LED "jazz-led" -#define JAZZ_LED(obj) OBJECT_CHECK(LedState, (obj), TYPE_JAZZ_LED) - -typedef struct LedState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - uint8_t segments; - QemuConsole *con; - screen_state_t state; -} LedState; - -static uint64_t jazz_led_read(void *opaque, hwaddr addr, - unsigned int size) -{ - LedState *s = opaque; - uint8_t val; - - val = s->segments; - trace_jazz_led_read(addr, val); - - return val; -} - -static void jazz_led_write(void *opaque, hwaddr addr, - uint64_t val, unsigned int size) -{ - LedState *s = opaque; - uint8_t new_val = val & 0xff; - - trace_jazz_led_write(addr, new_val); - - s->segments = new_val; - s->state |= REDRAW_SEGMENTS; -} - -static const MemoryRegionOps led_ops = { - .read = jazz_led_read, - .write = jazz_led_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl.min_access_size = 1, - .impl.max_access_size = 1, -}; - -/***********************************************************/ -/* jazz_led display */ - -static void draw_horizontal_line(DisplaySurface *ds, - int posy, int posx1, int posx2, - uint32_t color) -{ - uint8_t *d; - int x, bpp; - - 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++) { - *((uint8_t *)d) = color; - d++; - } - break; - case 2: - for (x = posx1; x <= posx2; x++) { - *((uint16_t *)d) = color; - d += 2; - } - break; - case 4: - for (x = posx1; x <= posx2; x++) { - *((uint32_t *)d) = color; - d += 4; - } - break; - } -} - -static void draw_vertical_line(DisplaySurface *ds, - int posx, int posy1, int posy2, - uint32_t color) -{ - uint8_t *d; - int y, bpp; - - 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 += surface_stride(ds); - } - break; - case 2: - for (y = posy1; y <= posy2; y++) { - *((uint16_t *)d) = color; - d += surface_stride(ds); - } - break; - case 4: - for (y = posy1; y <= posy2; y++) { - *((uint32_t *)d) = color; - d += surface_stride(ds); - } - break; - } -} - -static void jazz_led_update_display(void *opaque) -{ - LedState *s = opaque; - 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 = (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 (surface_bits_per_pixel(surface)) { - case 8: - color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa); - color_led = rgb_to_pixel8(0x00, 0xff, 0x00); - break; - case 15: - color_segment = rgb_to_pixel15(0xaa, 0xaa, 0xaa); - color_led = rgb_to_pixel15(0x00, 0xff, 0x00); - break; - case 16: - color_segment = rgb_to_pixel16(0xaa, 0xaa, 0xaa); - color_led = rgb_to_pixel16(0x00, 0xff, 0x00); - break; - case 24: - color_segment = rgb_to_pixel24(0xaa, 0xaa, 0xaa); - color_led = rgb_to_pixel24(0x00, 0xff, 0x00); - break; - case 32: - color_segment = rgb_to_pixel32(0xaa, 0xaa, 0xaa); - color_led = rgb_to_pixel32(0x00, 0xff, 0x00); - break; - default: - return; - } - - /* display segments */ - 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(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(s->con, 0, 0, - surface_width(surface), surface_height(surface)); -} - -static void jazz_led_invalidate_display(void *opaque) -{ - LedState *s = opaque; - s->state |= REDRAW_SEGMENTS | REDRAW_BACKGROUND; -} - -static void jazz_led_text_update(void *opaque, console_ch_t *chardata) -{ - LedState *s = opaque; - char buf[2]; - - 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++, ATTR2CHTYPE(buf[0], QEMU_COLOR_BLUE, - QEMU_COLOR_BLACK, 1)); - console_write_ch(chardata++, ATTR2CHTYPE(buf[1], QEMU_COLOR_BLUE, - QEMU_COLOR_BLACK, 1)); - - dpy_text_update(s->con, 0, 0, 2, 1); -} - -static int jazz_led_post_load(void *opaque, int version_id) -{ - /* force refresh */ - jazz_led_invalidate_display(opaque); - - return 0; -} - -static const VMStateDescription vmstate_jazz_led = { - .name = "jazz-led", - .version_id = 0, - .minimum_version_id = 0, - .post_load = jazz_led_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT8(segments, LedState), - VMSTATE_END_OF_LIST() - } -}; - -static const GraphicHwOps jazz_led_ops = { - .invalidate = jazz_led_invalidate_display, - .gfx_update = jazz_led_update_display, - .text_update = jazz_led_text_update, -}; - -static int jazz_led_init(SysBusDevice *dev) -{ - LedState *s = JAZZ_LED(dev); - - memory_region_init_io(&s->iomem, OBJECT(s), &led_ops, s, "led", 1); - sysbus_init_mmio(dev, &s->iomem); - - s->con = graphic_console_init(DEVICE(dev), 0, &jazz_led_ops, s); - - return 0; -} - -static void jazz_led_reset(DeviceState *d) -{ - LedState *s = JAZZ_LED(d); - - s->segments = 0; - s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND; - qemu_console_resize(s->con, 60, 80); -} - -static void jazz_led_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = jazz_led_init; - dc->desc = "Jazz LED display", - dc->vmsd = &vmstate_jazz_led; - dc->reset = jazz_led_reset; -} - -static const TypeInfo jazz_led_info = { - .name = TYPE_JAZZ_LED, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(LedState), - .class_init = jazz_led_class_init, -}; - -static void jazz_led_register(void) -{ - type_register_static(&jazz_led_info); -} - -type_init(jazz_led_register); diff --git a/qemu/hw/display/milkymist-tmu2.c b/qemu/hw/display/milkymist-tmu2.c deleted file mode 100644 index 9bc88f93b..000000000 --- a/qemu/hw/display/milkymist-tmu2.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - * QEMU model of the Milkymist texture mapping unit. - * - * Copyright (c) 2010 Michael Walle - * Copyright (c) 2010 Sebastien Bourdeauducq - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - * - * - * Specification available at: - * http://www.milkymist.org/socdoc/tmu2.pdf - * - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/sysbus.h" -#include "trace.h" -#include "qemu/error-report.h" - -#include -#include -#include - -enum { - R_CTL = 0, - R_HMESHLAST, - R_VMESHLAST, - R_BRIGHTNESS, - R_CHROMAKEY, - R_VERTICESADDR, - R_TEXFBUF, - R_TEXHRES, - R_TEXVRES, - R_TEXHMASK, - R_TEXVMASK, - R_DSTFBUF, - R_DSTHRES, - R_DSTVRES, - R_DSTHOFFSET, - R_DSTVOFFSET, - R_DSTSQUAREW, - R_DSTSQUAREH, - R_ALPHA, - R_MAX -}; - -enum { - CTL_START_BUSY = (1<<0), - CTL_CHROMAKEY = (1<<1), -}; - -enum { - MAX_BRIGHTNESS = 63, - MAX_ALPHA = 63, -}; - -enum { - MESH_MAXSIZE = 128, -}; - -struct vertex { - int x; - int y; -} QEMU_PACKED; - -#define TYPE_MILKYMIST_TMU2 "milkymist-tmu2" -#define MILKYMIST_TMU2(obj) \ - OBJECT_CHECK(MilkymistTMU2State, (obj), TYPE_MILKYMIST_TMU2) - -struct MilkymistTMU2State { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - CharDriverState *chr; - qemu_irq irq; - - uint32_t regs[R_MAX]; - - Display *dpy; - GLXFBConfig glx_fb_config; - GLXContext glx_context; -}; -typedef struct MilkymistTMU2State MilkymistTMU2State; - -static const int glx_fbconfig_attr[] = { - GLX_GREEN_SIZE, 5, - GLX_GREEN_SIZE, 6, - GLX_BLUE_SIZE, 5, - None -}; - -static int tmu2_glx_init(MilkymistTMU2State *s) -{ - GLXFBConfig *configs; - int nelements; - - s->dpy = XOpenDisplay(NULL); /* FIXME: call XCloseDisplay() */ - if (s->dpy == NULL) { - return 1; - } - - configs = glXChooseFBConfig(s->dpy, 0, glx_fbconfig_attr, &nelements); - if (configs == NULL) { - return 1; - } - - s->glx_fb_config = *configs; - XFree(configs); - - /* FIXME: call glXDestroyContext() */ - s->glx_context = glXCreateNewContext(s->dpy, s->glx_fb_config, - GLX_RGBA_TYPE, NULL, 1); - if (s->glx_context == NULL) { - return 1; - } - - return 0; -} - -static void tmu2_gl_map(struct vertex *mesh, int texhres, int texvres, - int hmeshlast, int vmeshlast, int ho, int vo, int sw, int sh) -{ - int x, y; - int x0, y0, x1, y1; - int u0, v0, u1, v1, u2, v2, u3, v3; - double xscale = 1.0 / ((double)(64 * texhres)); - double yscale = 1.0 / ((double)(64 * texvres)); - - glLoadIdentity(); - glTranslatef(ho, vo, 0); - glEnable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - - for (y = 0; y < vmeshlast; y++) { - y0 = y * sh; - y1 = y0 + sh; - for (x = 0; x < hmeshlast; x++) { - x0 = x * sw; - x1 = x0 + sw; - - u0 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x].x); - v0 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x].y); - u1 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x + 1].x); - v1 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x + 1].y); - u2 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x + 1].x); - v2 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x + 1].y); - u3 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x].x); - v3 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x].y); - - glTexCoord2d(((double)u0) * xscale, ((double)v0) * yscale); - glVertex3i(x0, y0, 0); - glTexCoord2d(((double)u1) * xscale, ((double)v1) * yscale); - glVertex3i(x1, y0, 0); - glTexCoord2d(((double)u2) * xscale, ((double)v2) * yscale); - glVertex3i(x1, y1, 0); - glTexCoord2d(((double)u3) * xscale, ((double)v3) * yscale); - glVertex3i(x0, y1, 0); - } - } - - glEnd(); -} - -static void tmu2_start(MilkymistTMU2State *s) -{ - int pbuffer_attrib[6] = { - GLX_PBUFFER_WIDTH, - 0, - GLX_PBUFFER_HEIGHT, - 0, - GLX_PRESERVED_CONTENTS, - True - }; - - GLXPbuffer pbuffer; - GLuint texture; - void *fb; - hwaddr fb_len; - void *mesh; - hwaddr mesh_len; - float m; - - trace_milkymist_tmu2_start(); - - /* Create and set up a suitable OpenGL context */ - pbuffer_attrib[1] = s->regs[R_DSTHRES]; - pbuffer_attrib[3] = s->regs[R_DSTVRES]; - pbuffer = glXCreatePbuffer(s->dpy, s->glx_fb_config, pbuffer_attrib); - glXMakeContextCurrent(s->dpy, pbuffer, pbuffer, s->glx_context); - - /* Fixup endianness. TODO: would it work on BE hosts? */ - glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); - glPixelStorei(GL_PACK_SWAP_BYTES, 1); - - /* Row alignment */ - glPixelStorei(GL_UNPACK_ALIGNMENT, 2); - glPixelStorei(GL_PACK_ALIGNMENT, 2); - - /* Read the QEMU source framebuffer into an OpenGL texture */ - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - fb_len = 2*s->regs[R_TEXHRES]*s->regs[R_TEXVRES]; - fb = cpu_physical_memory_map(s->regs[R_TEXFBUF], &fb_len, 0); - if (fb == NULL) { - glDeleteTextures(1, &texture); - glXMakeContextCurrent(s->dpy, None, None, NULL); - glXDestroyPbuffer(s->dpy, pbuffer); - return; - } - glTexImage2D(GL_TEXTURE_2D, 0, 3, s->regs[R_TEXHRES], s->regs[R_TEXVRES], - 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, fb); - cpu_physical_memory_unmap(fb, fb_len, 0, fb_len); - - /* Set up texturing options */ - /* WARNING: - * Many cases of TMU2 masking are not supported by OpenGL. - * We only implement the most common ones: - * - full bilinear filtering vs. nearest texel - * - texture clamping vs. texture wrapping - */ - if ((s->regs[R_TEXHMASK] & 0x3f) > 0x20) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - if ((s->regs[R_TEXHMASK] >> 6) & s->regs[R_TEXHRES]) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - } - if ((s->regs[R_TEXVMASK] >> 6) & s->regs[R_TEXVRES]) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - - /* Translucency and decay */ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - m = (float)(s->regs[R_BRIGHTNESS] + 1) / 64.0f; - glColor4f(m, m, m, (float)(s->regs[R_ALPHA] + 1) / 64.0f); - - /* Read the QEMU dest. framebuffer into the OpenGL framebuffer */ - fb_len = 2 * s->regs[R_DSTHRES] * s->regs[R_DSTVRES]; - fb = cpu_physical_memory_map(s->regs[R_DSTFBUF], &fb_len, 0); - if (fb == NULL) { - glDeleteTextures(1, &texture); - glXMakeContextCurrent(s->dpy, None, None, NULL); - glXDestroyPbuffer(s->dpy, pbuffer); - return; - } - - glDrawPixels(s->regs[R_DSTHRES], s->regs[R_DSTVRES], GL_RGB, - GL_UNSIGNED_SHORT_5_6_5, fb); - cpu_physical_memory_unmap(fb, fb_len, 0, fb_len); - glViewport(0, 0, s->regs[R_DSTHRES], s->regs[R_DSTVRES]); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0, s->regs[R_DSTHRES], 0.0, s->regs[R_DSTVRES], -1.0, 1.0); - glMatrixMode(GL_MODELVIEW); - - /* Map the texture */ - mesh_len = MESH_MAXSIZE*MESH_MAXSIZE*sizeof(struct vertex); - mesh = cpu_physical_memory_map(s->regs[R_VERTICESADDR], &mesh_len, 0); - if (mesh == NULL) { - glDeleteTextures(1, &texture); - glXMakeContextCurrent(s->dpy, None, None, NULL); - glXDestroyPbuffer(s->dpy, pbuffer); - return; - } - - tmu2_gl_map((struct vertex *)mesh, - s->regs[R_TEXHRES], s->regs[R_TEXVRES], - s->regs[R_HMESHLAST], s->regs[R_VMESHLAST], - s->regs[R_DSTHOFFSET], s->regs[R_DSTVOFFSET], - s->regs[R_DSTSQUAREW], s->regs[R_DSTSQUAREH]); - cpu_physical_memory_unmap(mesh, mesh_len, 0, mesh_len); - - /* Write back the OpenGL framebuffer to the QEMU framebuffer */ - fb_len = 2 * s->regs[R_DSTHRES] * s->regs[R_DSTVRES]; - fb = cpu_physical_memory_map(s->regs[R_DSTFBUF], &fb_len, 1); - if (fb == NULL) { - glDeleteTextures(1, &texture); - glXMakeContextCurrent(s->dpy, None, None, NULL); - glXDestroyPbuffer(s->dpy, pbuffer); - return; - } - - glReadPixels(0, 0, s->regs[R_DSTHRES], s->regs[R_DSTVRES], GL_RGB, - GL_UNSIGNED_SHORT_5_6_5, fb); - cpu_physical_memory_unmap(fb, fb_len, 1, fb_len); - - /* Free OpenGL allocs */ - glDeleteTextures(1, &texture); - glXMakeContextCurrent(s->dpy, None, None, NULL); - glXDestroyPbuffer(s->dpy, pbuffer); - - s->regs[R_CTL] &= ~CTL_START_BUSY; - - trace_milkymist_tmu2_pulse_irq(); - qemu_irq_pulse(s->irq); -} - -static uint64_t tmu2_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistTMU2State *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_CTL: - case R_HMESHLAST: - case R_VMESHLAST: - case R_BRIGHTNESS: - case R_CHROMAKEY: - case R_VERTICESADDR: - case R_TEXFBUF: - case R_TEXHRES: - case R_TEXVRES: - case R_TEXHMASK: - case R_TEXVMASK: - case R_DSTFBUF: - case R_DSTHRES: - case R_DSTVRES: - case R_DSTHOFFSET: - case R_DSTVOFFSET: - case R_DSTSQUAREW: - case R_DSTSQUAREH: - case R_ALPHA: - r = s->regs[addr]; - break; - - default: - error_report("milkymist_tmu2: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_tmu2_memory_read(addr << 2, r); - - return r; -} - -static void tmu2_check_registers(MilkymistTMU2State *s) -{ - if (s->regs[R_BRIGHTNESS] > MAX_BRIGHTNESS) { - error_report("milkymist_tmu2: max brightness is %d", MAX_BRIGHTNESS); - } - - if (s->regs[R_ALPHA] > MAX_ALPHA) { - error_report("milkymist_tmu2: max alpha is %d", MAX_ALPHA); - } - - if (s->regs[R_VERTICESADDR] & 0x07) { - error_report("milkymist_tmu2: vertex mesh address has to be 64-bit " - "aligned"); - } - - if (s->regs[R_TEXFBUF] & 0x01) { - error_report("milkymist_tmu2: texture buffer address has to be " - "16-bit aligned"); - } -} - -static void tmu2_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistTMU2State *s = opaque; - - trace_milkymist_tmu2_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_CTL: - s->regs[addr] = value; - if (value & CTL_START_BUSY) { - tmu2_start(s); - } - break; - case R_BRIGHTNESS: - case R_HMESHLAST: - case R_VMESHLAST: - case R_CHROMAKEY: - case R_VERTICESADDR: - case R_TEXFBUF: - case R_TEXHRES: - case R_TEXVRES: - case R_TEXHMASK: - case R_TEXVMASK: - case R_DSTFBUF: - case R_DSTHRES: - case R_DSTVRES: - case R_DSTHOFFSET: - case R_DSTVOFFSET: - case R_DSTSQUAREW: - case R_DSTSQUAREH: - case R_ALPHA: - s->regs[addr] = value; - break; - - default: - error_report("milkymist_tmu2: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - tmu2_check_registers(s); -} - -static const MemoryRegionOps tmu2_mmio_ops = { - .read = tmu2_read, - .write = tmu2_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void milkymist_tmu2_reset(DeviceState *d) -{ - MilkymistTMU2State *s = MILKYMIST_TMU2(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } -} - -static int milkymist_tmu2_init(SysBusDevice *dev) -{ - MilkymistTMU2State *s = MILKYMIST_TMU2(dev); - - if (tmu2_glx_init(s)) { - return 1; - } - - sysbus_init_irq(dev, &s->irq); - - memory_region_init_io(&s->regs_region, OBJECT(s), &tmu2_mmio_ops, s, - "milkymist-tmu2", R_MAX * 4); - sysbus_init_mmio(dev, &s->regs_region); - - return 0; -} - -static const VMStateDescription vmstate_milkymist_tmu2 = { - .name = "milkymist-tmu2", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistTMU2State, R_MAX), - VMSTATE_END_OF_LIST() - } -}; - -static void milkymist_tmu2_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = milkymist_tmu2_init; - dc->reset = milkymist_tmu2_reset; - dc->vmsd = &vmstate_milkymist_tmu2; -} - -static const TypeInfo milkymist_tmu2_info = { - .name = TYPE_MILKYMIST_TMU2, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistTMU2State), - .class_init = milkymist_tmu2_class_init, -}; - -static void milkymist_tmu2_register_types(void) -{ - type_register_static(&milkymist_tmu2_info); -} - -type_init(milkymist_tmu2_register_types) diff --git a/qemu/hw/display/milkymist-vgafb.c b/qemu/hw/display/milkymist-vgafb.c deleted file mode 100644 index 19ca25647..000000000 --- a/qemu/hw/display/milkymist-vgafb.c +++ /dev/null @@ -1,354 +0,0 @@ - -/* - * QEMU model of the Milkymist VGA framebuffer. - * - * Copyright (c) 2010-2012 Michael Walle - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - * - * - * Specification available at: - * http://www.milkymist.org/socdoc/vgafb.pdf - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/sysbus.h" -#include "trace.h" -#include "ui/console.h" -#include "framebuffer.h" -#include "ui/pixel_ops.h" -#include "qemu/error-report.h" - -#define BITS 8 -#include "milkymist-vgafb_template.h" -#define BITS 15 -#include "milkymist-vgafb_template.h" -#define BITS 16 -#include "milkymist-vgafb_template.h" -#define BITS 24 -#include "milkymist-vgafb_template.h" -#define BITS 32 -#include "milkymist-vgafb_template.h" - -enum { - R_CTRL = 0, - R_HRES, - R_HSYNC_START, - R_HSYNC_END, - R_HSCAN, - R_VRES, - R_VSYNC_START, - R_VSYNC_END, - R_VSCAN, - R_BASEADDRESS, - R_BASEADDRESS_ACT, - R_BURST_COUNT, - R_DDC, - R_SOURCE_CLOCK, - R_MAX -}; - -enum { - CTRL_RESET = (1<<0), -}; - -#define TYPE_MILKYMIST_VGAFB "milkymist-vgafb" -#define MILKYMIST_VGAFB(obj) \ - OBJECT_CHECK(MilkymistVgafbState, (obj), TYPE_MILKYMIST_VGAFB) - -struct MilkymistVgafbState { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - MemoryRegionSection fbsection; - QemuConsole *con; - - int invalidate; - uint32_t fb_offset; - uint32_t fb_mask; - - uint32_t regs[R_MAX]; -}; -typedef struct MilkymistVgafbState MilkymistVgafbState; - -static int vgafb_enabled(MilkymistVgafbState *s) -{ - return !(s->regs[R_CTRL] & CTRL_RESET); -} - -static void vgafb_update_display(void *opaque) -{ - MilkymistVgafbState *s = opaque; - SysBusDevice *sbd; - DisplaySurface *surface = qemu_console_surface(s->con); - int src_width; - int first = 0; - int last = 0; - drawfn fn; - - if (!vgafb_enabled(s)) { - return; - } - - sbd = SYS_BUS_DEVICE(s); - int dest_width = s->regs[R_HRES]; - - switch (surface_bits_per_pixel(surface)) { - case 0: - return; - case 8: - fn = draw_line_8; - break; - case 15: - fn = draw_line_15; - dest_width *= 2; - break; - case 16: - fn = draw_line_16; - dest_width *= 2; - break; - case 24: - fn = draw_line_24; - dest_width *= 3; - break; - case 32: - fn = draw_line_32; - dest_width *= 4; - break; - default: - hw_error("milkymist_vgafb: bad color depth\n"); - break; - } - - src_width = s->regs[R_HRES] * 2; - if (s->invalidate) { - framebuffer_update_memory_section(&s->fbsection, - sysbus_address_space(sbd), - s->regs[R_BASEADDRESS] + s->fb_offset, - s->regs[R_VRES], src_width); - } - - framebuffer_update_display(surface, &s->fbsection, - s->regs[R_HRES], - s->regs[R_VRES], - src_width, - dest_width, - 0, - s->invalidate, - fn, - NULL, - &first, &last); - - if (first >= 0) { - dpy_gfx_update(s->con, 0, first, s->regs[R_HRES], last - first + 1); - } - s->invalidate = 0; -} - -static void vgafb_invalidate_display(void *opaque) -{ - MilkymistVgafbState *s = opaque; - s->invalidate = 1; -} - -static void vgafb_resize(MilkymistVgafbState *s) -{ - if (!vgafb_enabled(s)) { - return; - } - - qemu_console_resize(s->con, s->regs[R_HRES], s->regs[R_VRES]); - s->invalidate = 1; -} - -static uint64_t vgafb_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistVgafbState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_CTRL: - case R_HRES: - case R_HSYNC_START: - case R_HSYNC_END: - case R_HSCAN: - case R_VRES: - case R_VSYNC_START: - case R_VSYNC_END: - case R_VSCAN: - case R_BASEADDRESS: - case R_BURST_COUNT: - case R_DDC: - case R_SOURCE_CLOCK: - r = s->regs[addr]; - break; - case R_BASEADDRESS_ACT: - r = s->regs[R_BASEADDRESS]; - break; - - default: - error_report("milkymist_vgafb: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_vgafb_memory_read(addr << 2, r); - - return r; -} - -static void vgafb_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistVgafbState *s = opaque; - - trace_milkymist_vgafb_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_CTRL: - s->regs[addr] = value; - vgafb_resize(s); - break; - case R_HSYNC_START: - case R_HSYNC_END: - case R_HSCAN: - case R_VSYNC_START: - case R_VSYNC_END: - case R_VSCAN: - case R_BURST_COUNT: - case R_DDC: - case R_SOURCE_CLOCK: - s->regs[addr] = value; - break; - case R_BASEADDRESS: - if (value & 0x1f) { - error_report("milkymist_vgafb: framebuffer base address have to " - "be 32 byte aligned"); - break; - } - s->regs[addr] = value & s->fb_mask; - s->invalidate = 1; - break; - case R_HRES: - case R_VRES: - s->regs[addr] = value; - vgafb_resize(s); - break; - case R_BASEADDRESS_ACT: - error_report("milkymist_vgafb: write to read-only register 0x" - TARGET_FMT_plx, addr << 2); - break; - - default: - error_report("milkymist_vgafb: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } -} - -static const MemoryRegionOps vgafb_mmio_ops = { - .read = vgafb_read, - .write = vgafb_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void milkymist_vgafb_reset(DeviceState *d) -{ - MilkymistVgafbState *s = MILKYMIST_VGAFB(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - - /* defaults */ - s->regs[R_CTRL] = CTRL_RESET; - s->regs[R_HRES] = 640; - s->regs[R_VRES] = 480; - s->regs[R_BASEADDRESS] = 0; -} - -static const GraphicHwOps vgafb_ops = { - .invalidate = vgafb_invalidate_display, - .gfx_update = vgafb_update_display, -}; - -static int milkymist_vgafb_init(SysBusDevice *dev) -{ - MilkymistVgafbState *s = MILKYMIST_VGAFB(dev); - - memory_region_init_io(&s->regs_region, OBJECT(s), &vgafb_mmio_ops, s, - "milkymist-vgafb", R_MAX * 4); - sysbus_init_mmio(dev, &s->regs_region); - - s->con = graphic_console_init(DEVICE(dev), 0, &vgafb_ops, s); - - return 0; -} - -static int vgafb_post_load(void *opaque, int version_id) -{ - vgafb_invalidate_display(opaque); - return 0; -} - -static const VMStateDescription vmstate_milkymist_vgafb = { - .name = "milkymist-vgafb", - .version_id = 1, - .minimum_version_id = 1, - .post_load = vgafb_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistVgafbState, R_MAX), - VMSTATE_END_OF_LIST() - } -}; - -static Property milkymist_vgafb_properties[] = { - DEFINE_PROP_UINT32("fb_offset", MilkymistVgafbState, fb_offset, 0x0), - DEFINE_PROP_UINT32("fb_mask", MilkymistVgafbState, fb_mask, 0xffffffff), - DEFINE_PROP_END_OF_LIST(), -}; - -static void milkymist_vgafb_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = milkymist_vgafb_init; - dc->reset = milkymist_vgafb_reset; - dc->vmsd = &vmstate_milkymist_vgafb; - dc->props = milkymist_vgafb_properties; -} - -static const TypeInfo milkymist_vgafb_info = { - .name = TYPE_MILKYMIST_VGAFB, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistVgafbState), - .class_init = milkymist_vgafb_class_init, -}; - -static void milkymist_vgafb_register_types(void) -{ - type_register_static(&milkymist_vgafb_info); -} - -type_init(milkymist_vgafb_register_types) diff --git a/qemu/hw/display/milkymist-vgafb_template.h b/qemu/hw/display/milkymist-vgafb_template.h deleted file mode 100644 index 48837809e..000000000 --- a/qemu/hw/display/milkymist-vgafb_template.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * QEMU model of the Milkymist VGA framebuffer. - * - * Copyright (c) 2010 Michael Walle - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - * - */ - -#if BITS == 8 -#define COPY_PIXEL(to, r, g, b) \ - do { \ - *to = rgb_to_pixel8(r, g, b); \ - to += 1; \ - } while (0) -#elif BITS == 15 -#define COPY_PIXEL(to, r, g, b) \ - do { \ - *(uint16_t *)to = rgb_to_pixel15(r, g, b); \ - to += 2; \ - } while (0) -#elif BITS == 16 -#define COPY_PIXEL(to, r, g, b) \ - do { \ - *(uint16_t *)to = rgb_to_pixel16(r, g, b); \ - to += 2; \ - } while (0) -#elif BITS == 24 -#define COPY_PIXEL(to, r, g, b) \ - do { \ - uint32_t tmp = rgb_to_pixel24(r, g, b); \ - *(to++) = tmp & 0xff; \ - *(to++) = (tmp >> 8) & 0xff; \ - *(to++) = (tmp >> 16) & 0xff; \ - } while (0) -#elif BITS == 32 -#define COPY_PIXEL(to, r, g, b) \ - do { \ - *(uint32_t *)to = rgb_to_pixel32(r, g, b); \ - to += 4; \ - } while (0) -#else -#error unknown bit depth -#endif - -static void glue(draw_line_, BITS)(void *opaque, uint8_t *d, const uint8_t *s, - int width, int deststep) -{ - uint16_t rgb565; - uint8_t r, g, b; - - while (width--) { - rgb565 = lduw_be_p(s); - r = ((rgb565 >> 11) & 0x1f) << 3; - g = ((rgb565 >> 5) & 0x3f) << 2; - b = ((rgb565 >> 0) & 0x1f) << 3; - COPY_PIXEL(d, r, g, b); - s += 2; - } -} - -#undef BITS -#undef COPY_PIXEL diff --git a/qemu/hw/display/omap_dss.c b/qemu/hw/display/omap_dss.c deleted file mode 100644 index 783e9e131..000000000 --- a/qemu/hw/display/omap_dss.c +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * OMAP2 Display Subsystem. - * - * Copyright (C) 2008 Nokia Corporation - * Written by Andrzej Zaborowski - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * 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 . - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "ui/console.h" -#include "hw/arm/omap.h" - -struct omap_dss_s { - qemu_irq irq; - qemu_irq drq; - DisplayState *state; - MemoryRegion iomem_diss1, iomem_disc1, iomem_rfbi1, iomem_venc1, iomem_im3; - - int autoidle; - int control; - int enable; - - struct omap_dss_panel_s { - int enable; - int nx; - int ny; - - int x; - int y; - } dig, lcd; - - struct { - uint32_t idlemode; - uint32_t irqst; - uint32_t irqen; - uint32_t control; - uint32_t config; - uint32_t capable; - uint32_t timing[4]; - int line; - uint32_t bg[2]; - uint32_t trans[2]; - - struct omap_dss_plane_s { - int enable; - int bpp; - int posx; - int posy; - int nx; - int ny; - - hwaddr addr[3]; - - uint32_t attr; - uint32_t tresh; - int rowinc; - int colinc; - int wininc; - } l[3]; - - int invalidate; - uint16_t palette[256]; - } dispc; - - struct { - int idlemode; - uint32_t control; - int enable; - int pixels; - int busy; - int skiplines; - uint16_t rxbuf; - uint32_t config[2]; - uint32_t time[4]; - uint32_t data[6]; - uint16_t vsync; - uint16_t hsync; - struct rfbi_chip_s *chip[2]; - } rfbi; -}; - -static void omap_dispc_interrupt_update(struct omap_dss_s *s) -{ - qemu_set_irq(s->irq, s->dispc.irqst & s->dispc.irqen); -} - -static void omap_rfbi_reset(struct omap_dss_s *s) -{ - s->rfbi.idlemode = 0; - s->rfbi.control = 2; - s->rfbi.enable = 0; - s->rfbi.pixels = 0; - s->rfbi.skiplines = 0; - s->rfbi.busy = 0; - s->rfbi.config[0] = 0x00310000; - s->rfbi.config[1] = 0x00310000; - s->rfbi.time[0] = 0; - s->rfbi.time[1] = 0; - s->rfbi.time[2] = 0; - s->rfbi.time[3] = 0; - s->rfbi.data[0] = 0; - s->rfbi.data[1] = 0; - s->rfbi.data[2] = 0; - s->rfbi.data[3] = 0; - s->rfbi.data[4] = 0; - s->rfbi.data[5] = 0; - s->rfbi.vsync = 0; - s->rfbi.hsync = 0; -} - -void omap_dss_reset(struct omap_dss_s *s) -{ - s->autoidle = 0; - s->control = 0; - s->enable = 0; - - s->dig.enable = 0; - s->dig.nx = 1; - s->dig.ny = 1; - - s->lcd.enable = 0; - s->lcd.nx = 1; - s->lcd.ny = 1; - - s->dispc.idlemode = 0; - s->dispc.irqst = 0; - s->dispc.irqen = 0; - s->dispc.control = 0; - s->dispc.config = 0; - s->dispc.capable = 0x161; - s->dispc.timing[0] = 0; - s->dispc.timing[1] = 0; - s->dispc.timing[2] = 0; - s->dispc.timing[3] = 0; - s->dispc.line = 0; - s->dispc.bg[0] = 0; - s->dispc.bg[1] = 0; - s->dispc.trans[0] = 0; - s->dispc.trans[1] = 0; - - s->dispc.l[0].enable = 0; - s->dispc.l[0].bpp = 0; - s->dispc.l[0].addr[0] = 0; - s->dispc.l[0].addr[1] = 0; - s->dispc.l[0].addr[2] = 0; - s->dispc.l[0].posx = 0; - s->dispc.l[0].posy = 0; - s->dispc.l[0].nx = 1; - s->dispc.l[0].ny = 1; - s->dispc.l[0].attr = 0; - s->dispc.l[0].tresh = 0; - s->dispc.l[0].rowinc = 1; - s->dispc.l[0].colinc = 1; - s->dispc.l[0].wininc = 0; - - omap_rfbi_reset(s); - omap_dispc_interrupt_update(s); -} - -static uint64_t omap_diss_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap_dss_s *s = (struct omap_dss_s *) opaque; - - if (size != 4) { - return omap_badwidth_read32(opaque, addr); - } - - switch (addr) { - case 0x00: /* DSS_REVISIONNUMBER */ - return 0x20; - - case 0x10: /* DSS_SYSCONFIG */ - return s->autoidle; - - case 0x14: /* DSS_SYSSTATUS */ - return 1; /* RESETDONE */ - - case 0x40: /* DSS_CONTROL */ - return s->control; - - case 0x50: /* DSS_PSA_LCD_REG_1 */ - case 0x54: /* DSS_PSA_LCD_REG_2 */ - case 0x58: /* DSS_PSA_VIDEO_REG */ - /* TODO: fake some values when appropriate s->control bits are set */ - return 0; - - case 0x5c: /* DSS_STATUS */ - return 1 + (s->control & 1); - - default: - break; - } - OMAP_BAD_REG(addr); - return 0; -} - -static void omap_diss_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - struct omap_dss_s *s = (struct omap_dss_s *) opaque; - - if (size != 4) { - omap_badwidth_write32(opaque, addr, value); - return; - } - - switch (addr) { - case 0x00: /* DSS_REVISIONNUMBER */ - case 0x14: /* DSS_SYSSTATUS */ - case 0x50: /* DSS_PSA_LCD_REG_1 */ - case 0x54: /* DSS_PSA_LCD_REG_2 */ - case 0x58: /* DSS_PSA_VIDEO_REG */ - case 0x5c: /* DSS_STATUS */ - OMAP_RO_REG(addr); - break; - - case 0x10: /* DSS_SYSCONFIG */ - if (value & 2) /* SOFTRESET */ - omap_dss_reset(s); - s->autoidle = value & 1; - break; - - case 0x40: /* DSS_CONTROL */ - s->control = value & 0x3dd; - break; - - default: - OMAP_BAD_REG(addr); - } -} - -static const MemoryRegionOps omap_diss_ops = { - .read = omap_diss_read, - .write = omap_diss_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static uint64_t omap_disc_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap_dss_s *s = (struct omap_dss_s *) opaque; - - if (size != 4) { - return omap_badwidth_read32(opaque, addr); - } - - switch (addr) { - case 0x000: /* DISPC_REVISION */ - return 0x20; - - case 0x010: /* DISPC_SYSCONFIG */ - return s->dispc.idlemode; - - case 0x014: /* DISPC_SYSSTATUS */ - return 1; /* RESETDONE */ - - case 0x018: /* DISPC_IRQSTATUS */ - return s->dispc.irqst; - - case 0x01c: /* DISPC_IRQENABLE */ - return s->dispc.irqen; - - case 0x040: /* DISPC_CONTROL */ - return s->dispc.control; - - case 0x044: /* DISPC_CONFIG */ - return s->dispc.config; - - case 0x048: /* DISPC_CAPABLE */ - return s->dispc.capable; - - case 0x04c: /* DISPC_DEFAULT_COLOR0 */ - return s->dispc.bg[0]; - case 0x050: /* DISPC_DEFAULT_COLOR1 */ - return s->dispc.bg[1]; - case 0x054: /* DISPC_TRANS_COLOR0 */ - return s->dispc.trans[0]; - case 0x058: /* DISPC_TRANS_COLOR1 */ - return s->dispc.trans[1]; - - case 0x05c: /* DISPC_LINE_STATUS */ - return 0x7ff; - case 0x060: /* DISPC_LINE_NUMBER */ - return s->dispc.line; - - case 0x064: /* DISPC_TIMING_H */ - return s->dispc.timing[0]; - case 0x068: /* DISPC_TIMING_V */ - return s->dispc.timing[1]; - case 0x06c: /* DISPC_POL_FREQ */ - return s->dispc.timing[2]; - case 0x070: /* DISPC_DIVISOR */ - return s->dispc.timing[3]; - - case 0x078: /* DISPC_SIZE_DIG */ - return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1); - case 0x07c: /* DISPC_SIZE_LCD */ - return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1); - - case 0x080: /* DISPC_GFX_BA0 */ - return s->dispc.l[0].addr[0]; - case 0x084: /* DISPC_GFX_BA1 */ - return s->dispc.l[0].addr[1]; - case 0x088: /* DISPC_GFX_POSITION */ - return (s->dispc.l[0].posy << 16) | s->dispc.l[0].posx; - case 0x08c: /* DISPC_GFX_SIZE */ - return ((s->dispc.l[0].ny - 1) << 16) | (s->dispc.l[0].nx - 1); - case 0x0a0: /* DISPC_GFX_ATTRIBUTES */ - return s->dispc.l[0].attr; - case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */ - return s->dispc.l[0].tresh; - case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */ - return 256; - case 0x0ac: /* DISPC_GFX_ROW_INC */ - return s->dispc.l[0].rowinc; - case 0x0b0: /* DISPC_GFX_PIXEL_INC */ - return s->dispc.l[0].colinc; - case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */ - return s->dispc.l[0].wininc; - case 0x0b8: /* DISPC_GFX_TABLE_BA */ - return s->dispc.l[0].addr[2]; - - case 0x0bc: /* DISPC_VID1_BA0 */ - case 0x0c0: /* DISPC_VID1_BA1 */ - case 0x0c4: /* DISPC_VID1_POSITION */ - case 0x0c8: /* DISPC_VID1_SIZE */ - case 0x0cc: /* DISPC_VID1_ATTRIBUTES */ - case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */ - case 0x0d4: /* DISPC_VID1_FIFO_SIZE_STATUS */ - case 0x0d8: /* DISPC_VID1_ROW_INC */ - case 0x0dc: /* DISPC_VID1_PIXEL_INC */ - case 0x0e0: /* DISPC_VID1_FIR */ - case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */ - case 0x0e8: /* DISPC_VID1_ACCU0 */ - case 0x0ec: /* DISPC_VID1_ACCU1 */ - case 0x0f0 ... 0x140: /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */ - case 0x14c: /* DISPC_VID2_BA0 */ - case 0x150: /* DISPC_VID2_BA1 */ - case 0x154: /* DISPC_VID2_POSITION */ - case 0x158: /* DISPC_VID2_SIZE */ - case 0x15c: /* DISPC_VID2_ATTRIBUTES */ - case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */ - case 0x164: /* DISPC_VID2_FIFO_SIZE_STATUS */ - case 0x168: /* DISPC_VID2_ROW_INC */ - case 0x16c: /* DISPC_VID2_PIXEL_INC */ - case 0x170: /* DISPC_VID2_FIR */ - case 0x174: /* DISPC_VID2_PICTURE_SIZE */ - case 0x178: /* DISPC_VID2_ACCU0 */ - case 0x17c: /* DISPC_VID2_ACCU1 */ - case 0x180 ... 0x1d0: /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */ - case 0x1d4: /* DISPC_DATA_CYCLE1 */ - case 0x1d8: /* DISPC_DATA_CYCLE2 */ - case 0x1dc: /* DISPC_DATA_CYCLE3 */ - return 0; - - default: - break; - } - OMAP_BAD_REG(addr); - return 0; -} - -static void omap_disc_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - struct omap_dss_s *s = (struct omap_dss_s *) opaque; - - if (size != 4) { - omap_badwidth_write32(opaque, addr, value); - return; - } - - switch (addr) { - case 0x010: /* DISPC_SYSCONFIG */ - if (value & 2) /* SOFTRESET */ - omap_dss_reset(s); - s->dispc.idlemode = value & 0x301b; - break; - - case 0x018: /* DISPC_IRQSTATUS */ - s->dispc.irqst &= ~value; - omap_dispc_interrupt_update(s); - break; - - case 0x01c: /* DISPC_IRQENABLE */ - s->dispc.irqen = value & 0xffff; - omap_dispc_interrupt_update(s); - break; - - case 0x040: /* DISPC_CONTROL */ - s->dispc.control = value & 0x07ff9fff; - s->dig.enable = (value >> 1) & 1; - s->lcd.enable = (value >> 0) & 1; - if (value & (1 << 12)) /* OVERLAY_OPTIMIZATION */ - if (!((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1)) { - fprintf(stderr, "%s: Overlay Optimization when no overlay " - "region effectively exists leads to " - "unpredictable behaviour!\n", __func__); - } - if (value & (1 << 6)) { /* GODIGITAL */ - /* XXX: Shadowed fields are: - * s->dispc.config - * s->dispc.capable - * s->dispc.bg[0] - * s->dispc.bg[1] - * s->dispc.trans[0] - * s->dispc.trans[1] - * s->dispc.line - * s->dispc.timing[0] - * s->dispc.timing[1] - * s->dispc.timing[2] - * s->dispc.timing[3] - * s->lcd.nx - * s->lcd.ny - * s->dig.nx - * s->dig.ny - * s->dispc.l[0].addr[0] - * s->dispc.l[0].addr[1] - * s->dispc.l[0].addr[2] - * s->dispc.l[0].posx - * s->dispc.l[0].posy - * s->dispc.l[0].nx - * s->dispc.l[0].ny - * s->dispc.l[0].tresh - * s->dispc.l[0].rowinc - * s->dispc.l[0].colinc - * s->dispc.l[0].wininc - * All they need to be loaded here from their shadow registers. - */ - } - if (value & (1 << 5)) { /* GOLCD */ - /* XXX: Likewise for LCD here. */ - } - s->dispc.invalidate = 1; - break; - - case 0x044: /* DISPC_CONFIG */ - s->dispc.config = value & 0x3fff; - /* XXX: - * bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded - * bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded - */ - s->dispc.invalidate = 1; - break; - - case 0x048: /* DISPC_CAPABLE */ - s->dispc.capable = value & 0x3ff; - break; - - case 0x04c: /* DISPC_DEFAULT_COLOR0 */ - s->dispc.bg[0] = value & 0xffffff; - s->dispc.invalidate = 1; - break; - case 0x050: /* DISPC_DEFAULT_COLOR1 */ - s->dispc.bg[1] = value & 0xffffff; - s->dispc.invalidate = 1; - break; - case 0x054: /* DISPC_TRANS_COLOR0 */ - s->dispc.trans[0] = value & 0xffffff; - s->dispc.invalidate = 1; - break; - case 0x058: /* DISPC_TRANS_COLOR1 */ - s->dispc.trans[1] = value & 0xffffff; - s->dispc.invalidate = 1; - break; - - case 0x060: /* DISPC_LINE_NUMBER */ - s->dispc.line = value & 0x7ff; - break; - - case 0x064: /* DISPC_TIMING_H */ - s->dispc.timing[0] = value & 0x0ff0ff3f; - break; - case 0x068: /* DISPC_TIMING_V */ - s->dispc.timing[1] = value & 0x0ff0ff3f; - break; - case 0x06c: /* DISPC_POL_FREQ */ - s->dispc.timing[2] = value & 0x0003ffff; - break; - case 0x070: /* DISPC_DIVISOR */ - s->dispc.timing[3] = value & 0x00ff00ff; - break; - - case 0x078: /* DISPC_SIZE_DIG */ - s->dig.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */ - s->dig.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */ - s->dispc.invalidate = 1; - break; - case 0x07c: /* DISPC_SIZE_LCD */ - s->lcd.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */ - s->lcd.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */ - s->dispc.invalidate = 1; - break; - case 0x080: /* DISPC_GFX_BA0 */ - s->dispc.l[0].addr[0] = (hwaddr) value; - s->dispc.invalidate = 1; - break; - case 0x084: /* DISPC_GFX_BA1 */ - s->dispc.l[0].addr[1] = (hwaddr) value; - s->dispc.invalidate = 1; - break; - case 0x088: /* DISPC_GFX_POSITION */ - s->dispc.l[0].posx = ((value >> 0) & 0x7ff); /* GFXPOSX */ - s->dispc.l[0].posy = ((value >> 16) & 0x7ff); /* GFXPOSY */ - s->dispc.invalidate = 1; - break; - case 0x08c: /* DISPC_GFX_SIZE */ - s->dispc.l[0].nx = ((value >> 0) & 0x7ff) + 1; /* GFXSIZEX */ - s->dispc.l[0].ny = ((value >> 16) & 0x7ff) + 1; /* GFXSIZEY */ - s->dispc.invalidate = 1; - break; - case 0x0a0: /* DISPC_GFX_ATTRIBUTES */ - s->dispc.l[0].attr = value & 0x7ff; - if (value & (3 << 9)) - fprintf(stderr, "%s: Big-endian pixel format not supported\n", - __FUNCTION__); - s->dispc.l[0].enable = value & 1; - s->dispc.l[0].bpp = (value >> 1) & 0xf; - s->dispc.invalidate = 1; - break; - case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */ - s->dispc.l[0].tresh = value & 0x01ff01ff; - break; - case 0x0ac: /* DISPC_GFX_ROW_INC */ - s->dispc.l[0].rowinc = value; - s->dispc.invalidate = 1; - break; - case 0x0b0: /* DISPC_GFX_PIXEL_INC */ - s->dispc.l[0].colinc = value; - s->dispc.invalidate = 1; - break; - case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */ - s->dispc.l[0].wininc = value; - break; - case 0x0b8: /* DISPC_GFX_TABLE_BA */ - s->dispc.l[0].addr[2] = (hwaddr) value; - s->dispc.invalidate = 1; - break; - - case 0x0bc: /* DISPC_VID1_BA0 */ - case 0x0c0: /* DISPC_VID1_BA1 */ - case 0x0c4: /* DISPC_VID1_POSITION */ - case 0x0c8: /* DISPC_VID1_SIZE */ - case 0x0cc: /* DISPC_VID1_ATTRIBUTES */ - case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */ - case 0x0d8: /* DISPC_VID1_ROW_INC */ - case 0x0dc: /* DISPC_VID1_PIXEL_INC */ - case 0x0e0: /* DISPC_VID1_FIR */ - case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */ - case 0x0e8: /* DISPC_VID1_ACCU0 */ - case 0x0ec: /* DISPC_VID1_ACCU1 */ - case 0x0f0 ... 0x140: /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */ - case 0x14c: /* DISPC_VID2_BA0 */ - case 0x150: /* DISPC_VID2_BA1 */ - case 0x154: /* DISPC_VID2_POSITION */ - case 0x158: /* DISPC_VID2_SIZE */ - case 0x15c: /* DISPC_VID2_ATTRIBUTES */ - case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */ - case 0x168: /* DISPC_VID2_ROW_INC */ - case 0x16c: /* DISPC_VID2_PIXEL_INC */ - case 0x170: /* DISPC_VID2_FIR */ - case 0x174: /* DISPC_VID2_PICTURE_SIZE */ - case 0x178: /* DISPC_VID2_ACCU0 */ - case 0x17c: /* DISPC_VID2_ACCU1 */ - case 0x180 ... 0x1d0: /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */ - case 0x1d4: /* DISPC_DATA_CYCLE1 */ - case 0x1d8: /* DISPC_DATA_CYCLE2 */ - case 0x1dc: /* DISPC_DATA_CYCLE3 */ - break; - - default: - OMAP_BAD_REG(addr); - } -} - -static const MemoryRegionOps omap_disc_ops = { - .read = omap_disc_read, - .write = omap_disc_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void omap_rfbi_transfer_stop(struct omap_dss_s *s) -{ - if (!s->rfbi.busy) - return; - - /* TODO: in non-Bypass mode we probably need to just deassert the DRQ. */ - - s->rfbi.busy = 0; -} - -static void omap_rfbi_transfer_start(struct omap_dss_s *s) -{ - void *data; - hwaddr len; - hwaddr data_addr; - int pitch; - static void *bounce_buffer; - static hwaddr bounce_len; - - if (!s->rfbi.enable || s->rfbi.busy) - return; - - if (s->rfbi.control & (1 << 1)) { /* BYPASS */ - /* TODO: in non-Bypass mode we probably need to just assert the - * DRQ and wait for DMA to write the pixels. */ - fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__); - return; - } - - if (!(s->dispc.control & (1 << 11))) /* RFBIMODE */ - return; - /* TODO: check that LCD output is enabled in DISPC. */ - - s->rfbi.busy = 1; - - len = s->rfbi.pixels * 2; - - data_addr = s->dispc.l[0].addr[0]; - data = cpu_physical_memory_map(data_addr, &len, 0); - if (data && len != s->rfbi.pixels * 2) { - cpu_physical_memory_unmap(data, len, 0, 0); - data = NULL; - len = s->rfbi.pixels * 2; - } - if (!data) { - if (len > bounce_len) { - bounce_buffer = g_realloc(bounce_buffer, len); - } - data = bounce_buffer; - cpu_physical_memory_read(data_addr, data, len); - } - - /* TODO bpp */ - s->rfbi.pixels = 0; - - /* TODO: negative values */ - pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2; - - if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) - s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch); - if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) - s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch); - - if (data != bounce_buffer) { - cpu_physical_memory_unmap(data, len, 0, len); - } - - omap_rfbi_transfer_stop(s); - - /* TODO */ - s->dispc.irqst |= 1; /* FRAMEDONE */ - omap_dispc_interrupt_update(s); -} - -static uint64_t omap_rfbi_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap_dss_s *s = (struct omap_dss_s *) opaque; - - if (size != 4) { - return omap_badwidth_read32(opaque, addr); - } - - switch (addr) { - case 0x00: /* RFBI_REVISION */ - return 0x10; - - case 0x10: /* RFBI_SYSCONFIG */ - return s->rfbi.idlemode; - - case 0x14: /* RFBI_SYSSTATUS */ - return 1 | (s->rfbi.busy << 8); /* RESETDONE */ - - case 0x40: /* RFBI_CONTROL */ - return s->rfbi.control; - - case 0x44: /* RFBI_PIXELCNT */ - return s->rfbi.pixels; - - case 0x48: /* RFBI_LINE_NUMBER */ - return s->rfbi.skiplines; - - case 0x58: /* RFBI_READ */ - case 0x5c: /* RFBI_STATUS */ - return s->rfbi.rxbuf; - - case 0x60: /* RFBI_CONFIG0 */ - return s->rfbi.config[0]; - case 0x64: /* RFBI_ONOFF_TIME0 */ - return s->rfbi.time[0]; - case 0x68: /* RFBI_CYCLE_TIME0 */ - return s->rfbi.time[1]; - case 0x6c: /* RFBI_DATA_CYCLE1_0 */ - return s->rfbi.data[0]; - case 0x70: /* RFBI_DATA_CYCLE2_0 */ - return s->rfbi.data[1]; - case 0x74: /* RFBI_DATA_CYCLE3_0 */ - return s->rfbi.data[2]; - - case 0x78: /* RFBI_CONFIG1 */ - return s->rfbi.config[1]; - case 0x7c: /* RFBI_ONOFF_TIME1 */ - return s->rfbi.time[2]; - case 0x80: /* RFBI_CYCLE_TIME1 */ - return s->rfbi.time[3]; - case 0x84: /* RFBI_DATA_CYCLE1_1 */ - return s->rfbi.data[3]; - case 0x88: /* RFBI_DATA_CYCLE2_1 */ - return s->rfbi.data[4]; - case 0x8c: /* RFBI_DATA_CYCLE3_1 */ - return s->rfbi.data[5]; - - case 0x90: /* RFBI_VSYNC_WIDTH */ - return s->rfbi.vsync; - case 0x94: /* RFBI_HSYNC_WIDTH */ - return s->rfbi.hsync; - } - OMAP_BAD_REG(addr); - return 0; -} - -static void omap_rfbi_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - struct omap_dss_s *s = (struct omap_dss_s *) opaque; - - if (size != 4) { - omap_badwidth_write32(opaque, addr, value); - return; - } - - switch (addr) { - case 0x10: /* RFBI_SYSCONFIG */ - if (value & 2) /* SOFTRESET */ - omap_rfbi_reset(s); - s->rfbi.idlemode = value & 0x19; - break; - - case 0x40: /* RFBI_CONTROL */ - s->rfbi.control = value & 0xf; - s->rfbi.enable = value & 1; - if (value & (1 << 4) && /* ITE */ - !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc)) - omap_rfbi_transfer_start(s); - break; - - case 0x44: /* RFBI_PIXELCNT */ - s->rfbi.pixels = value; - break; - - case 0x48: /* RFBI_LINE_NUMBER */ - s->rfbi.skiplines = value & 0x7ff; - break; - - case 0x4c: /* RFBI_CMD */ - if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) - s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff); - if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) - s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff); - break; - case 0x50: /* RFBI_PARAM */ - if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) - s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff); - if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) - s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff); - break; - case 0x54: /* RFBI_DATA */ - /* TODO: take into account the format set up in s->rfbi.config[?] and - * s->rfbi.data[?], but special-case the most usual scenario so that - * speed doesn't suffer. */ - if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) { - s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff); - s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16); - } - if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) { - s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff); - s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16); - } - if (!-- s->rfbi.pixels) - omap_rfbi_transfer_stop(s); - break; - case 0x58: /* RFBI_READ */ - if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) - s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1); - else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) - s->rfbi.rxbuf = s->rfbi.chip[1]->read(s->rfbi.chip[1]->opaque, 1); - if (!-- s->rfbi.pixels) - omap_rfbi_transfer_stop(s); - break; - - case 0x5c: /* RFBI_STATUS */ - if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) - s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0); - else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) - s->rfbi.rxbuf = s->rfbi.chip[1]->read(s->rfbi.chip[1]->opaque, 0); - if (!-- s->rfbi.pixels) - omap_rfbi_transfer_stop(s); - break; - - case 0x60: /* RFBI_CONFIG0 */ - s->rfbi.config[0] = value & 0x003f1fff; - break; - - case 0x64: /* RFBI_ONOFF_TIME0 */ - s->rfbi.time[0] = value & 0x3fffffff; - break; - case 0x68: /* RFBI_CYCLE_TIME0 */ - s->rfbi.time[1] = value & 0x0fffffff; - break; - case 0x6c: /* RFBI_DATA_CYCLE1_0 */ - s->rfbi.data[0] = value & 0x0f1f0f1f; - break; - case 0x70: /* RFBI_DATA_CYCLE2_0 */ - s->rfbi.data[1] = value & 0x0f1f0f1f; - break; - case 0x74: /* RFBI_DATA_CYCLE3_0 */ - s->rfbi.data[2] = value & 0x0f1f0f1f; - break; - case 0x78: /* RFBI_CONFIG1 */ - s->rfbi.config[1] = value & 0x003f1fff; - break; - - case 0x7c: /* RFBI_ONOFF_TIME1 */ - s->rfbi.time[2] = value & 0x3fffffff; - break; - case 0x80: /* RFBI_CYCLE_TIME1 */ - s->rfbi.time[3] = value & 0x0fffffff; - break; - case 0x84: /* RFBI_DATA_CYCLE1_1 */ - s->rfbi.data[3] = value & 0x0f1f0f1f; - break; - case 0x88: /* RFBI_DATA_CYCLE2_1 */ - s->rfbi.data[4] = value & 0x0f1f0f1f; - break; - case 0x8c: /* RFBI_DATA_CYCLE3_1 */ - s->rfbi.data[5] = value & 0x0f1f0f1f; - break; - - case 0x90: /* RFBI_VSYNC_WIDTH */ - s->rfbi.vsync = value & 0xffff; - break; - case 0x94: /* RFBI_HSYNC_WIDTH */ - s->rfbi.hsync = value & 0xffff; - break; - - default: - OMAP_BAD_REG(addr); - } -} - -static const MemoryRegionOps omap_rfbi_ops = { - .read = omap_rfbi_read, - .write = omap_rfbi_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static uint64_t omap_venc_read(void *opaque, hwaddr addr, - unsigned size) -{ - if (size != 4) { - return omap_badwidth_read32(opaque, addr); - } - - switch (addr) { - case 0x00: /* REV_ID */ - case 0x04: /* STATUS */ - case 0x08: /* F_CONTROL */ - case 0x10: /* VIDOUT_CTRL */ - case 0x14: /* SYNC_CTRL */ - case 0x1c: /* LLEN */ - case 0x20: /* FLENS */ - case 0x24: /* HFLTR_CTRL */ - case 0x28: /* CC_CARR_WSS_CARR */ - case 0x2c: /* C_PHASE */ - case 0x30: /* GAIN_U */ - case 0x34: /* GAIN_V */ - case 0x38: /* GAIN_Y */ - case 0x3c: /* BLACK_LEVEL */ - case 0x40: /* BLANK_LEVEL */ - case 0x44: /* X_COLOR */ - case 0x48: /* M_CONTROL */ - case 0x4c: /* BSTAMP_WSS_DATA */ - case 0x50: /* S_CARR */ - case 0x54: /* LINE21 */ - case 0x58: /* LN_SEL */ - case 0x5c: /* L21__WC_CTL */ - case 0x60: /* HTRIGGER_VTRIGGER */ - case 0x64: /* SAVID__EAVID */ - case 0x68: /* FLEN__FAL */ - case 0x6c: /* LAL__PHASE_RESET */ - case 0x70: /* HS_INT_START_STOP_X */ - case 0x74: /* HS_EXT_START_STOP_X */ - case 0x78: /* VS_INT_START_X */ - case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */ - case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */ - case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */ - case 0x88: /* VS_EXT_STOP_Y */ - case 0x90: /* AVID_START_STOP_X */ - case 0x94: /* AVID_START_STOP_Y */ - case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */ - case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */ - case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */ - case 0xb0: /* TVDETGP_INT_START_STOP_X */ - case 0xb4: /* TVDETGP_INT_START_STOP_Y */ - case 0xb8: /* GEN_CTRL */ - case 0xc4: /* DAC_TST__DAC_A */ - case 0xc8: /* DAC_B__DAC_C */ - return 0; - - default: - break; - } - OMAP_BAD_REG(addr); - return 0; -} - -static void omap_venc_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - if (size != 4) { - omap_badwidth_write32(opaque, addr, size); - return; - } - - switch (addr) { - case 0x08: /* F_CONTROL */ - case 0x10: /* VIDOUT_CTRL */ - case 0x14: /* SYNC_CTRL */ - case 0x1c: /* LLEN */ - case 0x20: /* FLENS */ - case 0x24: /* HFLTR_CTRL */ - case 0x28: /* CC_CARR_WSS_CARR */ - case 0x2c: /* C_PHASE */ - case 0x30: /* GAIN_U */ - case 0x34: /* GAIN_V */ - case 0x38: /* GAIN_Y */ - case 0x3c: /* BLACK_LEVEL */ - case 0x40: /* BLANK_LEVEL */ - case 0x44: /* X_COLOR */ - case 0x48: /* M_CONTROL */ - case 0x4c: /* BSTAMP_WSS_DATA */ - case 0x50: /* S_CARR */ - case 0x54: /* LINE21 */ - case 0x58: /* LN_SEL */ - case 0x5c: /* L21__WC_CTL */ - case 0x60: /* HTRIGGER_VTRIGGER */ - case 0x64: /* SAVID__EAVID */ - case 0x68: /* FLEN__FAL */ - case 0x6c: /* LAL__PHASE_RESET */ - case 0x70: /* HS_INT_START_STOP_X */ - case 0x74: /* HS_EXT_START_STOP_X */ - case 0x78: /* VS_INT_START_X */ - case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */ - case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */ - case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */ - case 0x88: /* VS_EXT_STOP_Y */ - case 0x90: /* AVID_START_STOP_X */ - case 0x94: /* AVID_START_STOP_Y */ - case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */ - case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */ - case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */ - case 0xb0: /* TVDETGP_INT_START_STOP_X */ - case 0xb4: /* TVDETGP_INT_START_STOP_Y */ - case 0xb8: /* GEN_CTRL */ - case 0xc4: /* DAC_TST__DAC_A */ - case 0xc8: /* DAC_B__DAC_C */ - break; - - default: - OMAP_BAD_REG(addr); - } -} - -static const MemoryRegionOps omap_venc_ops = { - .read = omap_venc_read, - .write = omap_venc_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static uint64_t omap_im3_read(void *opaque, hwaddr addr, - unsigned size) -{ - if (size != 4) { - return omap_badwidth_read32(opaque, addr); - } - - switch (addr) { - case 0x0a8: /* SBIMERRLOGA */ - case 0x0b0: /* SBIMERRLOG */ - case 0x190: /* SBIMSTATE */ - case 0x198: /* SBTMSTATE_L */ - case 0x19c: /* SBTMSTATE_H */ - case 0x1a8: /* SBIMCONFIG_L */ - case 0x1ac: /* SBIMCONFIG_H */ - case 0x1f8: /* SBID_L */ - case 0x1fc: /* SBID_H */ - return 0; - - default: - break; - } - OMAP_BAD_REG(addr); - return 0; -} - -static void omap_im3_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - if (size != 4) { - omap_badwidth_write32(opaque, addr, value); - return; - } - - switch (addr) { - case 0x0b0: /* SBIMERRLOG */ - case 0x190: /* SBIMSTATE */ - case 0x198: /* SBTMSTATE_L */ - case 0x19c: /* SBTMSTATE_H */ - case 0x1a8: /* SBIMCONFIG_L */ - case 0x1ac: /* SBIMCONFIG_H */ - break; - - default: - OMAP_BAD_REG(addr); - } -} - -static const MemoryRegionOps omap_im3_ops = { - .read = omap_im3_read, - .write = omap_im3_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta, - MemoryRegion *sysmem, - hwaddr l3_base, - qemu_irq irq, qemu_irq drq, - omap_clk fck1, omap_clk fck2, omap_clk ck54m, - omap_clk ick1, omap_clk ick2) -{ - struct omap_dss_s *s = g_new0(struct omap_dss_s, 1); - - s->irq = irq; - s->drq = drq; - omap_dss_reset(s); - - memory_region_init_io(&s->iomem_diss1, NULL, &omap_diss_ops, s, "omap.diss1", - omap_l4_region_size(ta, 0)); - memory_region_init_io(&s->iomem_disc1, NULL, &omap_disc_ops, s, "omap.disc1", - omap_l4_region_size(ta, 1)); - memory_region_init_io(&s->iomem_rfbi1, NULL, &omap_rfbi_ops, s, "omap.rfbi1", - omap_l4_region_size(ta, 2)); - memory_region_init_io(&s->iomem_venc1, NULL, &omap_venc_ops, s, "omap.venc1", - omap_l4_region_size(ta, 3)); - memory_region_init_io(&s->iomem_im3, NULL, &omap_im3_ops, s, - "omap.im3", 0x1000); - - omap_l4_attach(ta, 0, &s->iomem_diss1); - omap_l4_attach(ta, 1, &s->iomem_disc1); - omap_l4_attach(ta, 2, &s->iomem_rfbi1); - omap_l4_attach(ta, 3, &s->iomem_venc1); - memory_region_add_subregion(sysmem, l3_base, &s->iomem_im3); - -#if 0 - s->state = graphic_console_init(omap_update_display, - omap_invalidate_display, omap_screen_dump, s); -#endif - - return s; -} - -void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip) -{ - if (cs < 0 || cs > 1) - hw_error("%s: wrong CS %i\n", __FUNCTION__, cs); - s->rfbi.chip[cs] = chip; -} diff --git a/qemu/hw/display/omap_lcd_template.h b/qemu/hw/display/omap_lcd_template.h deleted file mode 100644 index f0ce71fd6..000000000 --- a/qemu/hw/display/omap_lcd_template.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * QEMU OMAP LCD Emulator templates - * - * Copyright (c) 2006 Andrzej Zaborowski - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if DEPTH == 8 -# define BPP 1 -# define PIXEL_TYPE uint8_t -#elif DEPTH == 15 || DEPTH == 16 -# define BPP 2 -# define PIXEL_TYPE uint16_t -#elif DEPTH == 32 -# define BPP 4 -# define PIXEL_TYPE uint32_t -#else -# error unsupport depth -#endif - -/* - * 2-bit colour - */ -static void glue(draw_line2_, DEPTH)(void *opaque, - uint8_t *d, const uint8_t *s, int width, int deststep) -{ - uint16_t *pal = opaque; - uint8_t v, r, g, b; - - do { - v = ldub_p((void *) s); - r = (pal[v & 3] >> 4) & 0xf0; - g = pal[v & 3] & 0xf0; - b = (pal[v & 3] << 4) & 0xf0; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - d += BPP; - v >>= 2; - r = (pal[v & 3] >> 4) & 0xf0; - g = pal[v & 3] & 0xf0; - b = (pal[v & 3] << 4) & 0xf0; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - d += BPP; - v >>= 2; - r = (pal[v & 3] >> 4) & 0xf0; - g = pal[v & 3] & 0xf0; - b = (pal[v & 3] << 4) & 0xf0; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - d += BPP; - v >>= 2; - r = (pal[v & 3] >> 4) & 0xf0; - g = pal[v & 3] & 0xf0; - b = (pal[v & 3] << 4) & 0xf0; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - d += BPP; - s ++; - width -= 4; - } while (width > 0); -} - -/* - * 4-bit colour - */ -static void glue(draw_line4_, DEPTH)(void *opaque, - uint8_t *d, const uint8_t *s, int width, int deststep) -{ - uint16_t *pal = opaque; - uint8_t v, r, g, b; - - do { - v = ldub_p((void *) s); - r = (pal[v & 0xf] >> 4) & 0xf0; - g = pal[v & 0xf] & 0xf0; - b = (pal[v & 0xf] << 4) & 0xf0; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - d += BPP; - v >>= 4; - r = (pal[v & 0xf] >> 4) & 0xf0; - g = pal[v & 0xf] & 0xf0; - b = (pal[v & 0xf] << 4) & 0xf0; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - d += BPP; - s ++; - width -= 2; - } while (width > 0); -} - -/* - * 8-bit colour - */ -static void glue(draw_line8_, DEPTH)(void *opaque, - uint8_t *d, const uint8_t *s, int width, int deststep) -{ - uint16_t *pal = opaque; - uint8_t v, r, g, b; - - do { - v = ldub_p((void *) s); - r = (pal[v] >> 4) & 0xf0; - g = pal[v] & 0xf0; - b = (pal[v] << 4) & 0xf0; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - s ++; - d += BPP; - } while (-- width != 0); -} - -/* - * 12-bit colour - */ -static void glue(draw_line12_, DEPTH)(void *opaque, - uint8_t *d, const uint8_t *s, int width, int deststep) -{ - uint16_t v; - uint8_t r, g, b; - - do { - v = lduw_le_p((void *) s); - r = (v >> 4) & 0xf0; - g = v & 0xf0; - b = (v << 4) & 0xf0; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - s += 2; - d += BPP; - } while (-- width != 0); -} - -/* - * 16-bit colour - */ -static void glue(draw_line16_, DEPTH)(void *opaque, - uint8_t *d, const uint8_t *s, int width, int deststep) -{ -#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) - memcpy(d, s, width * 2); -#else - uint16_t v; - uint8_t r, g, b; - - do { - v = lduw_le_p((void *) s); - r = (v >> 8) & 0xf8; - g = (v >> 3) & 0xfc; - b = (v << 3) & 0xf8; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - s += 2; - d += BPP; - } while (-- width != 0); -#endif -} - -#undef DEPTH -#undef BPP -#undef PIXEL_TYPE diff --git a/qemu/hw/display/omap_lcdc.c b/qemu/hw/display/omap_lcdc.c deleted file mode 100644 index ce1058bf8..000000000 --- a/qemu/hw/display/omap_lcdc.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * OMAP LCD controller. - * - * Copyright (C) 2006-2007 Andrzej Zaborowski - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "ui/console.h" -#include "hw/arm/omap.h" -#include "framebuffer.h" -#include "ui/pixel_ops.h" - -struct omap_lcd_panel_s { - MemoryRegion *sysmem; - MemoryRegion iomem; - MemoryRegionSection fbsection; - qemu_irq irq; - QemuConsole *con; - - int plm; - int tft; - int mono; - int enable; - int width; - int height; - int interrupts; - uint32_t timing[3]; - uint32_t subpanel; - uint32_t ctrl; - - struct omap_dma_lcd_channel_s *dma; - uint16_t palette[256]; - int palette_done; - int frame_done; - int invalidate; - int sync_error; -}; - -static void omap_lcd_interrupts(struct omap_lcd_panel_s *s) -{ - if (s->frame_done && (s->interrupts & 1)) { - qemu_irq_raise(s->irq); - return; - } - - if (s->palette_done && (s->interrupts & 2)) { - qemu_irq_raise(s->irq); - return; - } - - if (s->sync_error) { - qemu_irq_raise(s->irq); - return; - } - - qemu_irq_lower(s->irq); -} - -#define draw_line_func drawfn - -#define DEPTH 8 -#include "omap_lcd_template.h" -#define DEPTH 15 -#include "omap_lcd_template.h" -#define DEPTH 16 -#include "omap_lcd_template.h" -#define DEPTH 32 -#include "omap_lcd_template.h" - -static draw_line_func draw_line_table2[33] = { - [0 ... 32] = NULL, - [8] = draw_line2_8, - [15] = draw_line2_15, - [16] = draw_line2_16, - [32] = draw_line2_32, -}, draw_line_table4[33] = { - [0 ... 32] = NULL, - [8] = draw_line4_8, - [15] = draw_line4_15, - [16] = draw_line4_16, - [32] = draw_line4_32, -}, draw_line_table8[33] = { - [0 ... 32] = NULL, - [8] = draw_line8_8, - [15] = draw_line8_15, - [16] = draw_line8_16, - [32] = draw_line8_32, -}, draw_line_table12[33] = { - [0 ... 32] = NULL, - [8] = draw_line12_8, - [15] = draw_line12_15, - [16] = draw_line12_16, - [32] = draw_line12_32, -}, draw_line_table16[33] = { - [0 ... 32] = NULL, - [8] = draw_line16_8, - [15] = draw_line16_15, - [16] = draw_line16_16, - [32] = draw_line16_32, -}; - -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 || - !surface_bits_per_pixel(surface)) { - return; - } - - frame_offset = 0; - if (omap_lcd->plm != 2) { - cpu_physical_memory_read(omap_lcd->dma->phys_framebuffer[ - omap_lcd->dma->current_frame], - (void *)omap_lcd->palette, 0x200); - switch (omap_lcd->palette[0] >> 12 & 7) { - case 3 ... 7: - frame_offset += 0x200; - break; - default: - frame_offset += 0x20; - } - } - - /* Colour depth */ - switch ((omap_lcd->palette[0] >> 12) & 7) { - case 1: - draw_line = draw_line_table2[surface_bits_per_pixel(surface)]; - bpp = 2; - break; - - case 2: - draw_line = draw_line_table4[surface_bits_per_pixel(surface)]; - bpp = 4; - break; - - case 3: - 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[surface_bits_per_pixel(surface)]; - else - draw_line = draw_line_table16[surface_bits_per_pixel(surface)]; - bpp = 16; - break; - - default: - /* Unsupported at the moment. */ - return; - } - - /* Resolution */ - width = omap_lcd->width; - 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; - } - - if (omap_lcd->dma->current_frame == 0) - size = omap_lcd->dma->src_f1_bottom - omap_lcd->dma->src_f1_top; - else - size = omap_lcd->dma->src_f2_bottom - omap_lcd->dma->src_f2_top; - - if (frame_offset + ((width * omap_lcd->height * bpp) >> 3) > size + 2) { - omap_lcd->sync_error = 1; - omap_lcd_interrupts(omap_lcd); - omap_lcd->enable = 0; - return; - } - - /* Content */ - frame_base = omap_lcd->dma->phys_framebuffer[ - omap_lcd->dma->current_frame] + frame_offset; - omap_lcd->dma->condition |= 1 << omap_lcd->dma->current_frame; - if (omap_lcd->dma->interrupts & 1) - qemu_irq_raise(omap_lcd->dma->irq); - if (omap_lcd->dma->dual) - omap_lcd->dma->current_frame ^= 1; - - if (!surface_bits_per_pixel(surface)) { - return; - } - - first = 0; - height = omap_lcd->height; - if (omap_lcd->subpanel & (1 << 31)) { - if (omap_lcd->subpanel & (1 << 29)) - first = (omap_lcd->subpanel >> 16) & 0x3ff; - else - height = (omap_lcd->subpanel >> 16) & 0x3ff; - /* TODO: fill the rest of the panel with DPD */ - } - - step = width * bpp >> 3; - linesize = surface_stride(surface); - if (omap_lcd->invalidate) { - framebuffer_update_memory_section(&omap_lcd->fbsection, - omap_lcd->sysmem, frame_base, - height, step); - } - - framebuffer_update_display(surface, &omap_lcd->fbsection, - width, height, - step, linesize, 0, - omap_lcd->invalidate, - draw_line, omap_lcd->palette, - &first, &last); - - if (first >= 0) { - dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1); - } - omap_lcd->invalidate = 0; -} - -static void omap_invalidate_display(void *opaque) { - struct omap_lcd_panel_s *omap_lcd = opaque; - omap_lcd->invalidate = 1; -} - -static void omap_lcd_update(struct omap_lcd_panel_s *s) { - if (!s->enable) { - s->dma->current_frame = -1; - s->sync_error = 0; - if (s->plm != 1) - s->frame_done = 1; - omap_lcd_interrupts(s); - return; - } - - if (s->dma->current_frame == -1) { - s->frame_done = 0; - s->palette_done = 0; - s->dma->current_frame = 0; - } - - if (!s->dma->mpu->port[s->dma->src].addr_valid(s->dma->mpu, - s->dma->src_f1_top) || - !s->dma->mpu->port[ - s->dma->src].addr_valid(s->dma->mpu, - s->dma->src_f1_bottom) || - (s->dma->dual && - (!s->dma->mpu->port[ - s->dma->src].addr_valid(s->dma->mpu, - s->dma->src_f2_top) || - !s->dma->mpu->port[ - s->dma->src].addr_valid(s->dma->mpu, - s->dma->src_f2_bottom)))) { - s->dma->condition |= 1 << 2; - if (s->dma->interrupts & (1 << 1)) - qemu_irq_raise(s->dma->irq); - s->enable = 0; - return; - } - - s->dma->phys_framebuffer[0] = s->dma->src_f1_top; - s->dma->phys_framebuffer[1] = s->dma->src_f2_top; - - if (s->plm != 2 && !s->palette_done) { - cpu_physical_memory_read( - s->dma->phys_framebuffer[s->dma->current_frame], - (void *)s->palette, 0x200); - s->palette_done = 1; - omap_lcd_interrupts(s); - } -} - -static uint64_t omap_lcdc_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque; - - switch (addr) { - case 0x00: /* LCD_CONTROL */ - return (s->tft << 23) | (s->plm << 20) | - (s->tft << 7) | (s->interrupts << 3) | - (s->mono << 1) | s->enable | s->ctrl | 0xfe000c34; - - case 0x04: /* LCD_TIMING0 */ - return (s->timing[0] << 10) | (s->width - 1) | 0x0000000f; - - case 0x08: /* LCD_TIMING1 */ - return (s->timing[1] << 10) | (s->height - 1); - - case 0x0c: /* LCD_TIMING2 */ - return s->timing[2] | 0xfc000000; - - case 0x10: /* LCD_STATUS */ - return (s->palette_done << 6) | (s->sync_error << 2) | s->frame_done; - - case 0x14: /* LCD_SUBPANEL */ - return s->subpanel; - - default: - break; - } - OMAP_BAD_REG(addr); - return 0; -} - -static void omap_lcdc_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque; - - switch (addr) { - case 0x00: /* LCD_CONTROL */ - s->plm = (value >> 20) & 3; - s->tft = (value >> 7) & 1; - s->interrupts = (value >> 3) & 3; - s->mono = (value >> 1) & 1; - s->ctrl = value & 0x01cff300; - if (s->enable != (value & 1)) { - s->enable = value & 1; - omap_lcd_update(s); - } - break; - - case 0x04: /* LCD_TIMING0 */ - s->timing[0] = value >> 10; - s->width = (value & 0x3ff) + 1; - break; - - case 0x08: /* LCD_TIMING1 */ - s->timing[1] = value >> 10; - s->height = (value & 0x3ff) + 1; - break; - - case 0x0c: /* LCD_TIMING2 */ - s->timing[2] = value; - break; - - case 0x10: /* LCD_STATUS */ - break; - - case 0x14: /* LCD_SUBPANEL */ - s->subpanel = value & 0xa1ffffff; - break; - - default: - OMAP_BAD_REG(addr); - } -} - -static const MemoryRegionOps omap_lcdc_ops = { - .read = omap_lcdc_read, - .write = omap_lcdc_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -void omap_lcdc_reset(struct omap_lcd_panel_s *s) -{ - s->dma->current_frame = -1; - s->plm = 0; - s->tft = 0; - s->mono = 0; - s->enable = 0; - s->width = 0; - s->height = 0; - s->interrupts = 0; - s->timing[0] = 0; - s->timing[1] = 0; - s->timing[2] = 0; - s->subpanel = 0; - s->palette_done = 0; - s->frame_done = 0; - s->sync_error = 0; - s->invalidate = 1; - s->subpanel = 0; - s->ctrl = 0; -} - -static const GraphicHwOps omap_ops = { - .invalidate = omap_invalidate_display, - .gfx_update = omap_update_display, -}; - -struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem, - hwaddr base, - qemu_irq irq, - struct omap_dma_lcd_channel_s *dma, - omap_clk clk) -{ - struct omap_lcd_panel_s *s = g_new0(struct omap_lcd_panel_s, 1); - - s->irq = irq; - s->dma = dma; - s->sysmem = sysmem; - omap_lcdc_reset(s); - - memory_region_init_io(&s->iomem, NULL, &omap_lcdc_ops, s, "omap.lcdc", 0x100); - memory_region_add_subregion(sysmem, base, &s->iomem); - - s->con = graphic_console_init(NULL, 0, &omap_ops, s); - - return s; -} diff --git a/qemu/hw/display/pl110.c b/qemu/hw/display/pl110.c deleted file mode 100644 index d589959f1..000000000 --- a/qemu/hw/display/pl110.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Arm PrimeCell PL110 Color LCD Controller - * - * Copyright (c) 2005-2009 CodeSourcery. - * Written by Paul Brook - * - * This code is licensed under the GNU LGPL - */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" -#include "ui/console.h" -#include "framebuffer.h" -#include "ui/pixel_ops.h" - -#define PL110_CR_EN 0x001 -#define PL110_CR_BGR 0x100 -#define PL110_CR_BEBO 0x200 -#define PL110_CR_BEPO 0x400 -#define PL110_CR_PWR 0x800 - -enum pl110_bppmode -{ - BPP_1, - BPP_2, - BPP_4, - BPP_8, - BPP_16, - BPP_32, - BPP_16_565, /* PL111 only */ - BPP_12 /* PL111 only */ -}; - - -/* The Versatile/PB uses a slightly modified PL110 controller. */ -enum pl110_version -{ - PL110, - PL110_VERSATILE, - PL111 -}; - -#define TYPE_PL110 "pl110" -#define PL110(obj) OBJECT_CHECK(PL110State, (obj), TYPE_PL110) - -typedef struct PL110State { - SysBusDevice parent_obj; - - MemoryRegion iomem; - MemoryRegionSection fbsection; - QemuConsole *con; - - int version; - uint32_t timing[4]; - uint32_t cr; - uint32_t upbase; - uint32_t lpbase; - uint32_t int_status; - uint32_t int_mask; - int cols; - int rows; - enum pl110_bppmode bpp; - int invalidate; - uint32_t mux_ctrl; - uint32_t palette[256]; - uint32_t raw_palette[128]; - qemu_irq irq; -} PL110State; - -static int vmstate_pl110_post_load(void *opaque, int version_id); - -static const VMStateDescription vmstate_pl110 = { - .name = "pl110", - .version_id = 2, - .minimum_version_id = 1, - .post_load = vmstate_pl110_post_load, - .fields = (VMStateField[]) { - VMSTATE_INT32(version, PL110State), - VMSTATE_UINT32_ARRAY(timing, PL110State, 4), - VMSTATE_UINT32(cr, PL110State), - VMSTATE_UINT32(upbase, PL110State), - VMSTATE_UINT32(lpbase, PL110State), - VMSTATE_UINT32(int_status, PL110State), - VMSTATE_UINT32(int_mask, PL110State), - VMSTATE_INT32(cols, PL110State), - VMSTATE_INT32(rows, PL110State), - VMSTATE_UINT32(bpp, PL110State), - VMSTATE_INT32(invalidate, PL110State), - VMSTATE_UINT32_ARRAY(palette, PL110State, 256), - VMSTATE_UINT32_ARRAY(raw_palette, PL110State, 128), - VMSTATE_UINT32_V(mux_ctrl, PL110State, 2), - VMSTATE_END_OF_LIST() - } -}; - -static const unsigned char pl110_id[] = -{ 0x10, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; - -static const unsigned char pl111_id[] = { - 0x11, 0x11, 0x24, 0x00, 0x0d, 0xf0, 0x05, 0xb1 -}; - - -/* Indexed by pl110_version */ -static const unsigned char *idregs[] = { - pl110_id, - /* The ARM documentation (DDI0224C) says the CLCDC on the Versatile board - * has a different ID (0x93, 0x10, 0x04, 0x00, ...). However the hardware - * itself has the same ID values as a stock PL110, and guests (in - * particular Linux) rely on this. We emulate what the hardware does, - * rather than what the docs claim it ought to do. - */ - pl110_id, - pl111_id -}; - -#define BITS 8 -#include "pl110_template.h" -#define BITS 15 -#include "pl110_template.h" -#define BITS 16 -#include "pl110_template.h" -#define BITS 24 -#include "pl110_template.h" -#define BITS 32 -#include "pl110_template.h" - -static int pl110_enabled(PL110State *s) -{ - return (s->cr & PL110_CR_EN) && (s->cr & PL110_CR_PWR); -} - -static void pl110_update_display(void *opaque) -{ - PL110State *s = (PL110State *)opaque; - SysBusDevice *sbd; - DisplaySurface *surface = qemu_console_surface(s->con); - drawfn* fntable; - drawfn fn; - int dest_width; - int src_width; - int bpp_offset; - int first; - int last; - - if (!pl110_enabled(s)) { - return; - } - - sbd = SYS_BUS_DEVICE(s); - - switch (surface_bits_per_pixel(surface)) { - case 0: - return; - case 8: - fntable = pl110_draw_fn_8; - dest_width = 1; - break; - case 15: - fntable = pl110_draw_fn_15; - dest_width = 2; - break; - case 16: - fntable = pl110_draw_fn_16; - dest_width = 2; - break; - case 24: - fntable = pl110_draw_fn_24; - dest_width = 3; - break; - case 32: - fntable = pl110_draw_fn_32; - dest_width = 4; - break; - default: - fprintf(stderr, "pl110: Bad color depth\n"); - exit(1); - } - if (s->cr & PL110_CR_BGR) - bpp_offset = 0; - else - bpp_offset = 24; - - if ((s->version != PL111) && (s->bpp == BPP_16)) { - /* The PL110's native 16 bit mode is 5551; however - * most boards with a PL110 implement an external - * mux which allows bits to be reshuffled to give - * 565 format. The mux is typically controlled by - * an external system register. - * This is controlled by a GPIO input pin - * so boards can wire it up to their register. - * - * The PL111 straightforwardly implements both - * 5551 and 565 under control of the bpp field - * in the LCDControl register. - */ - switch (s->mux_ctrl) { - case 3: /* 565 BGR */ - bpp_offset = (BPP_16_565 - BPP_16); - break; - case 1: /* 5551 */ - break; - case 0: /* 888; also if we have loaded vmstate from an old version */ - case 2: /* 565 RGB */ - default: - /* treat as 565 but honour BGR bit */ - bpp_offset += (BPP_16_565 - BPP_16); - break; - } - } - - if (s->cr & PL110_CR_BEBO) - fn = fntable[s->bpp + 8 + bpp_offset]; - else if (s->cr & PL110_CR_BEPO) - fn = fntable[s->bpp + 16 + bpp_offset]; - else - fn = fntable[s->bpp + bpp_offset]; - - src_width = s->cols; - switch (s->bpp) { - case BPP_1: - src_width >>= 3; - break; - case BPP_2: - src_width >>= 2; - break; - case BPP_4: - src_width >>= 1; - break; - case BPP_8: - break; - case BPP_16: - case BPP_16_565: - case BPP_12: - src_width <<= 1; - break; - case BPP_32: - src_width <<= 2; - break; - } - dest_width *= s->cols; - first = 0; - if (s->invalidate) { - framebuffer_update_memory_section(&s->fbsection, - sysbus_address_space(sbd), - s->upbase, - s->rows, src_width); - } - - framebuffer_update_display(surface, &s->fbsection, - s->cols, s->rows, - src_width, dest_width, 0, - s->invalidate, - fn, s->palette, - &first, &last); - - if (first >= 0) { - dpy_gfx_update(s->con, 0, first, s->cols, last - first + 1); - } - s->invalidate = 0; -} - -static void pl110_invalidate_display(void * opaque) -{ - PL110State *s = (PL110State *)opaque; - s->invalidate = 1; - if (pl110_enabled(s)) { - qemu_console_resize(s->con, s->cols, s->rows); - } -} - -static void pl110_update_palette(PL110State *s, int n) -{ - DisplaySurface *surface = qemu_console_surface(s->con); - int i; - uint32_t raw; - unsigned int r, g, b; - - raw = s->raw_palette[n]; - n <<= 1; - for (i = 0; i < 2; i++) { - r = (raw & 0x1f) << 3; - raw >>= 5; - g = (raw & 0x1f) << 3; - raw >>= 5; - b = (raw & 0x1f) << 3; - /* The I bit is ignored. */ - raw >>= 6; - switch (surface_bits_per_pixel(surface)) { - case 8: - s->palette[n] = rgb_to_pixel8(r, g, b); - break; - case 15: - s->palette[n] = rgb_to_pixel15(r, g, b); - break; - case 16: - s->palette[n] = rgb_to_pixel16(r, g, b); - break; - case 24: - case 32: - s->palette[n] = rgb_to_pixel32(r, g, b); - break; - } - n++; - } -} - -static void pl110_resize(PL110State *s, int width, int height) -{ - if (width != s->cols || height != s->rows) { - if (pl110_enabled(s)) { - qemu_console_resize(s->con, width, height); - } - } - s->cols = width; - s->rows = height; -} - -/* Update interrupts. */ -static void pl110_update(PL110State *s) -{ - /* TODO: Implement interrupts. */ -} - -static uint64_t pl110_read(void *opaque, hwaddr offset, - unsigned size) -{ - PL110State *s = (PL110State *)opaque; - - if (offset >= 0xfe0 && offset < 0x1000) { - return idregs[s->version][(offset - 0xfe0) >> 2]; - } - if (offset >= 0x200 && offset < 0x400) { - return s->raw_palette[(offset - 0x200) >> 2]; - } - switch (offset >> 2) { - case 0: /* LCDTiming0 */ - return s->timing[0]; - case 1: /* LCDTiming1 */ - return s->timing[1]; - case 2: /* LCDTiming2 */ - return s->timing[2]; - case 3: /* LCDTiming3 */ - return s->timing[3]; - case 4: /* LCDUPBASE */ - return s->upbase; - case 5: /* LCDLPBASE */ - return s->lpbase; - case 6: /* LCDIMSC */ - if (s->version != PL110) { - return s->cr; - } - return s->int_mask; - case 7: /* LCDControl */ - if (s->version != PL110) { - return s->int_mask; - } - return s->cr; - case 8: /* LCDRIS */ - return s->int_status; - case 9: /* LCDMIS */ - return s->int_status & s->int_mask; - case 11: /* LCDUPCURR */ - /* TODO: Implement vertical refresh. */ - return s->upbase; - case 12: /* LCDLPCURR */ - return s->lpbase; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "pl110_read: Bad offset %x\n", (int)offset); - return 0; - } -} - -static void pl110_write(void *opaque, hwaddr offset, - uint64_t val, unsigned size) -{ - PL110State *s = (PL110State *)opaque; - int n; - - /* For simplicity invalidate the display whenever a control register - is written to. */ - s->invalidate = 1; - if (offset >= 0x200 && offset < 0x400) { - /* Palette. */ - n = (offset - 0x200) >> 2; - s->raw_palette[(offset - 0x200) >> 2] = val; - pl110_update_palette(s, n); - return; - } - switch (offset >> 2) { - case 0: /* LCDTiming0 */ - s->timing[0] = val; - n = ((val & 0xfc) + 4) * 4; - pl110_resize(s, n, s->rows); - break; - case 1: /* LCDTiming1 */ - s->timing[1] = val; - n = (val & 0x3ff) + 1; - pl110_resize(s, s->cols, n); - break; - case 2: /* LCDTiming2 */ - s->timing[2] = val; - break; - case 3: /* LCDTiming3 */ - s->timing[3] = val; - break; - case 4: /* LCDUPBASE */ - s->upbase = val; - break; - case 5: /* LCDLPBASE */ - s->lpbase = val; - break; - case 6: /* LCDIMSC */ - if (s->version != PL110) { - goto control; - } - imsc: - s->int_mask = val; - pl110_update(s); - break; - case 7: /* LCDControl */ - if (s->version != PL110) { - goto imsc; - } - control: - s->cr = val; - s->bpp = (val >> 1) & 7; - if (pl110_enabled(s)) { - qemu_console_resize(s->con, s->cols, s->rows); - } - break; - case 10: /* LCDICR */ - s->int_status &= ~val; - pl110_update(s); - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "pl110_write: Bad offset %x\n", (int)offset); - } -} - -static const MemoryRegionOps pl110_ops = { - .read = pl110_read, - .write = pl110_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void pl110_mux_ctrl_set(void *opaque, int line, int level) -{ - PL110State *s = (PL110State *)opaque; - s->mux_ctrl = level; -} - -static int vmstate_pl110_post_load(void *opaque, int version_id) -{ - PL110State *s = opaque; - /* Make sure we redraw, and at the right size */ - pl110_invalidate_display(s); - return 0; -} - -static const GraphicHwOps pl110_gfx_ops = { - .invalidate = pl110_invalidate_display, - .gfx_update = pl110_update_display, -}; - -static int pl110_initfn(SysBusDevice *sbd) -{ - DeviceState *dev = DEVICE(sbd); - PL110State *s = PL110(dev); - - memory_region_init_io(&s->iomem, OBJECT(s), &pl110_ops, s, "pl110", 0x1000); - sysbus_init_mmio(sbd, &s->iomem); - sysbus_init_irq(sbd, &s->irq); - qdev_init_gpio_in(dev, pl110_mux_ctrl_set, 1); - s->con = graphic_console_init(dev, 0, &pl110_gfx_ops, s); - return 0; -} - -static void pl110_init(Object *obj) -{ - PL110State *s = PL110(obj); - - s->version = PL110; -} - -static void pl110_versatile_init(Object *obj) -{ - PL110State *s = PL110(obj); - - s->version = PL110_VERSATILE; -} - -static void pl111_init(Object *obj) -{ - PL110State *s = PL110(obj); - - s->version = PL111; -} - -static void pl110_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = pl110_initfn; - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); - dc->vmsd = &vmstate_pl110; -} - -static const TypeInfo pl110_info = { - .name = TYPE_PL110, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(PL110State), - .instance_init = pl110_init, - .class_init = pl110_class_init, -}; - -static const TypeInfo pl110_versatile_info = { - .name = "pl110_versatile", - .parent = TYPE_PL110, - .instance_init = pl110_versatile_init, -}; - -static const TypeInfo pl111_info = { - .name = "pl111", - .parent = TYPE_PL110, - .instance_init = pl111_init, -}; - -static void pl110_register_types(void) -{ - type_register_static(&pl110_info); - type_register_static(&pl110_versatile_info); - type_register_static(&pl111_info); -} - -type_init(pl110_register_types) diff --git a/qemu/hw/display/pl110_template.h b/qemu/hw/display/pl110_template.h deleted file mode 100644 index 36ba791c6..000000000 --- a/qemu/hw/display/pl110_template.h +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Arm PrimeCell PL110 Color LCD Controller - * - * Copyright (c) 2005 CodeSourcery, LLC. - * Written by Paul Brook - * - * This code is licensed under the GNU LGPL - * - * Framebuffer format conversion routines. - */ - -#ifndef ORDER - -#if BITS == 8 -#define COPY_PIXEL(to, from) *(to++) = from -#elif BITS == 15 || BITS == 16 -#define COPY_PIXEL(to, from) do { *(uint16_t *)to = from; to += 2; } while (0) -#elif BITS == 24 -#define COPY_PIXEL(to, from) \ - do { \ - *(to++) = from; \ - *(to++) = (from) >> 8; \ - *(to++) = (from) >> 16; \ - } while (0) -#elif BITS == 32 -#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0) -#else -#error unknown bit depth -#endif - -#undef RGB -#define BORDER bgr -#define ORDER 0 -#include "pl110_template.h" -#define ORDER 1 -#include "pl110_template.h" -#define ORDER 2 -#include "pl110_template.h" -#undef BORDER -#define RGB -#define BORDER rgb -#define ORDER 0 -#include "pl110_template.h" -#define ORDER 1 -#include "pl110_template.h" -#define ORDER 2 -#include "pl110_template.h" -#undef BORDER - -static drawfn glue(pl110_draw_fn_,BITS)[48] = -{ - glue(pl110_draw_line1_lblp_bgr,BITS), - glue(pl110_draw_line2_lblp_bgr,BITS), - glue(pl110_draw_line4_lblp_bgr,BITS), - glue(pl110_draw_line8_lblp_bgr,BITS), - glue(pl110_draw_line16_555_lblp_bgr,BITS), - glue(pl110_draw_line32_lblp_bgr,BITS), - glue(pl110_draw_line16_lblp_bgr,BITS), - glue(pl110_draw_line12_lblp_bgr,BITS), - - glue(pl110_draw_line1_bbbp_bgr,BITS), - glue(pl110_draw_line2_bbbp_bgr,BITS), - glue(pl110_draw_line4_bbbp_bgr,BITS), - glue(pl110_draw_line8_bbbp_bgr,BITS), - glue(pl110_draw_line16_555_bbbp_bgr,BITS), - glue(pl110_draw_line32_bbbp_bgr,BITS), - glue(pl110_draw_line16_bbbp_bgr,BITS), - glue(pl110_draw_line12_bbbp_bgr,BITS), - - glue(pl110_draw_line1_lbbp_bgr,BITS), - glue(pl110_draw_line2_lbbp_bgr,BITS), - glue(pl110_draw_line4_lbbp_bgr,BITS), - glue(pl110_draw_line8_lbbp_bgr,BITS), - glue(pl110_draw_line16_555_lbbp_bgr,BITS), - glue(pl110_draw_line32_lbbp_bgr,BITS), - glue(pl110_draw_line16_lbbp_bgr,BITS), - glue(pl110_draw_line12_lbbp_bgr,BITS), - - glue(pl110_draw_line1_lblp_rgb,BITS), - glue(pl110_draw_line2_lblp_rgb,BITS), - glue(pl110_draw_line4_lblp_rgb,BITS), - glue(pl110_draw_line8_lblp_rgb,BITS), - glue(pl110_draw_line16_555_lblp_rgb,BITS), - glue(pl110_draw_line32_lblp_rgb,BITS), - glue(pl110_draw_line16_lblp_rgb,BITS), - glue(pl110_draw_line12_lblp_rgb,BITS), - - glue(pl110_draw_line1_bbbp_rgb,BITS), - glue(pl110_draw_line2_bbbp_rgb,BITS), - glue(pl110_draw_line4_bbbp_rgb,BITS), - glue(pl110_draw_line8_bbbp_rgb,BITS), - glue(pl110_draw_line16_555_bbbp_rgb,BITS), - glue(pl110_draw_line32_bbbp_rgb,BITS), - glue(pl110_draw_line16_bbbp_rgb,BITS), - glue(pl110_draw_line12_bbbp_rgb,BITS), - - glue(pl110_draw_line1_lbbp_rgb,BITS), - glue(pl110_draw_line2_lbbp_rgb,BITS), - glue(pl110_draw_line4_lbbp_rgb,BITS), - glue(pl110_draw_line8_lbbp_rgb,BITS), - glue(pl110_draw_line16_555_lbbp_rgb,BITS), - glue(pl110_draw_line32_lbbp_rgb,BITS), - glue(pl110_draw_line16_lbbp_rgb,BITS), - glue(pl110_draw_line12_lbbp_rgb,BITS), -}; - -#undef BITS -#undef COPY_PIXEL - -#else - -#if ORDER == 0 -#define NAME glue(glue(lblp_, BORDER), BITS) -#ifdef HOST_WORDS_BIGENDIAN -#define SWAP_WORDS 1 -#endif -#elif ORDER == 1 -#define NAME glue(glue(bbbp_, BORDER), BITS) -#ifndef HOST_WORDS_BIGENDIAN -#define SWAP_WORDS 1 -#endif -#else -#define SWAP_PIXELS 1 -#define NAME glue(glue(lbbp_, BORDER), BITS) -#ifdef HOST_WORDS_BIGENDIAN -#define SWAP_WORDS 1 -#endif -#endif - -#define FN_2(x, y) FN(x, y) FN(x+1, y) -#define FN_4(x, y) FN_2(x, y) FN_2(x+2, y) -#define FN_8(y) FN_4(0, y) FN_4(4, y) - -static void glue(pl110_draw_line1_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) -{ - uint32_t *palette = opaque; - uint32_t data; - while (width > 0) { - data = *(uint32_t *)src; -#ifdef SWAP_PIXELS -#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 7 - (x))) & 1]); -#else -#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x) + y)) & 1]); -#endif -#ifdef SWAP_WORDS - FN_8(24) - FN_8(16) - FN_8(8) - FN_8(0) -#else - FN_8(0) - FN_8(8) - FN_8(16) - FN_8(24) -#endif -#undef FN - width -= 32; - src += 4; - } -} - -static void glue(pl110_draw_line2_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) -{ - uint32_t *palette = opaque; - uint32_t data; - while (width > 0) { - data = *(uint32_t *)src; -#ifdef SWAP_PIXELS -#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 6 - (x)*2)) & 3]); -#else -#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*2 + y)) & 3]); -#endif -#ifdef SWAP_WORDS - FN_4(0, 24) - FN_4(0, 16) - FN_4(0, 8) - FN_4(0, 0) -#else - FN_4(0, 0) - FN_4(0, 8) - FN_4(0, 16) - FN_4(0, 24) -#endif -#undef FN - width -= 16; - src += 4; - } -} - -static void glue(pl110_draw_line4_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) -{ - uint32_t *palette = opaque; - uint32_t data; - while (width > 0) { - data = *(uint32_t *)src; -#ifdef SWAP_PIXELS -#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 4 - (x)*4)) & 0xf]); -#else -#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*4 + y)) & 0xf]); -#endif -#ifdef SWAP_WORDS - FN_2(0, 24) - FN_2(0, 16) - FN_2(0, 8) - FN_2(0, 0) -#else - FN_2(0, 0) - FN_2(0, 8) - FN_2(0, 16) - FN_2(0, 24) -#endif -#undef FN - width -= 8; - src += 4; - } -} - -static void glue(pl110_draw_line8_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) -{ - uint32_t *palette = opaque; - uint32_t data; - while (width > 0) { - data = *(uint32_t *)src; -#define FN(x) COPY_PIXEL(d, palette[(data >> (x)) & 0xff]); -#ifdef SWAP_WORDS - FN(24) - FN(16) - FN(8) - FN(0) -#else - FN(0) - FN(8) - FN(16) - FN(24) -#endif -#undef FN - width -= 4; - src += 4; - } -} - -static void glue(pl110_draw_line16_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) -{ - uint32_t data; - unsigned int r, g, b; - while (width > 0) { - data = *(uint32_t *)src; -#ifdef SWAP_WORDS - data = bswap32(data); -#endif -#ifdef RGB -#define LSB r -#define MSB b -#else -#define LSB b -#define MSB r -#endif -#if 0 - LSB = data & 0x1f; - data >>= 5; - g = data & 0x3f; - data >>= 6; - MSB = data & 0x1f; - data >>= 5; -#else - LSB = (data & 0x1f) << 3; - data >>= 5; - g = (data & 0x3f) << 2; - data >>= 6; - MSB = (data & 0x1f) << 3; - data >>= 5; -#endif - COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); - LSB = (data & 0x1f) << 3; - data >>= 5; - g = (data & 0x3f) << 2; - data >>= 6; - MSB = (data & 0x1f) << 3; - data >>= 5; - COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); -#undef MSB -#undef LSB - width -= 2; - src += 4; - } -} - -static void glue(pl110_draw_line32_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) -{ - uint32_t data; - unsigned int r, g, b; - while (width > 0) { - data = *(uint32_t *)src; -#ifdef RGB -#define LSB r -#define MSB b -#else -#define LSB b -#define MSB r -#endif -#ifndef SWAP_WORDS - LSB = data & 0xff; - g = (data >> 8) & 0xff; - MSB = (data >> 16) & 0xff; -#else - LSB = (data >> 24) & 0xff; - g = (data >> 16) & 0xff; - MSB = (data >> 8) & 0xff; -#endif - COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); -#undef MSB -#undef LSB - width--; - src += 4; - } -} - -static void glue(pl110_draw_line16_555_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) -{ - /* RGB 555 plus an intensity bit (which we ignore) */ - uint32_t data; - unsigned int r, g, b; - while (width > 0) { - data = *(uint32_t *)src; -#ifdef SWAP_WORDS - data = bswap32(data); -#endif -#ifdef RGB -#define LSB r -#define MSB b -#else -#define LSB b -#define MSB r -#endif - LSB = (data & 0x1f) << 3; - data >>= 5; - g = (data & 0x1f) << 3; - data >>= 5; - MSB = (data & 0x1f) << 3; - data >>= 5; - COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); - LSB = (data & 0x1f) << 3; - data >>= 5; - g = (data & 0x1f) << 3; - data >>= 5; - MSB = (data & 0x1f) << 3; - data >>= 6; - COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); -#undef MSB -#undef LSB - width -= 2; - src += 4; - } -} - -static void glue(pl110_draw_line12_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) -{ - /* RGB 444 with 4 bits of zeroes at the top of each halfword */ - uint32_t data; - unsigned int r, g, b; - while (width > 0) { - data = *(uint32_t *)src; -#ifdef SWAP_WORDS - data = bswap32(data); -#endif -#ifdef RGB -#define LSB r -#define MSB b -#else -#define LSB b -#define MSB r -#endif - LSB = (data & 0xf) << 4; - data >>= 4; - g = (data & 0xf) << 4; - data >>= 4; - MSB = (data & 0xf) << 4; - data >>= 8; - COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); - LSB = (data & 0xf) << 4; - data >>= 4; - g = (data & 0xf) << 4; - data >>= 4; - MSB = (data & 0xf) << 4; - data >>= 8; - COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); -#undef MSB -#undef LSB - width -= 2; - src += 4; - } -} - -#undef SWAP_PIXELS -#undef NAME -#undef SWAP_WORDS -#undef ORDER - -#endif diff --git a/qemu/hw/display/pxa2xx_lcd.c b/qemu/hw/display/pxa2xx_lcd.c deleted file mode 100644 index 845521c5b..000000000 --- a/qemu/hw/display/pxa2xx_lcd.c +++ /dev/null @@ -1,1065 +0,0 @@ -/* - * Intel XScale PXA255/270 LCDC emulation. - * - * Copyright (c) 2006 Openedhand Ltd. - * Written by Andrzej Zaborowski - * - * This code is licensed under the GPLv2. - * - * 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/osdep.h" -#include "hw/hw.h" -#include "ui/console.h" -#include "hw/arm/pxa.h" -#include "ui/pixel_ops.h" -/* FIXME: For graphic_rotate. Should probably be done in common code. */ -#include "sysemu/sysemu.h" -#include "framebuffer.h" - -struct DMAChannel { - uint32_t branch; - uint8_t up; - uint8_t palette[1024]; - uint8_t pbuffer[1024]; - void (*redraw)(PXA2xxLCDState *s, hwaddr addr, - int *miny, int *maxy); - - uint32_t descriptor; - uint32_t source; - uint32_t id; - uint32_t command; -}; - -struct PXA2xxLCDState { - MemoryRegion *sysmem; - MemoryRegion iomem; - MemoryRegionSection fbsection; - qemu_irq irq; - int irqlevel; - - int invalidated; - QemuConsole *con; - drawfn *line_fn[2]; - int dest_width; - int xres, yres; - int pal_for; - int transp; - enum { - pxa_lcdc_2bpp = 1, - pxa_lcdc_4bpp = 2, - pxa_lcdc_8bpp = 3, - pxa_lcdc_16bpp = 4, - pxa_lcdc_18bpp = 5, - pxa_lcdc_18pbpp = 6, - pxa_lcdc_19bpp = 7, - pxa_lcdc_19pbpp = 8, - pxa_lcdc_24bpp = 9, - pxa_lcdc_25bpp = 10, - } bpp; - - uint32_t control[6]; - uint32_t status[2]; - uint32_t ovl1c[2]; - uint32_t ovl2c[2]; - uint32_t ccr; - uint32_t cmdcr; - uint32_t trgbr; - uint32_t tcr; - uint32_t liidr; - uint8_t bscntr; - - struct DMAChannel dma_ch[7]; - - qemu_irq vsync_cb; - int orientation; -}; - -typedef struct QEMU_PACKED { - uint32_t fdaddr; - uint32_t fsaddr; - uint32_t fidr; - uint32_t ldcmd; -} PXAFrameDescriptor; - -#define LCCR0 0x000 /* LCD Controller Control register 0 */ -#define LCCR1 0x004 /* LCD Controller Control register 1 */ -#define LCCR2 0x008 /* LCD Controller Control register 2 */ -#define LCCR3 0x00c /* LCD Controller Control register 3 */ -#define LCCR4 0x010 /* LCD Controller Control register 4 */ -#define LCCR5 0x014 /* LCD Controller Control register 5 */ - -#define FBR0 0x020 /* DMA Channel 0 Frame Branch register */ -#define FBR1 0x024 /* DMA Channel 1 Frame Branch register */ -#define FBR2 0x028 /* DMA Channel 2 Frame Branch register */ -#define FBR3 0x02c /* DMA Channel 3 Frame Branch register */ -#define FBR4 0x030 /* DMA Channel 4 Frame Branch register */ -#define FBR5 0x110 /* DMA Channel 5 Frame Branch register */ -#define FBR6 0x114 /* DMA Channel 6 Frame Branch register */ - -#define LCSR1 0x034 /* LCD Controller Status register 1 */ -#define LCSR0 0x038 /* LCD Controller Status register 0 */ -#define LIIDR 0x03c /* LCD Controller Interrupt ID register */ - -#define TRGBR 0x040 /* TMED RGB Seed register */ -#define TCR 0x044 /* TMED Control register */ - -#define OVL1C1 0x050 /* Overlay 1 Control register 1 */ -#define OVL1C2 0x060 /* Overlay 1 Control register 2 */ -#define OVL2C1 0x070 /* Overlay 2 Control register 1 */ -#define OVL2C2 0x080 /* Overlay 2 Control register 2 */ -#define CCR 0x090 /* Cursor Control register */ - -#define CMDCR 0x100 /* Command Control register */ -#define PRSR 0x104 /* Panel Read Status register */ - -#define PXA_LCDDMA_CHANS 7 -#define DMA_FDADR 0x00 /* Frame Descriptor Address register */ -#define DMA_FSADR 0x04 /* Frame Source Address register */ -#define DMA_FIDR 0x08 /* Frame ID register */ -#define DMA_LDCMD 0x0c /* Command register */ - -/* LCD Buffer Strength Control register */ -#define BSCNTR 0x04000054 - -/* Bitfield masks */ -#define LCCR0_ENB (1 << 0) -#define LCCR0_CMS (1 << 1) -#define LCCR0_SDS (1 << 2) -#define LCCR0_LDM (1 << 3) -#define LCCR0_SOFM0 (1 << 4) -#define LCCR0_IUM (1 << 5) -#define LCCR0_EOFM0 (1 << 6) -#define LCCR0_PAS (1 << 7) -#define LCCR0_DPD (1 << 9) -#define LCCR0_DIS (1 << 10) -#define LCCR0_QDM (1 << 11) -#define LCCR0_PDD (0xff << 12) -#define LCCR0_BSM0 (1 << 20) -#define LCCR0_OUM (1 << 21) -#define LCCR0_LCDT (1 << 22) -#define LCCR0_RDSTM (1 << 23) -#define LCCR0_CMDIM (1 << 24) -#define LCCR0_OUC (1 << 25) -#define LCCR0_LDDALT (1 << 26) -#define LCCR1_PPL(x) ((x) & 0x3ff) -#define LCCR2_LPP(x) ((x) & 0x3ff) -#define LCCR3_API (15 << 16) -#define LCCR3_BPP(x) ((((x) >> 24) & 7) | (((x) >> 26) & 8)) -#define LCCR3_PDFOR(x) (((x) >> 30) & 3) -#define LCCR4_K1(x) (((x) >> 0) & 7) -#define LCCR4_K2(x) (((x) >> 3) & 7) -#define LCCR4_K3(x) (((x) >> 6) & 7) -#define LCCR4_PALFOR(x) (((x) >> 15) & 3) -#define LCCR5_SOFM(ch) (1 << (ch - 1)) -#define LCCR5_EOFM(ch) (1 << (ch + 7)) -#define LCCR5_BSM(ch) (1 << (ch + 15)) -#define LCCR5_IUM(ch) (1 << (ch + 23)) -#define OVLC1_EN (1 << 31) -#define CCR_CEN (1 << 31) -#define FBR_BRA (1 << 0) -#define FBR_BINT (1 << 1) -#define FBR_SRCADDR (0xfffffff << 4) -#define LCSR0_LDD (1 << 0) -#define LCSR0_SOF0 (1 << 1) -#define LCSR0_BER (1 << 2) -#define LCSR0_ABC (1 << 3) -#define LCSR0_IU0 (1 << 4) -#define LCSR0_IU1 (1 << 5) -#define LCSR0_OU (1 << 6) -#define LCSR0_QD (1 << 7) -#define LCSR0_EOF0 (1 << 8) -#define LCSR0_BS0 (1 << 9) -#define LCSR0_SINT (1 << 10) -#define LCSR0_RDST (1 << 11) -#define LCSR0_CMDINT (1 << 12) -#define LCSR0_BERCH(x) (((x) & 7) << 28) -#define LCSR1_SOF(ch) (1 << (ch - 1)) -#define LCSR1_EOF(ch) (1 << (ch + 7)) -#define LCSR1_BS(ch) (1 << (ch + 15)) -#define LCSR1_IU(ch) (1 << (ch + 23)) -#define LDCMD_LENGTH(x) ((x) & 0x001ffffc) -#define LDCMD_EOFINT (1 << 21) -#define LDCMD_SOFINT (1 << 22) -#define LDCMD_PAL (1 << 26) - -/* Route internal interrupt lines to the global IC */ -static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s) -{ - int level = 0; - level |= (s->status[0] & LCSR0_LDD) && !(s->control[0] & LCCR0_LDM); - level |= (s->status[0] & LCSR0_SOF0) && !(s->control[0] & LCCR0_SOFM0); - level |= (s->status[0] & LCSR0_IU0) && !(s->control[0] & LCCR0_IUM); - level |= (s->status[0] & LCSR0_IU1) && !(s->control[5] & LCCR5_IUM(1)); - level |= (s->status[0] & LCSR0_OU) && !(s->control[0] & LCCR0_OUM); - level |= (s->status[0] & LCSR0_QD) && !(s->control[0] & LCCR0_QDM); - level |= (s->status[0] & LCSR0_EOF0) && !(s->control[0] & LCCR0_EOFM0); - level |= (s->status[0] & LCSR0_BS0) && !(s->control[0] & LCCR0_BSM0); - level |= (s->status[0] & LCSR0_RDST) && !(s->control[0] & LCCR0_RDSTM); - level |= (s->status[0] & LCSR0_CMDINT) && !(s->control[0] & LCCR0_CMDIM); - level |= (s->status[1] & ~s->control[5]); - - qemu_set_irq(s->irq, !!level); - s->irqlevel = level; -} - -/* Set Branch Status interrupt high and poke associated registers */ -static inline void pxa2xx_dma_bs_set(PXA2xxLCDState *s, int ch) -{ - int unmasked; - if (ch == 0) { - s->status[0] |= LCSR0_BS0; - unmasked = !(s->control[0] & LCCR0_BSM0); - } else { - s->status[1] |= LCSR1_BS(ch); - unmasked = !(s->control[5] & LCCR5_BSM(ch)); - } - - if (unmasked) { - if (s->irqlevel) - s->status[0] |= LCSR0_SINT; - else - s->liidr = s->dma_ch[ch].id; - } -} - -/* Set Start Of Frame Status interrupt high and poke associated registers */ -static inline void pxa2xx_dma_sof_set(PXA2xxLCDState *s, int ch) -{ - int unmasked; - if (!(s->dma_ch[ch].command & LDCMD_SOFINT)) - return; - - if (ch == 0) { - s->status[0] |= LCSR0_SOF0; - unmasked = !(s->control[0] & LCCR0_SOFM0); - } else { - s->status[1] |= LCSR1_SOF(ch); - unmasked = !(s->control[5] & LCCR5_SOFM(ch)); - } - - if (unmasked) { - if (s->irqlevel) - s->status[0] |= LCSR0_SINT; - else - s->liidr = s->dma_ch[ch].id; - } -} - -/* Set End Of Frame Status interrupt high and poke associated registers */ -static inline void pxa2xx_dma_eof_set(PXA2xxLCDState *s, int ch) -{ - int unmasked; - if (!(s->dma_ch[ch].command & LDCMD_EOFINT)) - return; - - if (ch == 0) { - s->status[0] |= LCSR0_EOF0; - unmasked = !(s->control[0] & LCCR0_EOFM0); - } else { - s->status[1] |= LCSR1_EOF(ch); - unmasked = !(s->control[5] & LCCR5_EOFM(ch)); - } - - if (unmasked) { - if (s->irqlevel) - s->status[0] |= LCSR0_SINT; - else - s->liidr = s->dma_ch[ch].id; - } -} - -/* Set Bus Error Status interrupt high and poke associated registers */ -static inline void pxa2xx_dma_ber_set(PXA2xxLCDState *s, int ch) -{ - s->status[0] |= LCSR0_BERCH(ch) | LCSR0_BER; - if (s->irqlevel) - s->status[0] |= LCSR0_SINT; - else - s->liidr = s->dma_ch[ch].id; -} - -/* Load new Frame Descriptors from DMA */ -static void pxa2xx_descriptor_load(PXA2xxLCDState *s) -{ - PXAFrameDescriptor desc; - hwaddr descptr; - int i; - - for (i = 0; i < PXA_LCDDMA_CHANS; i ++) { - s->dma_ch[i].source = 0; - - if (!s->dma_ch[i].up) - continue; - - if (s->dma_ch[i].branch & FBR_BRA) { - descptr = s->dma_ch[i].branch & FBR_SRCADDR; - if (s->dma_ch[i].branch & FBR_BINT) - pxa2xx_dma_bs_set(s, i); - s->dma_ch[i].branch &= ~FBR_BRA; - } else - descptr = s->dma_ch[i].descriptor; - - if (!((descptr >= PXA2XX_SDRAM_BASE && descptr + - sizeof(desc) <= PXA2XX_SDRAM_BASE + ram_size) || - (descptr >= PXA2XX_INTERNAL_BASE && descptr + sizeof(desc) <= - PXA2XX_INTERNAL_BASE + PXA2XX_INTERNAL_SIZE))) { - continue; - } - - cpu_physical_memory_read(descptr, &desc, sizeof(desc)); - s->dma_ch[i].descriptor = le32_to_cpu(desc.fdaddr); - s->dma_ch[i].source = le32_to_cpu(desc.fsaddr); - s->dma_ch[i].id = le32_to_cpu(desc.fidr); - s->dma_ch[i].command = le32_to_cpu(desc.ldcmd); - } -} - -static uint64_t pxa2xx_lcdc_read(void *opaque, hwaddr offset, - unsigned size) -{ - PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; - int ch; - - switch (offset) { - case LCCR0: - return s->control[0]; - case LCCR1: - return s->control[1]; - case LCCR2: - return s->control[2]; - case LCCR3: - return s->control[3]; - case LCCR4: - return s->control[4]; - case LCCR5: - return s->control[5]; - - case OVL1C1: - return s->ovl1c[0]; - case OVL1C2: - return s->ovl1c[1]; - case OVL2C1: - return s->ovl2c[0]; - case OVL2C2: - return s->ovl2c[1]; - - case CCR: - return s->ccr; - - case CMDCR: - return s->cmdcr; - - case TRGBR: - return s->trgbr; - case TCR: - return s->tcr; - - case 0x200 ... 0x1000: /* DMA per-channel registers */ - ch = (offset - 0x200) >> 4; - if (!(ch >= 0 && ch < PXA_LCDDMA_CHANS)) - goto fail; - - switch (offset & 0xf) { - case DMA_FDADR: - return s->dma_ch[ch].descriptor; - case DMA_FSADR: - return s->dma_ch[ch].source; - case DMA_FIDR: - return s->dma_ch[ch].id; - case DMA_LDCMD: - return s->dma_ch[ch].command; - default: - goto fail; - } - - case FBR0: - return s->dma_ch[0].branch; - case FBR1: - return s->dma_ch[1].branch; - case FBR2: - return s->dma_ch[2].branch; - case FBR3: - return s->dma_ch[3].branch; - case FBR4: - return s->dma_ch[4].branch; - case FBR5: - return s->dma_ch[5].branch; - case FBR6: - return s->dma_ch[6].branch; - - case BSCNTR: - return s->bscntr; - - case PRSR: - return 0; - - case LCSR0: - return s->status[0]; - case LCSR1: - return s->status[1]; - case LIIDR: - return s->liidr; - - default: - fail: - hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset); - } - - return 0; -} - -static void pxa2xx_lcdc_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; - int ch; - - switch (offset) { - case LCCR0: - /* ACK Quick Disable done */ - if ((s->control[0] & LCCR0_ENB) && !(value & LCCR0_ENB)) - s->status[0] |= LCSR0_QD; - - if (!(s->control[0] & LCCR0_LCDT) && (value & LCCR0_LCDT)) - printf("%s: internal frame buffer unsupported\n", __FUNCTION__); - - if ((s->control[3] & LCCR3_API) && - (value & LCCR0_ENB) && !(value & LCCR0_LCDT)) - s->status[0] |= LCSR0_ABC; - - s->control[0] = value & 0x07ffffff; - pxa2xx_lcdc_int_update(s); - - s->dma_ch[0].up = !!(value & LCCR0_ENB); - s->dma_ch[1].up = (s->ovl1c[0] & OVLC1_EN) || (value & LCCR0_SDS); - break; - - case LCCR1: - s->control[1] = value; - break; - - case LCCR2: - s->control[2] = value; - break; - - case LCCR3: - s->control[3] = value & 0xefffffff; - s->bpp = LCCR3_BPP(value); - break; - - case LCCR4: - s->control[4] = value & 0x83ff81ff; - break; - - case LCCR5: - s->control[5] = value & 0x3f3f3f3f; - break; - - case OVL1C1: - if (!(s->ovl1c[0] & OVLC1_EN) && (value & OVLC1_EN)) - printf("%s: Overlay 1 not supported\n", __FUNCTION__); - - s->ovl1c[0] = value & 0x80ffffff; - s->dma_ch[1].up = (value & OVLC1_EN) || (s->control[0] & LCCR0_SDS); - break; - - case OVL1C2: - s->ovl1c[1] = value & 0x000fffff; - break; - - case OVL2C1: - if (!(s->ovl2c[0] & OVLC1_EN) && (value & OVLC1_EN)) - printf("%s: Overlay 2 not supported\n", __FUNCTION__); - - s->ovl2c[0] = value & 0x80ffffff; - s->dma_ch[2].up = !!(value & OVLC1_EN); - s->dma_ch[3].up = !!(value & OVLC1_EN); - s->dma_ch[4].up = !!(value & OVLC1_EN); - break; - - case OVL2C2: - s->ovl2c[1] = value & 0x007fffff; - break; - - case CCR: - if (!(s->ccr & CCR_CEN) && (value & CCR_CEN)) - printf("%s: Hardware cursor unimplemented\n", __FUNCTION__); - - s->ccr = value & 0x81ffffe7; - s->dma_ch[5].up = !!(value & CCR_CEN); - break; - - case CMDCR: - s->cmdcr = value & 0xff; - break; - - case TRGBR: - s->trgbr = value & 0x00ffffff; - break; - - case TCR: - s->tcr = value & 0x7fff; - break; - - case 0x200 ... 0x1000: /* DMA per-channel registers */ - ch = (offset - 0x200) >> 4; - if (!(ch >= 0 && ch < PXA_LCDDMA_CHANS)) - goto fail; - - switch (offset & 0xf) { - case DMA_FDADR: - s->dma_ch[ch].descriptor = value & 0xfffffff0; - break; - - default: - goto fail; - } - break; - - case FBR0: - s->dma_ch[0].branch = value & 0xfffffff3; - break; - case FBR1: - s->dma_ch[1].branch = value & 0xfffffff3; - break; - case FBR2: - s->dma_ch[2].branch = value & 0xfffffff3; - break; - case FBR3: - s->dma_ch[3].branch = value & 0xfffffff3; - break; - case FBR4: - s->dma_ch[4].branch = value & 0xfffffff3; - break; - case FBR5: - s->dma_ch[5].branch = value & 0xfffffff3; - break; - case FBR6: - s->dma_ch[6].branch = value & 0xfffffff3; - break; - - case BSCNTR: - s->bscntr = value & 0xf; - break; - - case PRSR: - break; - - case LCSR0: - s->status[0] &= ~(value & 0xfff); - if (value & LCSR0_BER) - s->status[0] &= ~LCSR0_BERCH(7); - break; - - case LCSR1: - s->status[1] &= ~(value & 0x3e3f3f); - break; - - default: - fail: - hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset); - } -} - -static const MemoryRegionOps pxa2xx_lcdc_ops = { - .read = pxa2xx_lcdc_read, - .write = pxa2xx_lcdc_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -/* 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; - s->pal_for = LCCR4_PALFOR(s->control[4]); - format = s->pal_for; - - switch (bpp) { - case pxa_lcdc_2bpp: - n = 4; - break; - case pxa_lcdc_4bpp: - n = 16; - break; - case pxa_lcdc_8bpp: - n = 256; - break; - default: - format = 0; - return; - } - - src = (uint8_t *) s->dma_ch[ch].pbuffer; - dest = (uint32_t *) s->dma_ch[ch].palette; - alpha = r = g = b = 0; - - for (i = 0; i < n; i ++) { - switch (format) { - case 0: /* 16 bpp, no transparency */ - alpha = 0; - if (s->control[0] & LCCR0_CMS) { - r = g = b = *(uint16_t *) src & 0xff; - } - else { - r = (*(uint16_t *) src & 0xf800) >> 8; - g = (*(uint16_t *) src & 0x07e0) >> 3; - b = (*(uint16_t *) src & 0x001f) << 3; - } - src += 2; - break; - case 1: /* 16 bpp plus transparency */ - alpha = *(uint32_t *) src & (1 << 24); - if (s->control[0] & LCCR0_CMS) - r = g = b = *(uint32_t *) src & 0xff; - else { - r = (*(uint32_t *) src & 0xf80000) >> 16; - g = (*(uint32_t *) src & 0x00fc00) >> 8; - b = (*(uint32_t *) src & 0x0000f8); - } - src += 4; - break; - case 2: /* 18 bpp plus transparency */ - alpha = *(uint32_t *) src & (1 << 24); - if (s->control[0] & LCCR0_CMS) - r = g = b = *(uint32_t *) src & 0xff; - else { - r = (*(uint32_t *) src & 0xfc0000) >> 16; - g = (*(uint32_t *) src & 0x00fc00) >> 8; - b = (*(uint32_t *) src & 0x0000fc); - } - src += 4; - break; - case 3: /* 24 bpp plus transparency */ - alpha = *(uint32_t *) src & (1 << 24); - if (s->control[0] & LCCR0_CMS) - r = g = b = *(uint32_t *) src & 0xff; - else { - r = (*(uint32_t *) src & 0xff0000) >> 16; - g = (*(uint32_t *) src & 0x00ff00) >> 8; - b = (*(uint32_t *) src & 0x0000ff); - } - src += 4; - break; - } - switch (surface_bits_per_pixel(surface)) { - case 8: - *dest = rgb_to_pixel8(r, g, b) | alpha; - break; - case 15: - *dest = rgb_to_pixel15(r, g, b) | alpha; - break; - case 16: - *dest = rgb_to_pixel16(r, g, b) | alpha; - break; - case 24: - *dest = rgb_to_pixel24(r, g, b) | alpha; - break; - case 32: - *dest = rgb_to_pixel32(r, g, b) | alpha; - break; - } - dest ++; - } -} - -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) - fn = s->line_fn[s->transp][s->bpp]; - if (!fn) - return; - - src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */ - if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) - src_width *= 3; - else if (s->bpp > pxa_lcdc_16bpp) - src_width *= 4; - else if (s->bpp > pxa_lcdc_8bpp) - src_width *= 2; - - dest_width = s->xres * s->dest_width; - *miny = 0; - if (s->invalidated) { - framebuffer_update_memory_section(&s->fbsection, s->sysmem, - addr, s->yres, src_width); - } - framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres, - src_width, dest_width, s->dest_width, - s->invalidated, - fn, s->dma_ch[0].palette, miny, maxy); -} - -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) - fn = s->line_fn[s->transp][s->bpp]; - if (!fn) - return; - - src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */ - if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) - src_width *= 3; - else if (s->bpp > pxa_lcdc_16bpp) - src_width *= 4; - else if (s->bpp > pxa_lcdc_8bpp) - src_width *= 2; - - dest_width = s->yres * s->dest_width; - *miny = 0; - if (s->invalidated) { - framebuffer_update_memory_section(&s->fbsection, s->sysmem, - addr, s->yres, src_width); - } - framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres, - src_width, s->dest_width, -dest_width, - s->invalidated, - fn, s->dma_ch[0].palette, - miny, maxy); -} - -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) { - fn = s->line_fn[s->transp][s->bpp]; - } - if (!fn) { - return; - } - - src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */ - if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) { - src_width *= 3; - } else if (s->bpp > pxa_lcdc_16bpp) { - src_width *= 4; - } else if (s->bpp > pxa_lcdc_8bpp) { - src_width *= 2; - } - - dest_width = s->xres * s->dest_width; - *miny = 0; - if (s->invalidated) { - framebuffer_update_memory_section(&s->fbsection, s->sysmem, - addr, s->yres, src_width); - } - framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres, - src_width, -dest_width, -s->dest_width, - s->invalidated, - fn, s->dma_ch[0].palette, miny, maxy); -} - -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) { - fn = s->line_fn[s->transp][s->bpp]; - } - if (!fn) { - return; - } - - src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */ - if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) { - src_width *= 3; - } else if (s->bpp > pxa_lcdc_16bpp) { - src_width *= 4; - } else if (s->bpp > pxa_lcdc_8bpp) { - src_width *= 2; - } - - dest_width = s->yres * s->dest_width; - *miny = 0; - if (s->invalidated) { - framebuffer_update_memory_section(&s->fbsection, s->sysmem, - addr, s->yres, src_width); - } - framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres, - src_width, -s->dest_width, dest_width, - s->invalidated, - fn, s->dma_ch[0].palette, - miny, maxy); -} - -static void pxa2xx_lcdc_resize(PXA2xxLCDState *s) -{ - int width, height; - if (!(s->control[0] & LCCR0_ENB)) - return; - - width = LCCR1_PPL(s->control[1]) + 1; - height = LCCR2_LPP(s->control[2]) + 1; - - if (width != s->xres || height != s->yres) { - if (s->orientation == 90 || s->orientation == 270) { - qemu_console_resize(s->con, height, width); - } else { - qemu_console_resize(s->con, width, height); - } - s->invalidated = 1; - s->xres = width; - s->yres = height; - } -} - -static void pxa2xx_update_display(void *opaque) -{ - PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; - hwaddr fbptr; - int miny, maxy; - int ch; - if (!(s->control[0] & LCCR0_ENB)) - return; - - pxa2xx_descriptor_load(s); - - pxa2xx_lcdc_resize(s); - miny = s->yres; - maxy = 0; - s->transp = s->dma_ch[2].up || s->dma_ch[3].up; - /* Note: With overlay planes the order depends on LCCR0 bit 25. */ - for (ch = 0; ch < PXA_LCDDMA_CHANS; ch ++) - if (s->dma_ch[ch].up) { - if (!s->dma_ch[ch].source) { - pxa2xx_dma_ber_set(s, ch); - continue; - } - fbptr = s->dma_ch[ch].source; - if (!((fbptr >= PXA2XX_SDRAM_BASE && - fbptr <= PXA2XX_SDRAM_BASE + ram_size) || - (fbptr >= PXA2XX_INTERNAL_BASE && - fbptr <= PXA2XX_INTERNAL_BASE + PXA2XX_INTERNAL_SIZE))) { - pxa2xx_dma_ber_set(s, ch); - continue; - } - - if (s->dma_ch[ch].command & LDCMD_PAL) { - cpu_physical_memory_read(fbptr, s->dma_ch[ch].pbuffer, - MAX(LDCMD_LENGTH(s->dma_ch[ch].command), - sizeof(s->dma_ch[ch].pbuffer))); - pxa2xx_palette_parse(s, ch, s->bpp); - } else { - /* Do we need to reparse palette */ - if (LCCR4_PALFOR(s->control[4]) != s->pal_for) - pxa2xx_palette_parse(s, ch, s->bpp); - - /* ACK frame start */ - pxa2xx_dma_sof_set(s, ch); - - s->dma_ch[ch].redraw(s, fbptr, &miny, &maxy); - s->invalidated = 0; - - /* ACK frame completed */ - pxa2xx_dma_eof_set(s, ch); - } - } - - if (s->control[0] & LCCR0_DIS) { - /* ACK last frame completed */ - s->control[0] &= ~LCCR0_ENB; - s->status[0] |= LCSR0_LDD; - } - - if (miny >= 0) { - switch (s->orientation) { - case 0: - dpy_gfx_update(s->con, 0, miny, s->xres, maxy - miny + 1); - break; - case 90: - 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->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->con, maxy, 0, miny - maxy + 1, s->xres); - break; - } - } - pxa2xx_lcdc_int_update(s); - - qemu_irq_raise(s->vsync_cb); -} - -static void pxa2xx_invalidate_display(void *opaque) -{ - PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; - s->invalidated = 1; -} - -static void pxa2xx_lcdc_orientation(void *opaque, int angle) -{ - PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; - - switch (angle) { - case 0: - s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot0; - break; - case 90: - s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot90; - break; - case 180: - s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot180; - break; - case 270: - s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot270; - break; - } - - s->orientation = angle; - s->xres = s->yres = -1; - pxa2xx_lcdc_resize(s); -} - -static const VMStateDescription vmstate_dma_channel = { - .name = "dma_channel", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_UINT32(branch, struct DMAChannel), - VMSTATE_UINT8(up, struct DMAChannel), - VMSTATE_BUFFER(pbuffer, struct DMAChannel), - VMSTATE_UINT32(descriptor, struct DMAChannel), - VMSTATE_UINT32(source, struct DMAChannel), - VMSTATE_UINT32(id, struct DMAChannel), - VMSTATE_UINT32(command, struct DMAChannel), - VMSTATE_END_OF_LIST() - } -}; - -static int pxa2xx_lcdc_post_load(void *opaque, int version_id) -{ - PXA2xxLCDState *s = opaque; - - s->bpp = LCCR3_BPP(s->control[3]); - s->xres = s->yres = s->pal_for = -1; - - return 0; -} - -static const VMStateDescription vmstate_pxa2xx_lcdc = { - .name = "pxa2xx_lcdc", - .version_id = 0, - .minimum_version_id = 0, - .post_load = pxa2xx_lcdc_post_load, - .fields = (VMStateField[]) { - VMSTATE_INT32(irqlevel, PXA2xxLCDState), - VMSTATE_INT32(transp, PXA2xxLCDState), - VMSTATE_UINT32_ARRAY(control, PXA2xxLCDState, 6), - VMSTATE_UINT32_ARRAY(status, PXA2xxLCDState, 2), - VMSTATE_UINT32_ARRAY(ovl1c, PXA2xxLCDState, 2), - VMSTATE_UINT32_ARRAY(ovl2c, PXA2xxLCDState, 2), - VMSTATE_UINT32(ccr, PXA2xxLCDState), - VMSTATE_UINT32(cmdcr, PXA2xxLCDState), - VMSTATE_UINT32(trgbr, PXA2xxLCDState), - VMSTATE_UINT32(tcr, PXA2xxLCDState), - VMSTATE_UINT32(liidr, PXA2xxLCDState), - VMSTATE_UINT8(bscntr, PXA2xxLCDState), - VMSTATE_STRUCT_ARRAY(dma_ch, PXA2xxLCDState, 7, 0, - vmstate_dma_channel, struct DMAChannel), - VMSTATE_END_OF_LIST() - } -}; - -#define BITS 8 -#include "pxa2xx_template.h" -#define BITS 15 -#include "pxa2xx_template.h" -#define BITS 16 -#include "pxa2xx_template.h" -#define BITS 24 -#include "pxa2xx_template.h" -#define BITS 32 -#include "pxa2xx_template.h" - -static const GraphicHwOps pxa2xx_ops = { - .invalidate = pxa2xx_invalidate_display, - .gfx_update = pxa2xx_update_display, -}; - -PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, - hwaddr base, qemu_irq irq) -{ - PXA2xxLCDState *s; - DisplaySurface *surface; - - s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState)); - s->invalidated = 1; - s->irq = irq; - s->sysmem = sysmem; - - pxa2xx_lcdc_orientation(s, graphic_rotate); - - memory_region_init_io(&s->iomem, NULL, &pxa2xx_lcdc_ops, s, - "pxa2xx-lcd-controller", 0x00100000); - memory_region_add_subregion(sysmem, base, &s->iomem); - - s->con = graphic_console_init(NULL, 0, &pxa2xx_ops, s); - surface = qemu_console_surface(s->con); - - switch (surface_bits_per_pixel(surface)) { - case 0: - s->dest_width = 0; - break; - case 8: - s->line_fn[0] = pxa2xx_draw_fn_8; - s->line_fn[1] = pxa2xx_draw_fn_8t; - s->dest_width = 1; - break; - case 15: - s->line_fn[0] = pxa2xx_draw_fn_15; - s->line_fn[1] = pxa2xx_draw_fn_15t; - s->dest_width = 2; - break; - case 16: - s->line_fn[0] = pxa2xx_draw_fn_16; - s->line_fn[1] = pxa2xx_draw_fn_16t; - s->dest_width = 2; - break; - case 24: - s->line_fn[0] = pxa2xx_draw_fn_24; - s->line_fn[1] = pxa2xx_draw_fn_24t; - s->dest_width = 3; - break; - case 32: - s->line_fn[0] = pxa2xx_draw_fn_32; - s->line_fn[1] = pxa2xx_draw_fn_32t; - s->dest_width = 4; - break; - default: - fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__); - exit(1); - } - - vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s); - - return s; -} - -void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler) -{ - s->vsync_cb = handler; -} diff --git a/qemu/hw/display/pxa2xx_template.h b/qemu/hw/display/pxa2xx_template.h deleted file mode 100644 index c64eebc4b..000000000 --- a/qemu/hw/display/pxa2xx_template.h +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Intel XScale PXA255/270 LCDC emulation. - * - * Copyright (c) 2006 Openedhand Ltd. - * Written by Andrzej Zaborowski - * - * This code is licensed under the GPLv2. - * - * Framebuffer format conversion routines. - */ - -# define SKIP_PIXEL(to) to += deststep -#if BITS == 8 -# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0) -#elif BITS == 15 || BITS == 16 -# define COPY_PIXEL(to, from) \ - do { \ - *(uint16_t *) to = from; \ - SKIP_PIXEL(to); \ - } while (0) -#elif BITS == 24 -# define COPY_PIXEL(to, from) \ - do { \ - *(uint16_t *) to = from; \ - *(to + 2) = (from) >> 16; \ - SKIP_PIXEL(to); \ - } while (0) -#elif BITS == 32 -# define COPY_PIXEL(to, from) \ - do { \ - *(uint32_t *) to = from; \ - SKIP_PIXEL(to); \ - } while (0) -#else -# error unknown bit depth -#endif - -#ifdef HOST_WORDS_BIGENDIAN -# define SWAP_WORDS 1 -#endif - -#define FN_2(x) FN(x + 1) FN(x) -#define FN_4(x) FN_2(x + 2) FN_2(x) - -static void glue(pxa2xx_draw_line2_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t *palette = opaque; - uint32_t data; - while (width > 0) { - data = *(uint32_t *) src; -#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]); -#ifdef SWAP_WORDS - FN_4(12) - FN_4(8) - FN_4(4) - FN_4(0) -#else - FN_4(0) - FN_4(4) - FN_4(8) - FN_4(12) -#endif -#undef FN - width -= 16; - src += 4; - } -} - -static void glue(pxa2xx_draw_line4_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t *palette = opaque; - uint32_t data; - while (width > 0) { - data = *(uint32_t *) src; -#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]); -#ifdef SWAP_WORDS - FN_2(6) - FN_2(4) - FN_2(2) - FN_2(0) -#else - FN_2(0) - FN_2(2) - FN_2(4) - FN_2(6) -#endif -#undef FN - width -= 8; - src += 4; - } -} - -static void glue(pxa2xx_draw_line8_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t *palette = opaque; - uint32_t data; - while (width > 0) { - data = *(uint32_t *) src; -#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]); -#ifdef SWAP_WORDS - FN(24) - FN(16) - FN(8) - FN(0) -#else - FN(0) - FN(8) - FN(16) - FN(24) -#endif -#undef FN - width -= 4; - src += 4; - } -} - -static void glue(pxa2xx_draw_line16_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t data; - unsigned int r, g, b; - while (width > 0) { - data = *(uint32_t *) src; -#ifdef SWAP_WORDS - data = bswap32(data); -#endif - b = (data & 0x1f) << 3; - data >>= 5; - g = (data & 0x3f) << 2; - data >>= 6; - r = (data & 0x1f) << 3; - data >>= 5; - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - b = (data & 0x1f) << 3; - data >>= 5; - g = (data & 0x3f) << 2; - data >>= 6; - r = (data & 0x1f) << 3; - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - width -= 2; - src += 4; - } -} - -static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t data; - unsigned int r, g, b; - while (width > 0) { - data = *(uint32_t *) src; -#ifdef SWAP_WORDS - data = bswap32(data); -#endif - b = (data & 0x1f) << 3; - data >>= 5; - g = (data & 0x1f) << 3; - data >>= 5; - r = (data & 0x1f) << 3; - data >>= 5; - if (data & 1) - SKIP_PIXEL(dest); - else - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - data >>= 1; - b = (data & 0x1f) << 3; - data >>= 5; - g = (data & 0x1f) << 3; - data >>= 5; - r = (data & 0x1f) << 3; - data >>= 5; - if (data & 1) - SKIP_PIXEL(dest); - else - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - width -= 2; - src += 4; - } -} - -static void glue(pxa2xx_draw_line18_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t data; - unsigned int r, g, b; - while (width > 0) { - data = *(uint32_t *) src; -#ifdef SWAP_WORDS - data = bswap32(data); -#endif - b = (data & 0x3f) << 2; - data >>= 6; - g = (data & 0x3f) << 2; - data >>= 6; - r = (data & 0x3f) << 2; - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - width -= 1; - src += 4; - } -} - -/* The wicked packed format */ -static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t data[3]; - unsigned int r, g, b; - while (width > 0) { - data[0] = *(uint32_t *) src; - src += 4; - data[1] = *(uint32_t *) src; - src += 4; - data[2] = *(uint32_t *) src; - src += 4; -#ifdef SWAP_WORDS - data[0] = bswap32(data[0]); - data[1] = bswap32(data[1]); - data[2] = bswap32(data[2]); -#endif - b = (data[0] & 0x3f) << 2; - data[0] >>= 6; - g = (data[0] & 0x3f) << 2; - data[0] >>= 6; - r = (data[0] & 0x3f) << 2; - data[0] >>= 12; - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - b = (data[0] & 0x3f) << 2; - data[0] >>= 6; - g = ((data[1] & 0xf) << 4) | (data[0] << 2); - data[1] >>= 4; - r = (data[1] & 0x3f) << 2; - data[1] >>= 12; - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - b = (data[1] & 0x3f) << 2; - data[1] >>= 6; - g = (data[1] & 0x3f) << 2; - data[1] >>= 6; - r = ((data[2] & 0x3) << 6) | (data[1] << 2); - data[2] >>= 8; - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - b = (data[2] & 0x3f) << 2; - data[2] >>= 6; - g = (data[2] & 0x3f) << 2; - data[2] >>= 6; - r = data[2] << 2; - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - width -= 4; - } -} - -static void glue(pxa2xx_draw_line19_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t data; - unsigned int r, g, b; - while (width > 0) { - data = *(uint32_t *) src; -#ifdef SWAP_WORDS - data = bswap32(data); -#endif - b = (data & 0x3f) << 2; - data >>= 6; - g = (data & 0x3f) << 2; - data >>= 6; - r = (data & 0x3f) << 2; - data >>= 6; - if (data & 1) - SKIP_PIXEL(dest); - else - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - width -= 1; - src += 4; - } -} - -/* The wicked packed format */ -static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t data[3]; - unsigned int r, g, b; - while (width > 0) { - data[0] = *(uint32_t *) src; - src += 4; - data[1] = *(uint32_t *) src; - src += 4; - data[2] = *(uint32_t *) src; - src += 4; -# ifdef SWAP_WORDS - data[0] = bswap32(data[0]); - data[1] = bswap32(data[1]); - data[2] = bswap32(data[2]); -# endif - b = (data[0] & 0x3f) << 2; - data[0] >>= 6; - g = (data[0] & 0x3f) << 2; - data[0] >>= 6; - r = (data[0] & 0x3f) << 2; - data[0] >>= 6; - if (data[0] & 1) - SKIP_PIXEL(dest); - else - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - data[0] >>= 6; - b = (data[0] & 0x3f) << 2; - data[0] >>= 6; - g = ((data[1] & 0xf) << 4) | (data[0] << 2); - data[1] >>= 4; - r = (data[1] & 0x3f) << 2; - data[1] >>= 6; - if (data[1] & 1) - SKIP_PIXEL(dest); - else - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - data[1] >>= 6; - b = (data[1] & 0x3f) << 2; - data[1] >>= 6; - g = (data[1] & 0x3f) << 2; - data[1] >>= 6; - r = ((data[2] & 0x3) << 6) | (data[1] << 2); - data[2] >>= 2; - if (data[2] & 1) - SKIP_PIXEL(dest); - else - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - data[2] >>= 6; - b = (data[2] & 0x3f) << 2; - data[2] >>= 6; - g = (data[2] & 0x3f) << 2; - data[2] >>= 6; - r = data[2] << 2; - data[2] >>= 6; - if (data[2] & 1) - SKIP_PIXEL(dest); - else - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - width -= 4; - } -} - -static void glue(pxa2xx_draw_line24_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t data; - unsigned int r, g, b; - while (width > 0) { - data = *(uint32_t *) src; -#ifdef SWAP_WORDS - data = bswap32(data); -#endif - b = data & 0xff; - data >>= 8; - g = data & 0xff; - data >>= 8; - r = data & 0xff; - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - width -= 1; - src += 4; - } -} - -static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t data; - unsigned int r, g, b; - while (width > 0) { - data = *(uint32_t *) src; -#ifdef SWAP_WORDS - data = bswap32(data); -#endif - b = (data & 0x7f) << 1; - data >>= 7; - g = data & 0xff; - data >>= 8; - r = data & 0xff; - data >>= 8; - if (data & 1) - SKIP_PIXEL(dest); - else - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - width -= 1; - src += 4; - } -} - -static void glue(pxa2xx_draw_line25_, BITS)(void *opaque, - uint8_t *dest, const uint8_t *src, int width, int deststep) -{ - uint32_t data; - unsigned int r, g, b; - while (width > 0) { - data = *(uint32_t *) src; -#ifdef SWAP_WORDS - data = bswap32(data); -#endif - b = data & 0xff; - data >>= 8; - g = data & 0xff; - data >>= 8; - r = data & 0xff; - data >>= 8; - if (data & 1) - SKIP_PIXEL(dest); - else - COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); - width -= 1; - src += 4; - } -} - -/* Overlay planes disabled, no transparency */ -static drawfn glue(pxa2xx_draw_fn_, BITS)[16] = -{ - [0 ... 0xf] = NULL, - [pxa_lcdc_2bpp] = glue(pxa2xx_draw_line2_, BITS), - [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS), - [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS), - [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16_, BITS), - [pxa_lcdc_18bpp] = glue(pxa2xx_draw_line18_, BITS), - [pxa_lcdc_18pbpp] = glue(pxa2xx_draw_line18p_, BITS), - [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24_, BITS), -}; - -/* Overlay planes enabled, transparency used */ -static drawfn glue(glue(pxa2xx_draw_fn_, BITS), t)[16] = -{ - [0 ... 0xf] = NULL, - [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS), - [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS), - [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16t_, BITS), - [pxa_lcdc_19bpp] = glue(pxa2xx_draw_line19_, BITS), - [pxa_lcdc_19pbpp] = glue(pxa2xx_draw_line19p_, BITS), - [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24t_, BITS), - [pxa_lcdc_25bpp] = glue(pxa2xx_draw_line25_, BITS), -}; - -#undef BITS -#undef COPY_PIXEL -#undef SKIP_PIXEL - -#ifdef SWAP_WORDS -# undef SWAP_WORDS -#endif diff --git a/qemu/hw/display/qxl-logger.c b/qemu/hw/display/qxl-logger.c deleted file mode 100644 index 2ec6d8fa3..000000000 --- a/qemu/hw/display/qxl-logger.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * qxl command logging -- for debug purposes - * - * Copyright (C) 2010 Red Hat, Inc. - * - * maintained by Gerd Hoffmann - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * 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 . - */ - -#include "qemu/osdep.h" -#include "qemu/timer.h" -#include "qxl.h" - -static const char *const qxl_type[] = { - [ QXL_CMD_NOP ] = "nop", - [ QXL_CMD_DRAW ] = "draw", - [ QXL_CMD_UPDATE ] = "update", - [ QXL_CMD_CURSOR ] = "cursor", - [ QXL_CMD_MESSAGE ] = "message", - [ QXL_CMD_SURFACE ] = "surface", -}; - -static const char *const qxl_draw_type[] = { - [ QXL_DRAW_NOP ] = "nop", - [ QXL_DRAW_FILL ] = "fill", - [ QXL_DRAW_OPAQUE ] = "opaque", - [ QXL_DRAW_COPY ] = "copy", - [ QXL_COPY_BITS ] = "copy-bits", - [ QXL_DRAW_BLEND ] = "blend", - [ QXL_DRAW_BLACKNESS ] = "blackness", - [ QXL_DRAW_WHITENESS ] = "whitemess", - [ QXL_DRAW_INVERS ] = "invers", - [ QXL_DRAW_ROP3 ] = "rop3", - [ QXL_DRAW_STROKE ] = "stroke", - [ QXL_DRAW_TEXT ] = "text", - [ QXL_DRAW_TRANSPARENT ] = "transparent", - [ QXL_DRAW_ALPHA_BLEND ] = "alpha-blend", -}; - -static const char *const qxl_draw_effect[] = { - [ QXL_EFFECT_BLEND ] = "blend", - [ QXL_EFFECT_OPAQUE ] = "opaque", - [ QXL_EFFECT_REVERT_ON_DUP ] = "revert-on-dup", - [ QXL_EFFECT_BLACKNESS_ON_DUP ] = "blackness-on-dup", - [ QXL_EFFECT_WHITENESS_ON_DUP ] = "whiteness-on-dup", - [ QXL_EFFECT_NOP_ON_DUP ] = "nop-on-dup", - [ QXL_EFFECT_NOP ] = "nop", - [ QXL_EFFECT_OPAQUE_BRUSH ] = "opaque-brush", -}; - -static const char *const qxl_surface_cmd[] = { - [ QXL_SURFACE_CMD_CREATE ] = "create", - [ QXL_SURFACE_CMD_DESTROY ] = "destroy", -}; - -static const char *const spice_surface_fmt[] = { - [ SPICE_SURFACE_FMT_INVALID ] = "invalid", - [ SPICE_SURFACE_FMT_1_A ] = "alpha/1", - [ SPICE_SURFACE_FMT_8_A ] = "alpha/8", - [ SPICE_SURFACE_FMT_16_555 ] = "555/16", - [ SPICE_SURFACE_FMT_16_565 ] = "565/16", - [ SPICE_SURFACE_FMT_32_xRGB ] = "xRGB/32", - [ SPICE_SURFACE_FMT_32_ARGB ] = "ARGB/32", -}; - -static const char *const qxl_cursor_cmd[] = { - [ QXL_CURSOR_SET ] = "set", - [ QXL_CURSOR_MOVE ] = "move", - [ QXL_CURSOR_HIDE ] = "hide", - [ QXL_CURSOR_TRAIL ] = "trail", -}; - -static const char *const spice_cursor_type[] = { - [ SPICE_CURSOR_TYPE_ALPHA ] = "alpha", - [ SPICE_CURSOR_TYPE_MONO ] = "mono", - [ SPICE_CURSOR_TYPE_COLOR4 ] = "color4", - [ SPICE_CURSOR_TYPE_COLOR8 ] = "color8", - [ SPICE_CURSOR_TYPE_COLOR16 ] = "color16", - [ SPICE_CURSOR_TYPE_COLOR24 ] = "color24", - [ SPICE_CURSOR_TYPE_COLOR32 ] = "color32", -}; - -static const char *qxl_v2n(const char *const n[], size_t l, int v) -{ - if (v >= l || !n[v]) { - return "???"; - } - return n[v]; -} -#define qxl_name(_list, _value) qxl_v2n(_list, ARRAY_SIZE(_list), _value) - -static int qxl_log_image(PCIQXLDevice *qxl, QXLPHYSICAL addr, int group_id) -{ - QXLImage *image; - QXLImageDescriptor *desc; - - image = qxl_phys2virt(qxl, addr, group_id); - if (!image) { - return 1; - } - desc = &image->descriptor; - fprintf(stderr, " (id %" PRIx64 " type %d flags %d width %d height %d", - desc->id, desc->type, desc->flags, desc->width, desc->height); - switch (desc->type) { - case SPICE_IMAGE_TYPE_BITMAP: - fprintf(stderr, ", fmt %d flags %d x %d y %d stride %d" - " palette %" PRIx64 " data %" PRIx64, - image->bitmap.format, image->bitmap.flags, - image->bitmap.x, image->bitmap.y, - image->bitmap.stride, - image->bitmap.palette, image->bitmap.data); - break; - } - fprintf(stderr, ")"); - return 0; -} - -static void qxl_log_rect(QXLRect *rect) -{ - fprintf(stderr, " %dx%d+%d+%d", - rect->right - rect->left, - rect->bottom - rect->top, - rect->left, rect->top); -} - -static int qxl_log_cmd_draw_copy(PCIQXLDevice *qxl, QXLCopy *copy, - int group_id) -{ - int ret; - - fprintf(stderr, " src %" PRIx64, - copy->src_bitmap); - ret = qxl_log_image(qxl, copy->src_bitmap, group_id); - if (ret != 0) { - return ret; - } - fprintf(stderr, " area"); - qxl_log_rect(©->src_area); - fprintf(stderr, " rop %d", copy->rop_descriptor); - return 0; -} - -static int qxl_log_cmd_draw(PCIQXLDevice *qxl, QXLDrawable *draw, int group_id) -{ - fprintf(stderr, ": surface_id %d type %s effect %s", - draw->surface_id, - qxl_name(qxl_draw_type, draw->type), - qxl_name(qxl_draw_effect, draw->effect)); - switch (draw->type) { - case QXL_DRAW_COPY: - return qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id); - break; - } - return 0; -} - -static int qxl_log_cmd_draw_compat(PCIQXLDevice *qxl, QXLCompatDrawable *draw, - int group_id) -{ - fprintf(stderr, ": type %s effect %s", - qxl_name(qxl_draw_type, draw->type), - qxl_name(qxl_draw_effect, draw->effect)); - if (draw->bitmap_offset) { - fprintf(stderr, ": bitmap %d", - draw->bitmap_offset); - qxl_log_rect(&draw->bitmap_area); - } - switch (draw->type) { - case QXL_DRAW_COPY: - return qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id); - break; - } - return 0; -} - -static void qxl_log_cmd_surface(PCIQXLDevice *qxl, QXLSurfaceCmd *cmd) -{ - fprintf(stderr, ": %s id %d", - qxl_name(qxl_surface_cmd, cmd->type), - cmd->surface_id); - if (cmd->type == QXL_SURFACE_CMD_CREATE) { - fprintf(stderr, " size %dx%d stride %d format %s (count %d, max %d)", - cmd->u.surface_create.width, - cmd->u.surface_create.height, - cmd->u.surface_create.stride, - qxl_name(spice_surface_fmt, cmd->u.surface_create.format), - qxl->guest_surfaces.count, qxl->guest_surfaces.max); - } - if (cmd->type == QXL_SURFACE_CMD_DESTROY) { - fprintf(stderr, " (count %d)", qxl->guest_surfaces.count); - } -} - -int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id) -{ - QXLCursor *cursor; - - fprintf(stderr, ": %s", - qxl_name(qxl_cursor_cmd, cmd->type)); - switch (cmd->type) { - case QXL_CURSOR_SET: - fprintf(stderr, " +%d+%d visible %s, shape @ 0x%" PRIx64, - cmd->u.set.position.x, - cmd->u.set.position.y, - cmd->u.set.visible ? "yes" : "no", - cmd->u.set.shape); - cursor = qxl_phys2virt(qxl, cmd->u.set.shape, group_id); - if (!cursor) { - return 1; - } - fprintf(stderr, " type %s size %dx%d hot-spot +%d+%d" - " unique 0x%" PRIx64 " data-size %d", - qxl_name(spice_cursor_type, cursor->header.type), - cursor->header.width, cursor->header.height, - cursor->header.hot_spot_x, cursor->header.hot_spot_y, - cursor->header.unique, cursor->data_size); - break; - case QXL_CURSOR_MOVE: - fprintf(stderr, " +%d+%d", cmd->u.position.x, cmd->u.position.y); - break; - } - return 0; -} - -int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext) -{ - bool compat = ext->flags & QXL_COMMAND_FLAG_COMPAT; - void *data; - int ret; - - if (!qxl->cmdlog) { - return 0; - } - fprintf(stderr, "%" PRId64 " qxl-%d/%s:", qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - qxl->id, ring); - fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data, - qxl_name(qxl_type, ext->cmd.type), - compat ? "(compat)" : ""); - - data = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); - if (!data) { - return 1; - } - switch (ext->cmd.type) { - case QXL_CMD_DRAW: - if (!compat) { - ret = qxl_log_cmd_draw(qxl, data, ext->group_id); - } else { - ret = qxl_log_cmd_draw_compat(qxl, data, ext->group_id); - } - if (ret) { - return ret; - } - break; - case QXL_CMD_SURFACE: - qxl_log_cmd_surface(qxl, data); - break; - case QXL_CMD_CURSOR: - qxl_log_cmd_cursor(qxl, data, ext->group_id); - break; - } - fprintf(stderr, "\n"); - return 0; -} diff --git a/qemu/hw/display/qxl-render.c b/qemu/hw/display/qxl-render.c deleted file mode 100644 index 9ad9d9e0f..000000000 --- a/qemu/hw/display/qxl-render.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * qxl local rendering (aka display on sdl/vnc) - * - * Copyright (C) 2010 Red Hat, Inc. - * - * maintained by Gerd Hoffmann - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * 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 . - */ - -#include "qemu/osdep.h" -#include "qxl.h" -#include "trace.h" - -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; - int len, i; - - if (is_buffer_shared(surface)) { - return; - } - trace_qxl_render_blit(qxl->guest_primary.qxl_stride, - rect->left, rect->right, rect->top, rect->bottom); - src = qxl->guest_primary.data; - if (qxl->guest_primary.qxl_stride < 0) { - /* qxl surface is upside down, walk src scanlines - * in reverse order to flip it */ - src += (qxl->guest_primary.surface.height - rect->top - 1) * - qxl->guest_primary.abs_stride; - } else { - src += rect->top * qxl->guest_primary.abs_stride; - } - dst += rect->top * qxl->guest_primary.abs_stride; - src += rect->left * qxl->guest_primary.bytes_pp; - dst += rect->left * qxl->guest_primary.bytes_pp; - len = (rect->right - rect->left) * qxl->guest_primary.bytes_pp; - - for (i = rect->top; i < rect->bottom; i++) { - memcpy(dst, src, len); - dst += qxl->guest_primary.abs_stride; - src += qxl->guest_primary.qxl_stride; - } -} - -void qxl_render_resize(PCIQXLDevice *qxl) -{ - QXLSurfaceCreate *sc = &qxl->guest_primary.surface; - - qxl->guest_primary.qxl_stride = sc->stride; - qxl->guest_primary.abs_stride = abs(sc->stride); - qxl->guest_primary.resized++; - switch (sc->format) { - case SPICE_SURFACE_FMT_16_555: - qxl->guest_primary.bytes_pp = 2; - qxl->guest_primary.bits_pp = 15; - break; - case SPICE_SURFACE_FMT_16_565: - qxl->guest_primary.bytes_pp = 2; - qxl->guest_primary.bits_pp = 16; - break; - case SPICE_SURFACE_FMT_32_xRGB: - case SPICE_SURFACE_FMT_32_ARGB: - qxl->guest_primary.bytes_pp = 4; - qxl->guest_primary.bits_pp = 32; - break; - default: - fprintf(stderr, "%s: unhandled format: %x\n", __FUNCTION__, - qxl->guest_primary.surface.format); - qxl->guest_primary.bytes_pp = 4; - qxl->guest_primary.bits_pp = 32; - break; - } -} - -static void qxl_set_rect_to_surface(PCIQXLDevice *qxl, QXLRect *area) -{ - area->left = 0; - area->right = qxl->guest_primary.surface.width; - area->top = 0; - area->bottom = qxl->guest_primary.surface.height; -} - -static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) -{ - VGACommonState *vga = &qxl->vga; - DisplaySurface *surface; - int i; - - if (qxl->guest_primary.resized) { - qxl->guest_primary.resized = 0; - qxl->guest_primary.data = qxl_phys2virt(qxl, - qxl->guest_primary.surface.mem, - MEMSLOT_GROUP_GUEST); - if (!qxl->guest_primary.data) { - return; - } - qxl_set_rect_to_surface(qxl, &qxl->dirty[0]); - qxl->num_dirty_rects = 1; - trace_qxl_render_guest_primary_resized( - qxl->guest_primary.surface.width, - qxl->guest_primary.surface.height, - qxl->guest_primary.qxl_stride, - qxl->guest_primary.bytes_pp, - qxl->guest_primary.bits_pp); - if (qxl->guest_primary.qxl_stride > 0) { - pixman_format_code_t format = - qemu_default_pixman_format(qxl->guest_primary.bits_pp, true); - surface = qemu_create_displaysurface_from - (qxl->guest_primary.surface.width, - qxl->guest_primary.surface.height, - format, - qxl->guest_primary.abs_stride, - qxl->guest_primary.data); - } else { - surface = qemu_create_displaysurface - (qxl->guest_primary.surface.width, - qxl->guest_primary.surface.height); - } - dpy_gfx_replace_surface(vga->con, surface); - } - - if (!qxl->guest_primary.data) { - return; - } - for (i = 0; i < qxl->num_dirty_rects; i++) { - if (qemu_spice_rect_is_empty(qxl->dirty+i)) { - break; - } - if (qxl->dirty[i].left < 0 || - qxl->dirty[i].top < 0 || - qxl->dirty[i].left > qxl->dirty[i].right || - qxl->dirty[i].top > qxl->dirty[i].bottom || - qxl->dirty[i].right > qxl->guest_primary.surface.width || - qxl->dirty[i].bottom > qxl->guest_primary.surface.height) { - continue; - } - qxl_blit(qxl, qxl->dirty+i); - 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); - } - qxl->num_dirty_rects = 0; -} - -/* - * use ssd.lock to protect render_update_cookie_num. - * qxl_render_update is called by io thread or vcpu thread, and the completion - * callbacks are called by spice_server thread, deferring to bh called from the - * io thread. - */ -void qxl_render_update(PCIQXLDevice *qxl) -{ - QXLCookie *cookie; - - qemu_mutex_lock(&qxl->ssd.lock); - - if (!runstate_is_running() || !qxl->guest_primary.commands) { - qxl_render_update_area_unlocked(qxl); - qemu_mutex_unlock(&qxl->ssd.lock); - return; - } - - qxl->guest_primary.commands = 0; - qxl->render_update_cookie_num++; - qemu_mutex_unlock(&qxl->ssd.lock); - cookie = qxl_cookie_new(QXL_COOKIE_TYPE_RENDER_UPDATE_AREA, - 0); - qxl_set_rect_to_surface(qxl, &cookie->u.render.area); - qxl_spice_update_area(qxl, 0, &cookie->u.render.area, NULL, - 0, 1 /* clear_dirty_region */, QXL_ASYNC, cookie); -} - -void qxl_render_update_area_bh(void *opaque) -{ - PCIQXLDevice *qxl = opaque; - - qemu_mutex_lock(&qxl->ssd.lock); - qxl_render_update_area_unlocked(qxl); - qemu_mutex_unlock(&qxl->ssd.lock); -} - -void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie) -{ - qemu_mutex_lock(&qxl->ssd.lock); - trace_qxl_render_update_area_done(cookie); - qemu_bh_schedule(qxl->update_area_bh); - qxl->render_update_cookie_num--; - qemu_mutex_unlock(&qxl->ssd.lock); - g_free(cookie); -} - -static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor) -{ - QEMUCursor *c; - uint8_t *image, *mask; - size_t size; - - c = cursor_alloc(cursor->header.width, cursor->header.height); - c->hot_x = cursor->header.hot_spot_x; - c->hot_y = cursor->header.hot_spot_y; - switch (cursor->header.type) { - case SPICE_CURSOR_TYPE_ALPHA: - size = sizeof(uint32_t) * cursor->header.width * cursor->header.height; - memcpy(c->data, cursor->chunk.data, size); - if (qxl->debug > 2) { - cursor_print_ascii_art(c, "qxl/alpha"); - } - break; - case SPICE_CURSOR_TYPE_MONO: - mask = cursor->chunk.data; - image = mask + cursor_get_mono_bpl(c) * c->width; - cursor_set_mono(c, 0xffffff, 0x000000, image, 1, mask); - if (qxl->debug > 2) { - cursor_print_ascii_art(c, "qxl/mono"); - } - break; - default: - fprintf(stderr, "%s: not implemented: type %d\n", - __FUNCTION__, cursor->header.type); - goto fail; - } - return c; - -fail: - cursor_put(c); - return NULL; -} - - -/* called from spice server thread context only */ -int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) -{ - QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); - QXLCursor *cursor; - QEMUCursor *c; - - if (!cmd) { - return 1; - } - - if (!dpy_cursor_define_supported(qxl->vga.con)) { - return 0; - } - - if (qxl->debug > 1 && cmd->type != QXL_CURSOR_MOVE) { - fprintf(stderr, "%s", __FUNCTION__); - qxl_log_cmd_cursor(qxl, cmd, ext->group_id); - fprintf(stderr, "\n"); - } - switch (cmd->type) { - case QXL_CURSOR_SET: - cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id); - if (!cursor) { - return 1; - } - if (cursor->chunk.data_size != cursor->data_size) { - fprintf(stderr, "%s: multiple chunks\n", __FUNCTION__); - return 1; - } - c = qxl_cursor(qxl, cursor); - if (c == NULL) { - c = cursor_builtin_left_ptr(); - } - qemu_mutex_lock(&qxl->ssd.lock); - if (qxl->ssd.cursor) { - cursor_put(qxl->ssd.cursor); - } - qxl->ssd.cursor = c; - qxl->ssd.mouse_x = cmd->u.set.position.x; - qxl->ssd.mouse_y = cmd->u.set.position.y; - qemu_mutex_unlock(&qxl->ssd.lock); - qemu_bh_schedule(qxl->ssd.cursor_bh); - break; - case QXL_CURSOR_MOVE: - qemu_mutex_lock(&qxl->ssd.lock); - qxl->ssd.mouse_x = cmd->u.position.x; - qxl->ssd.mouse_y = cmd->u.position.y; - qemu_mutex_unlock(&qxl->ssd.lock); - qemu_bh_schedule(qxl->ssd.cursor_bh); - break; - } - return 0; -} diff --git a/qemu/hw/display/qxl.c b/qemu/hw/display/qxl.c deleted file mode 100644 index 919dc5cd3..000000000 --- a/qemu/hw/display/qxl.c +++ /dev/null @@ -1,2359 +0,0 @@ -/* - * Copyright (C) 2010 Red Hat, Inc. - * - * written by Yaniv Kamay, Izik Eidus, Gerd Hoffmann - * maintained by Gerd Hoffmann - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * 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 . - */ - -#include "qemu/osdep.h" -#include - -#include "qemu-common.h" -#include "qemu/timer.h" -#include "qemu/queue.h" -#include "qemu/atomic.h" -#include "sysemu/sysemu.h" -#include "trace.h" - -#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); \ - if (cons >= ARRAY_SIZE((r)->items)) { \ - qxl_set_guest_bug(qxl, "SPICE_RING_CONS_ITEM indices mismatch " \ - "%u >= %zu", cons, ARRAY_SIZE((r)->items)); \ - ret = NULL; \ - } else { \ - ret = &(r)->items[cons].el; \ - } \ - } - -#undef ALIGN -#define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1)) - -#define PIXEL_SIZE 0.2936875 //1280x1024 is 14.8" x 11.9" - -#define QXL_MODE(_x, _y, _b, _o) \ - { .x_res = _x, \ - .y_res = _y, \ - .bits = _b, \ - .stride = (_x) * (_b) / 8, \ - .x_mili = PIXEL_SIZE * (_x), \ - .y_mili = PIXEL_SIZE * (_y), \ - .orientation = _o, \ - } - -#define QXL_MODE_16_32(x_res, y_res, orientation) \ - QXL_MODE(x_res, y_res, 16, orientation), \ - QXL_MODE(x_res, y_res, 32, orientation) - -#define QXL_MODE_EX(x_res, y_res) \ - QXL_MODE_16_32(x_res, y_res, 0), \ - QXL_MODE_16_32(x_res, y_res, 1) - -static QXLMode qxl_modes[] = { - QXL_MODE_EX(640, 480), - QXL_MODE_EX(800, 480), - QXL_MODE_EX(800, 600), - QXL_MODE_EX(832, 624), - QXL_MODE_EX(960, 640), - QXL_MODE_EX(1024, 600), - QXL_MODE_EX(1024, 768), - QXL_MODE_EX(1152, 864), - QXL_MODE_EX(1152, 870), - QXL_MODE_EX(1280, 720), - QXL_MODE_EX(1280, 760), - QXL_MODE_EX(1280, 768), - QXL_MODE_EX(1280, 800), - QXL_MODE_EX(1280, 960), - QXL_MODE_EX(1280, 1024), - QXL_MODE_EX(1360, 768), - QXL_MODE_EX(1366, 768), - QXL_MODE_EX(1400, 1050), - QXL_MODE_EX(1440, 900), - QXL_MODE_EX(1600, 900), - QXL_MODE_EX(1600, 1200), - QXL_MODE_EX(1680, 1050), - QXL_MODE_EX(1920, 1080), - /* these modes need more than 8 MB video memory */ - QXL_MODE_EX(1920, 1200), - QXL_MODE_EX(1920, 1440), - QXL_MODE_EX(2000, 2000), - QXL_MODE_EX(2048, 1536), - QXL_MODE_EX(2048, 2048), - QXL_MODE_EX(2560, 1440), - QXL_MODE_EX(2560, 1600), - /* these modes need more than 16 MB video memory */ - QXL_MODE_EX(2560, 2048), - QXL_MODE_EX(2800, 2100), - QXL_MODE_EX(3200, 2400), - /* these modes need more than 32 MB video memory */ - QXL_MODE_EX(3840, 2160), /* 4k mainstream */ - QXL_MODE_EX(4096, 2160), /* 4k */ - /* these modes need more than 64 MB video memory */ - QXL_MODE_EX(7680, 4320), /* 8k mainstream */ - /* these modes need more than 128 MB video memory */ - QXL_MODE_EX(8192, 4320), /* 8k */ -}; - -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); -static void qxl_reset_surfaces(PCIQXLDevice *d); -static void qxl_ring_set_dirty(PCIQXLDevice *qxl); - -static void qxl_hw_update(void *opaque); - -void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) -{ - trace_qxl_set_guest_bug(qxl->id); - qxl_send_events(qxl, QXL_INTERRUPT_ERROR); - qxl->guest_bug = 1; - if (qxl->guestdebug) { - va_list ap; - va_start(ap, msg); - fprintf(stderr, "qxl-%d: guest bug: ", qxl->id); - vfprintf(stderr, msg, ap); - fprintf(stderr, "\n"); - va_end(ap); - } -} - -static void qxl_clear_guest_bug(PCIQXLDevice *qxl) -{ - qxl->guest_bug = 0; -} - -void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, - struct QXLRect *area, struct QXLRect *dirty_rects, - uint32_t num_dirty_rects, - uint32_t clear_dirty_region, - qxl_async_io async, struct QXLCookie *cookie) -{ - trace_qxl_spice_update_area(qxl->id, surface_id, area->left, area->right, - area->top, area->bottom); - trace_qxl_spice_update_area_rest(qxl->id, num_dirty_rects, - clear_dirty_region); - if (async == QXL_SYNC) { - spice_qxl_update_area(&qxl->ssd.qxl, surface_id, area, - dirty_rects, num_dirty_rects, clear_dirty_region); - } else { - assert(cookie != NULL); - spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area, - clear_dirty_region, (uintptr_t)cookie); - } -} - -static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl, - uint32_t id) -{ - trace_qxl_spice_destroy_surface_wait_complete(qxl->id, id); - qemu_mutex_lock(&qxl->track_lock); - qxl->guest_surfaces.cmds[id] = 0; - qxl->guest_surfaces.count--; - qemu_mutex_unlock(&qxl->track_lock); -} - -static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id, - qxl_async_io async) -{ - QXLCookie *cookie; - - trace_qxl_spice_destroy_surface_wait(qxl->id, id, async); - if (async) { - cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO, - QXL_IO_DESTROY_SURFACE_ASYNC); - cookie->u.surface_id = id; - spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uintptr_t)cookie); - } else { - spice_qxl_destroy_surface_wait(&qxl->ssd.qxl, id); - qxl_spice_destroy_surface_wait_complete(qxl, id); - } -} - -static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl) -{ - trace_qxl_spice_flush_surfaces_async(qxl->id, qxl->guest_surfaces.count, - qxl->num_free_res); - spice_qxl_flush_surfaces_async(&qxl->ssd.qxl, - (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, - QXL_IO_FLUSH_SURFACES_ASYNC)); -} - -void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, - uint32_t count) -{ - trace_qxl_spice_loadvm_commands(qxl->id, ext, count); - spice_qxl_loadvm_commands(&qxl->ssd.qxl, ext, count); -} - -void qxl_spice_oom(PCIQXLDevice *qxl) -{ - trace_qxl_spice_oom(qxl->id); - spice_qxl_oom(&qxl->ssd.qxl); -} - -void qxl_spice_reset_memslots(PCIQXLDevice *qxl) -{ - trace_qxl_spice_reset_memslots(qxl->id); - spice_qxl_reset_memslots(&qxl->ssd.qxl); -} - -static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl) -{ - trace_qxl_spice_destroy_surfaces_complete(qxl->id); - qemu_mutex_lock(&qxl->track_lock); - memset(qxl->guest_surfaces.cmds, 0, - sizeof(qxl->guest_surfaces.cmds[0]) * qxl->ssd.num_surfaces); - qxl->guest_surfaces.count = 0; - qemu_mutex_unlock(&qxl->track_lock); -} - -static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async) -{ - trace_qxl_spice_destroy_surfaces(qxl->id, async); - if (async) { - spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl, - (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, - QXL_IO_DESTROY_ALL_SURFACES_ASYNC)); - } else { - spice_qxl_destroy_surfaces(&qxl->ssd.qxl); - qxl_spice_destroy_surfaces_complete(qxl); - } -} - -static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay) -{ - trace_qxl_spice_monitors_config(qxl->id); - if (replay) { - /* - * don't use QXL_COOKIE_TYPE_IO: - * - we are not running yet (post_load), we will assert - * in send_events - * - this is not a guest io, but a reply, so async_io isn't set. - */ - spice_qxl_monitors_config_async(&qxl->ssd.qxl, - qxl->guest_monitors_config, - MEMSLOT_GROUP_GUEST, - (uintptr_t)qxl_cookie_new( - QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG, - 0)); - } else { -#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */ - if (qxl->max_outputs) { - spice_qxl_set_max_monitors(&qxl->ssd.qxl, qxl->max_outputs); - } -#endif - qxl->guest_monitors_config = qxl->ram->monitors_config; - spice_qxl_monitors_config_async(&qxl->ssd.qxl, - qxl->ram->monitors_config, - MEMSLOT_GROUP_GUEST, - (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, - QXL_IO_MONITORS_CONFIG_ASYNC)); - } -} - -void qxl_spice_reset_image_cache(PCIQXLDevice *qxl) -{ - trace_qxl_spice_reset_image_cache(qxl->id); - spice_qxl_reset_image_cache(&qxl->ssd.qxl); -} - -void qxl_spice_reset_cursor(PCIQXLDevice *qxl) -{ - trace_qxl_spice_reset_cursor(qxl->id); - spice_qxl_reset_cursor(&qxl->ssd.qxl); - qemu_mutex_lock(&qxl->track_lock); - qxl->guest_cursor = 0; - qemu_mutex_unlock(&qxl->track_lock); - if (qxl->ssd.cursor) { - cursor_put(qxl->ssd.cursor); - } - qxl->ssd.cursor = cursor_builtin_hidden(); -} - -static ram_addr_t qxl_rom_size(void) -{ - uint32_t required_rom_size = sizeof(QXLRom) + sizeof(QXLModes) + - sizeof(qxl_modes); - uint32_t rom_size = 8192; /* two pages */ - - QEMU_BUILD_BUG_ON(required_rom_size > rom_size); - return rom_size; -} - -static void init_qxl_rom(PCIQXLDevice *d) -{ - QXLRom *rom = memory_region_get_ram_ptr(&d->rom_bar); - QXLModes *modes = (QXLModes *)(rom + 1); - uint32_t ram_header_size; - uint32_t surface0_area_size; - uint32_t num_pages; - uint32_t fb; - int i, n; - - memset(rom, 0, d->rom_size); - - rom->magic = cpu_to_le32(QXL_ROM_MAGIC); - rom->id = cpu_to_le32(d->id); - rom->log_level = cpu_to_le32(d->guestdebug); - rom->modes_offset = cpu_to_le32(sizeof(QXLRom)); - - rom->slot_gen_bits = MEMSLOT_GENERATION_BITS; - rom->slot_id_bits = MEMSLOT_SLOT_BITS; - rom->slots_start = 1; - rom->slots_end = NUM_MEMSLOTS - 1; - rom->n_surfaces = cpu_to_le32(d->ssd.num_surfaces); - - for (i = 0, n = 0; i < ARRAY_SIZE(qxl_modes); i++) { - fb = qxl_modes[i].y_res * qxl_modes[i].stride; - if (fb > d->vgamem_size) { - continue; - } - modes->modes[n].id = cpu_to_le32(i); - modes->modes[n].x_res = cpu_to_le32(qxl_modes[i].x_res); - modes->modes[n].y_res = cpu_to_le32(qxl_modes[i].y_res); - modes->modes[n].bits = cpu_to_le32(qxl_modes[i].bits); - modes->modes[n].stride = cpu_to_le32(qxl_modes[i].stride); - modes->modes[n].x_mili = cpu_to_le32(qxl_modes[i].x_mili); - modes->modes[n].y_mili = cpu_to_le32(qxl_modes[i].y_mili); - modes->modes[n].orientation = cpu_to_le32(qxl_modes[i].orientation); - n++; - } - modes->n_modes = cpu_to_le32(n); - - ram_header_size = ALIGN(sizeof(QXLRam), 4096); - surface0_area_size = ALIGN(d->vgamem_size, 4096); - num_pages = d->vga.vram_size; - num_pages -= ram_header_size; - num_pages -= surface0_area_size; - num_pages = num_pages / QXL_PAGE_SIZE; - - assert(ram_header_size + surface0_area_size <= d->vga.vram_size); - - rom->draw_area_offset = cpu_to_le32(0); - rom->surface0_area_size = cpu_to_le32(surface0_area_size); - rom->pages_offset = cpu_to_le32(surface0_area_size); - rom->num_pages = cpu_to_le32(num_pages); - rom->ram_header_offset = cpu_to_le32(d->vga.vram_size - ram_header_size); - - d->shadow_rom = *rom; - d->rom = rom; - d->modes = modes; -} - -static void init_qxl_ram(PCIQXLDevice *d) -{ - uint8_t *buf; - uint64_t *item; - - buf = d->vga.vram_ptr; - d->ram = (QXLRam *)(buf + le32_to_cpu(d->shadow_rom.ram_header_offset)); - d->ram->magic = cpu_to_le32(QXL_RAM_MAGIC); - d->ram->int_pending = cpu_to_le32(0); - d->ram->int_mask = cpu_to_le32(0); - d->ram->update_surface = 0; - d->ram->monitors_config = 0; - 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; - qxl_ring_set_dirty(d); -} - -/* can be called from spice server thread context */ -static void qxl_set_dirty(MemoryRegion *mr, ram_addr_t addr, ram_addr_t end) -{ - memory_region_set_dirty(mr, addr, end - addr); -} - -static void qxl_rom_set_dirty(PCIQXLDevice *qxl) -{ - qxl_set_dirty(&qxl->rom_bar, 0, qxl->rom_size); -} - -/* called from spice server thread context only */ -static void qxl_ram_set_dirty(PCIQXLDevice *qxl, void *ptr) -{ - void *base = qxl->vga.vram_ptr; - intptr_t offset; - - offset = ptr - base; - assert(offset < qxl->vga.vram_size); - qxl_set_dirty(&qxl->vga.vram, offset, offset + 3); -} - -/* can be called from spice server thread context */ -static void qxl_ring_set_dirty(PCIQXLDevice *qxl) -{ - ram_addr_t addr = qxl->shadow_rom.ram_header_offset; - ram_addr_t end = qxl->vga.vram_size; - qxl_set_dirty(&qxl->vga.vram, addr, end); -} - -/* - * keep track of some command state, for savevm/loadvm. - * called from spice server thread context only - */ -static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) -{ - switch (le32_to_cpu(ext->cmd.type)) { - case QXL_CMD_SURFACE: - { - QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); - - if (!cmd) { - return 1; - } - uint32_t id = le32_to_cpu(cmd->surface_id); - - if (id >= qxl->ssd.num_surfaces) { - qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE id %d >= %d", id, - qxl->ssd.num_surfaces); - return 1; - } - if (cmd->type == QXL_SURFACE_CMD_CREATE && - (cmd->u.surface_create.stride & 0x03) != 0) { - qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE stride = %d %% 4 != 0\n", - cmd->u.surface_create.stride); - return 1; - } - qemu_mutex_lock(&qxl->track_lock); - if (cmd->type == QXL_SURFACE_CMD_CREATE) { - qxl->guest_surfaces.cmds[id] = ext->cmd.data; - qxl->guest_surfaces.count++; - if (qxl->guest_surfaces.max < qxl->guest_surfaces.count) - qxl->guest_surfaces.max = qxl->guest_surfaces.count; - } - if (cmd->type == QXL_SURFACE_CMD_DESTROY) { - qxl->guest_surfaces.cmds[id] = 0; - qxl->guest_surfaces.count--; - } - qemu_mutex_unlock(&qxl->track_lock); - break; - } - case QXL_CMD_CURSOR: - { - QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); - - if (!cmd) { - return 1; - } - if (cmd->type == QXL_CURSOR_SET) { - qemu_mutex_lock(&qxl->track_lock); - qxl->guest_cursor = ext->cmd.data; - qemu_mutex_unlock(&qxl->track_lock); - } - break; - } - } - return 0; -} - -/* spice display interface callbacks */ - -static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - - trace_qxl_interface_attach_worker(qxl->id); - qxl->ssd.worker = qxl_worker; -} - -static void interface_set_compression_level(QXLInstance *sin, int level) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - - trace_qxl_interface_set_compression_level(qxl->id, level); - qxl->shadow_rom.compression_level = cpu_to_le32(level); - qxl->rom->compression_level = cpu_to_le32(level); - qxl_rom_set_dirty(qxl); -} - -static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - - if (!qemu_spice_display_is_running(&qxl->ssd)) { - return; - } - - trace_qxl_interface_set_mm_time(qxl->id, mm_time); - qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time); - qxl->rom->mm_clock = cpu_to_le32(mm_time); - qxl_rom_set_dirty(qxl); -} - -static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - - trace_qxl_interface_get_init_info(qxl->id); - info->memslot_gen_bits = MEMSLOT_GENERATION_BITS; - info->memslot_id_bits = MEMSLOT_SLOT_BITS; - info->num_memslots = NUM_MEMSLOTS; - info->num_memslots_groups = NUM_MEMSLOTS_GROUPS; - info->internal_groupslot_id = 0; - info->qxl_ram_size = - le32_to_cpu(qxl->shadow_rom.num_pages) << QXL_PAGE_BITS; - info->n_surfaces = qxl->ssd.num_surfaces; -} - -static const char *qxl_mode_to_string(int mode) -{ - switch (mode) { - case QXL_MODE_COMPAT: - return "compat"; - case QXL_MODE_NATIVE: - return "native"; - case QXL_MODE_UNDEFINED: - return "undefined"; - case QXL_MODE_VGA: - return "vga"; - } - return "INVALID"; -} - -static const char *io_port_to_string(uint32_t io_port) -{ - if (io_port >= QXL_IO_RANGE_SIZE) { - return "out of range"; - } - static const char *io_port_to_string[QXL_IO_RANGE_SIZE + 1] = { - [QXL_IO_NOTIFY_CMD] = "QXL_IO_NOTIFY_CMD", - [QXL_IO_NOTIFY_CURSOR] = "QXL_IO_NOTIFY_CURSOR", - [QXL_IO_UPDATE_AREA] = "QXL_IO_UPDATE_AREA", - [QXL_IO_UPDATE_IRQ] = "QXL_IO_UPDATE_IRQ", - [QXL_IO_NOTIFY_OOM] = "QXL_IO_NOTIFY_OOM", - [QXL_IO_RESET] = "QXL_IO_RESET", - [QXL_IO_SET_MODE] = "QXL_IO_SET_MODE", - [QXL_IO_LOG] = "QXL_IO_LOG", - [QXL_IO_MEMSLOT_ADD] = "QXL_IO_MEMSLOT_ADD", - [QXL_IO_MEMSLOT_DEL] = "QXL_IO_MEMSLOT_DEL", - [QXL_IO_DETACH_PRIMARY] = "QXL_IO_DETACH_PRIMARY", - [QXL_IO_ATTACH_PRIMARY] = "QXL_IO_ATTACH_PRIMARY", - [QXL_IO_CREATE_PRIMARY] = "QXL_IO_CREATE_PRIMARY", - [QXL_IO_DESTROY_PRIMARY] = "QXL_IO_DESTROY_PRIMARY", - [QXL_IO_DESTROY_SURFACE_WAIT] = "QXL_IO_DESTROY_SURFACE_WAIT", - [QXL_IO_DESTROY_ALL_SURFACES] = "QXL_IO_DESTROY_ALL_SURFACES", - [QXL_IO_UPDATE_AREA_ASYNC] = "QXL_IO_UPDATE_AREA_ASYNC", - [QXL_IO_MEMSLOT_ADD_ASYNC] = "QXL_IO_MEMSLOT_ADD_ASYNC", - [QXL_IO_CREATE_PRIMARY_ASYNC] = "QXL_IO_CREATE_PRIMARY_ASYNC", - [QXL_IO_DESTROY_PRIMARY_ASYNC] = "QXL_IO_DESTROY_PRIMARY_ASYNC", - [QXL_IO_DESTROY_SURFACE_ASYNC] = "QXL_IO_DESTROY_SURFACE_ASYNC", - [QXL_IO_DESTROY_ALL_SURFACES_ASYNC] - = "QXL_IO_DESTROY_ALL_SURFACES_ASYNC", - [QXL_IO_FLUSH_SURFACES_ASYNC] = "QXL_IO_FLUSH_SURFACES_ASYNC", - [QXL_IO_FLUSH_RELEASE] = "QXL_IO_FLUSH_RELEASE", - [QXL_IO_MONITORS_CONFIG_ASYNC] = "QXL_IO_MONITORS_CONFIG_ASYNC", - }; - return io_port_to_string[io_port]; -} - -/* called from spice server thread context only */ -static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - SimpleSpiceUpdate *update; - QXLCommandRing *ring; - QXLCommand *cmd; - int notify, ret; - - trace_qxl_ring_command_check(qxl->id, qxl_mode_to_string(qxl->mode)); - - switch (qxl->mode) { - case QXL_MODE_VGA: - ret = false; - qemu_mutex_lock(&qxl->ssd.lock); - update = QTAILQ_FIRST(&qxl->ssd.updates); - if (update != NULL) { - QTAILQ_REMOVE(&qxl->ssd.updates, update, next); - *ext = update->ext; - ret = true; - } - qemu_mutex_unlock(&qxl->ssd.lock); - if (ret) { - trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode)); - qxl_log_command(qxl, "vga", ext); - } - return ret; - case QXL_MODE_COMPAT: - case QXL_MODE_NATIVE: - case QXL_MODE_UNDEFINED: - ring = &qxl->ram->cmd_ring; - if (qxl->guest_bug || SPICE_RING_IS_EMPTY(ring)) { - return false; - } - SPICE_RING_CONS_ITEM(qxl, ring, cmd); - if (!cmd) { - return false; - } - ext->cmd = *cmd; - ext->group_id = MEMSLOT_GROUP_GUEST; - ext->flags = qxl->cmdflags; - SPICE_RING_POP(ring, notify); - qxl_ring_set_dirty(qxl); - if (notify) { - qxl_send_events(qxl, QXL_INTERRUPT_DISPLAY); - } - qxl->guest_primary.commands++; - qxl_track_command(qxl, ext); - qxl_log_command(qxl, "cmd", ext); - trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode)); - return true; - default: - return false; - } -} - -/* called from spice server thread context only */ -static int interface_req_cmd_notification(QXLInstance *sin) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - int wait = 1; - - trace_qxl_ring_command_req_notification(qxl->id); - switch (qxl->mode) { - case QXL_MODE_COMPAT: - case QXL_MODE_NATIVE: - case QXL_MODE_UNDEFINED: - SPICE_RING_CONS_WAIT(&qxl->ram->cmd_ring, wait); - qxl_ring_set_dirty(qxl); - break; - default: - /* nothing */ - break; - } - return wait; -} - -/* called from spice server thread context only */ -static inline void qxl_push_free_res(PCIQXLDevice *d, int flush) -{ - QXLReleaseRing *ring = &d->ram->release_ring; - uint64_t *item; - int notify; - -#define QXL_FREE_BUNCH_SIZE 32 - - if (ring->prod - ring->cons + 1 == ring->num_items) { - /* ring full -- can't push */ - return; - } - if (!flush && d->oom_running) { - /* collect everything from oom handler before pushing */ - return; - } - if (!flush && d->num_free_res < QXL_FREE_BUNCH_SIZE) { - /* collect a bit more before pushing */ - return; - } - - SPICE_RING_PUSH(ring, notify); - trace_qxl_ring_res_push(d->id, qxl_mode_to_string(d->mode), - d->guest_surfaces.count, d->num_free_res, - d->last_release, notify ? "yes" : "no"); - trace_qxl_ring_res_push_rest(d->id, ring->prod - ring->cons, - ring->num_items, ring->prod, ring->cons); - if (notify) { - qxl_send_events(d, QXL_INTERRUPT_DISPLAY); - } - SPICE_RING_PROD_ITEM(d, ring, item); - if (!item) { - return; - } - *item = 0; - d->num_free_res = 0; - d->last_release = NULL; - qxl_ring_set_dirty(d); -} - -/* called from spice server thread context only */ -static void interface_release_resource(QXLInstance *sin, - QXLReleaseInfoExt ext) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - QXLReleaseRing *ring; - uint64_t *item, id; - - if (ext.group_id == MEMSLOT_GROUP_HOST) { - /* host group -> vga mode update request */ - QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id); - SimpleSpiceUpdate *update; - g_assert(cmdext->cmd.type == QXL_CMD_DRAW); - update = container_of(cmdext, SimpleSpiceUpdate, ext); - qemu_spice_destroy_update(&qxl->ssd, update); - return; - } - - /* - * ext->info points into guest-visible memory - * pci bar 0, $command.release_info - */ - ring = &qxl->ram->release_ring; - SPICE_RING_PROD_ITEM(qxl, ring, item); - if (!item) { - return; - } - if (*item == 0) { - /* stick head into the ring */ - id = ext.info->id; - ext.info->next = 0; - qxl_ram_set_dirty(qxl, &ext.info->next); - *item = id; - qxl_ring_set_dirty(qxl); - } else { - /* append item to the list */ - qxl->last_release->next = ext.info->id; - qxl_ram_set_dirty(qxl, &qxl->last_release->next); - ext.info->next = 0; - qxl_ram_set_dirty(qxl, &ext.info->next); - } - qxl->last_release = ext.info; - qxl->num_free_res++; - trace_qxl_ring_res_put(qxl->id, qxl->num_free_res); - qxl_push_free_res(qxl, 0); -} - -/* called from spice server thread context only */ -static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - QXLCursorRing *ring; - QXLCommand *cmd; - int notify; - - trace_qxl_ring_cursor_check(qxl->id, qxl_mode_to_string(qxl->mode)); - - switch (qxl->mode) { - case QXL_MODE_COMPAT: - case QXL_MODE_NATIVE: - case QXL_MODE_UNDEFINED: - ring = &qxl->ram->cursor_ring; - if (SPICE_RING_IS_EMPTY(ring)) { - return false; - } - SPICE_RING_CONS_ITEM(qxl, ring, cmd); - if (!cmd) { - return false; - } - ext->cmd = *cmd; - ext->group_id = MEMSLOT_GROUP_GUEST; - ext->flags = qxl->cmdflags; - SPICE_RING_POP(ring, notify); - qxl_ring_set_dirty(qxl); - if (notify) { - qxl_send_events(qxl, QXL_INTERRUPT_CURSOR); - } - qxl->guest_primary.commands++; - qxl_track_command(qxl, ext); - qxl_log_command(qxl, "csr", ext); - if (qxl->id == 0) { - qxl_render_cursor(qxl, ext); - } - trace_qxl_ring_cursor_get(qxl->id, qxl_mode_to_string(qxl->mode)); - return true; - default: - return false; - } -} - -/* called from spice server thread context only */ -static int interface_req_cursor_notification(QXLInstance *sin) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - int wait = 1; - - trace_qxl_ring_cursor_req_notification(qxl->id); - switch (qxl->mode) { - case QXL_MODE_COMPAT: - case QXL_MODE_NATIVE: - case QXL_MODE_UNDEFINED: - SPICE_RING_CONS_WAIT(&qxl->ram->cursor_ring, wait); - qxl_ring_set_dirty(qxl); - break; - default: - /* nothing */ - break; - } - return wait; -} - -/* called from spice server thread context */ -static void interface_notify_update(QXLInstance *sin, uint32_t update_id) -{ - /* - * Called by spice-server as a result of a QXL_CMD_UPDATE which is not in - * use by xf86-video-qxl and is defined out in the qxl windows driver. - * Probably was at some earlier version that is prior to git start (2009), - * and is still guest trigerrable. - */ - fprintf(stderr, "%s: deprecated\n", __func__); -} - -/* called from spice server thread context only */ -static int interface_flush_resources(QXLInstance *sin) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - int ret; - - ret = qxl->num_free_res; - if (ret) { - qxl_push_free_res(qxl, 1); - } - return ret; -} - -static void qxl_create_guest_primary_complete(PCIQXLDevice *d); - -/* called from spice server thread context only */ -static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie) -{ - uint32_t current_async; - - qemu_mutex_lock(&qxl->async_lock); - current_async = qxl->current_async; - qxl->current_async = QXL_UNDEFINED_IO; - qemu_mutex_unlock(&qxl->async_lock); - - trace_qxl_interface_async_complete_io(qxl->id, current_async, cookie); - if (!cookie) { - fprintf(stderr, "qxl: %s: error, cookie is NULL\n", __func__); - return; - } - if (cookie && current_async != cookie->io) { - fprintf(stderr, - "qxl: %s: error: current_async = %d != %" - PRId64 " = cookie->io\n", __func__, current_async, cookie->io); - } - switch (current_async) { - case QXL_IO_MEMSLOT_ADD_ASYNC: - case QXL_IO_DESTROY_PRIMARY_ASYNC: - case QXL_IO_UPDATE_AREA_ASYNC: - case QXL_IO_FLUSH_SURFACES_ASYNC: - case QXL_IO_MONITORS_CONFIG_ASYNC: - break; - case QXL_IO_CREATE_PRIMARY_ASYNC: - qxl_create_guest_primary_complete(qxl); - break; - case QXL_IO_DESTROY_ALL_SURFACES_ASYNC: - qxl_spice_destroy_surfaces_complete(qxl); - break; - case QXL_IO_DESTROY_SURFACE_ASYNC: - qxl_spice_destroy_surface_wait_complete(qxl, cookie->u.surface_id); - break; - default: - fprintf(stderr, "qxl: %s: unexpected current_async %d\n", __func__, - current_async); - } - qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD); -} - -/* called from spice server thread context only */ -static void interface_update_area_complete(QXLInstance *sin, - uint32_t surface_id, - QXLRect *dirty, uint32_t num_updated_rects) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - int i; - int qxl_i; - - qemu_mutex_lock(&qxl->ssd.lock); - if (surface_id != 0 || !qxl->render_update_cookie_num) { - qemu_mutex_unlock(&qxl->ssd.lock); - return; - } - trace_qxl_interface_update_area_complete(qxl->id, surface_id, dirty->left, - dirty->right, dirty->top, dirty->bottom); - trace_qxl_interface_update_area_complete_rest(qxl->id, num_updated_rects); - if (qxl->num_dirty_rects + num_updated_rects > QXL_NUM_DIRTY_RECTS) { - /* - * overflow - treat this as a full update. Not expected to be common. - */ - trace_qxl_interface_update_area_complete_overflow(qxl->id, - QXL_NUM_DIRTY_RECTS); - qxl->guest_primary.resized = 1; - } - if (qxl->guest_primary.resized) { - /* - * Don't bother copying or scheduling the bh since we will flip - * the whole area anyway on completion of the update_area async call - */ - qemu_mutex_unlock(&qxl->ssd.lock); - return; - } - qxl_i = qxl->num_dirty_rects; - for (i = 0; i < num_updated_rects; i++) { - qxl->dirty[qxl_i++] = dirty[i]; - } - qxl->num_dirty_rects += num_updated_rects; - trace_qxl_interface_update_area_complete_schedule_bh(qxl->id, - qxl->num_dirty_rects); - qemu_bh_schedule(qxl->update_area_bh); - qemu_mutex_unlock(&qxl->ssd.lock); -} - -/* called from spice server thread context only */ -static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - QXLCookie *cookie = (QXLCookie *)(uintptr_t)cookie_token; - - switch (cookie->type) { - case QXL_COOKIE_TYPE_IO: - interface_async_complete_io(qxl, cookie); - g_free(cookie); - break; - case QXL_COOKIE_TYPE_RENDER_UPDATE_AREA: - qxl_render_update_area_done(qxl, cookie); - break; - case QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG: - break; - default: - fprintf(stderr, "qxl: %s: unexpected cookie type %d\n", - __func__, cookie->type); - g_free(cookie); - } -} - -/* called from spice server thread context only */ -static void interface_set_client_capabilities(QXLInstance *sin, - uint8_t client_present, - uint8_t caps[58]) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - - if (qxl->revision < 4) { - trace_qxl_set_client_capabilities_unsupported_by_revision(qxl->id, - qxl->revision); - return; - } - - if (runstate_check(RUN_STATE_INMIGRATE) || - runstate_check(RUN_STATE_POSTMIGRATE)) { - return; - } - - qxl->shadow_rom.client_present = client_present; - memcpy(qxl->shadow_rom.client_capabilities, caps, - sizeof(qxl->shadow_rom.client_capabilities)); - qxl->rom->client_present = client_present; - memcpy(qxl->rom->client_capabilities, caps, - sizeof(qxl->rom->client_capabilities)); - qxl_rom_set_dirty(qxl); - - qxl_send_events(qxl, QXL_INTERRUPT_CLIENT); -} - -static uint32_t qxl_crc32(const uint8_t *p, unsigned len) -{ - /* - * zlib xors the seed with 0xffffffff, and xors the result - * again with 0xffffffff; Both are not done with linux's crc32, - * which we want to be compatible with, so undo that. - */ - return crc32(0xffffffff, p, len) ^ 0xffffffff; -} - -/* called from main context only */ -static int interface_client_monitors_config(QXLInstance *sin, - VDAgentMonitorsConfig *monitors_config) -{ - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); - QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar); - int i; - unsigned max_outputs = ARRAY_SIZE(rom->client_monitors_config.heads); - - if (qxl->revision < 4) { - trace_qxl_client_monitors_config_unsupported_by_device(qxl->id, - qxl->revision); - return 0; - } - /* - * Older windows drivers set int_mask to 0 when their ISR is called, - * then later set it to ~0. So it doesn't relate to the actual interrupts - * handled. However, they are old, so clearly they don't support this - * interrupt - */ - if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 || - !(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) { - trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id, - qxl->ram->int_mask, - monitors_config); - return 0; - } - if (!monitors_config) { - return 1; - } - -#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */ - /* limit number of outputs based on setting limit */ - if (qxl->max_outputs && qxl->max_outputs <= max_outputs) { - max_outputs = qxl->max_outputs; - } -#endif - - memset(&rom->client_monitors_config, 0, - sizeof(rom->client_monitors_config)); - rom->client_monitors_config.count = monitors_config->num_of_monitors; - /* monitors_config->flags ignored */ - if (rom->client_monitors_config.count >= max_outputs) { - trace_qxl_client_monitors_config_capped(qxl->id, - monitors_config->num_of_monitors, - max_outputs); - rom->client_monitors_config.count = max_outputs; - } - for (i = 0 ; i < rom->client_monitors_config.count ; ++i) { - VDAgentMonConfig *monitor = &monitors_config->monitors[i]; - QXLURect *rect = &rom->client_monitors_config.heads[i]; - /* monitor->depth ignored */ - rect->left = monitor->x; - rect->top = monitor->y; - rect->right = monitor->x + monitor->width; - rect->bottom = monitor->y + monitor->height; - } - rom->client_monitors_config_crc = qxl_crc32( - (const uint8_t *)&rom->client_monitors_config, - sizeof(rom->client_monitors_config)); - trace_qxl_client_monitors_config_crc(qxl->id, - sizeof(rom->client_monitors_config), - rom->client_monitors_config_crc); - - trace_qxl_interrupt_client_monitors_config(qxl->id, - rom->client_monitors_config.count, - rom->client_monitors_config.heads); - qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG); - return 1; -} - -static const QXLInterface qxl_interface = { - .base.type = SPICE_INTERFACE_QXL, - .base.description = "qxl gpu", - .base.major_version = SPICE_INTERFACE_QXL_MAJOR, - .base.minor_version = SPICE_INTERFACE_QXL_MINOR, - - .attache_worker = interface_attach_worker, - .set_compression_level = interface_set_compression_level, - .set_mm_time = interface_set_mm_time, - .get_init_info = interface_get_init_info, - - /* the callbacks below are called from spice server thread context */ - .get_command = interface_get_command, - .req_cmd_notification = interface_req_cmd_notification, - .release_resource = interface_release_resource, - .get_cursor_command = interface_get_cursor_command, - .req_cursor_notification = interface_req_cursor_notification, - .notify_update = interface_notify_update, - .flush_resources = interface_flush_resources, - .async_complete = interface_async_complete, - .update_area_complete = interface_update_area_complete, - .set_client_capabilities = interface_set_client_capabilities, - .client_monitors_config = interface_client_monitors_config, -}; - -static const GraphicHwOps qxl_ops = { - .gfx_update = qxl_hw_update, -}; - -static void qxl_enter_vga_mode(PCIQXLDevice *d) -{ - if (d->mode == QXL_MODE_VGA) { - return; - } - trace_qxl_enter_vga_mode(d->id); -#if SPICE_SERVER_VERSION >= 0x000c03 /* release 0.12.3 */ - spice_qxl_driver_unload(&d->ssd.qxl); -#endif - graphic_console_set_hwops(d->ssd.dcl.con, d->vga.hw_ops, &d->vga); - update_displaychangelistener(&d->ssd.dcl, GUI_REFRESH_INTERVAL_DEFAULT); - qemu_spice_create_host_primary(&d->ssd); - d->mode = QXL_MODE_VGA; - vga_dirty_log_start(&d->vga); - graphic_hw_update(d->vga.con); -} - -static void qxl_exit_vga_mode(PCIQXLDevice *d) -{ - if (d->mode != QXL_MODE_VGA) { - return; - } - trace_qxl_exit_vga_mode(d->id); - graphic_console_set_hwops(d->ssd.dcl.con, &qxl_ops, d); - update_displaychangelistener(&d->ssd.dcl, GUI_REFRESH_INTERVAL_IDLE); - vga_dirty_log_stop(&d->vga); - qxl_destroy_primary(d, QXL_SYNC); -} - -static void qxl_update_irq(PCIQXLDevice *d) -{ - uint32_t pending = le32_to_cpu(d->ram->int_pending); - uint32_t mask = le32_to_cpu(d->ram->int_mask); - int level = !!(pending & mask); - pci_set_irq(&d->pci, level); - qxl_ring_set_dirty(d); -} - -static void qxl_check_state(PCIQXLDevice *d) -{ - QXLRam *ram = d->ram; - int spice_display_running = qemu_spice_display_is_running(&d->ssd); - - assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cmd_ring)); - assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cursor_ring)); -} - -static void qxl_reset_state(PCIQXLDevice *d) -{ - QXLRom *rom = d->rom; - - qxl_check_state(d); - d->shadow_rom.update_id = cpu_to_le32(0); - *rom = d->shadow_rom; - qxl_rom_set_dirty(d); - init_qxl_ram(d); - d->num_free_res = 0; - d->last_release = NULL; - memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty)); - qxl_update_irq(d); -} - -static void qxl_soft_reset(PCIQXLDevice *d) -{ - trace_qxl_soft_reset(d->id); - qxl_check_state(d); - qxl_clear_guest_bug(d); - qemu_mutex_lock(&d->async_lock); - d->current_async = QXL_UNDEFINED_IO; - qemu_mutex_unlock(&d->async_lock); - - if (d->id == 0) { - qxl_enter_vga_mode(d); - } else { - d->mode = QXL_MODE_UNDEFINED; - } -} - -static void qxl_hard_reset(PCIQXLDevice *d, int loadvm) -{ - bool startstop = qemu_spice_display_is_running(&d->ssd); - - trace_qxl_hard_reset(d->id, loadvm); - - if (startstop) { - qemu_spice_display_stop(); - } - - qxl_spice_reset_cursor(d); - qxl_spice_reset_image_cache(d); - qxl_reset_surfaces(d); - qxl_reset_memslots(d); - - /* pre loadvm reset must not touch QXLRam. This lives in - * device memory, is migrated together with RAM and thus - * already loaded at this point */ - if (!loadvm) { - qxl_reset_state(d); - } - qemu_spice_create_host_memslot(&d->ssd); - qxl_soft_reset(d); - - if (startstop) { - qemu_spice_display_start(); - } -} - -static void qxl_reset_handler(DeviceState *dev) -{ - PCIQXLDevice *d = PCI_QXL(PCI_DEVICE(dev)); - - qxl_hard_reset(d, 0); -} - -static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) -{ - VGACommonState *vga = opaque; - PCIQXLDevice *qxl = container_of(vga, PCIQXLDevice, vga); - - trace_qxl_io_write_vga(qxl->id, qxl_mode_to_string(qxl->mode), addr, val); - if (qxl->mode != QXL_MODE_VGA) { - qxl_destroy_primary(qxl, QXL_SYNC); - qxl_soft_reset(qxl); - } - vga_ioport_write(opaque, addr, val); -} - -static const MemoryRegionPortio qxl_vga_portio_list[] = { - { 0x04, 2, 1, .read = vga_ioport_read, - .write = qxl_vga_ioport_write }, /* 3b4 */ - { 0x0a, 1, 1, .read = vga_ioport_read, - .write = qxl_vga_ioport_write }, /* 3ba */ - { 0x10, 16, 1, .read = vga_ioport_read, - .write = qxl_vga_ioport_write }, /* 3c0 */ - { 0x24, 2, 1, .read = vga_ioport_read, - .write = qxl_vga_ioport_write }, /* 3d4 */ - { 0x2a, 1, 1, .read = vga_ioport_read, - .write = qxl_vga_ioport_write }, /* 3da */ - PORTIO_END_OF_LIST(), -}; - -static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta, - qxl_async_io async) -{ - static const int regions[] = { - QXL_RAM_RANGE_INDEX, - QXL_VRAM_RANGE_INDEX, - QXL_VRAM64_RANGE_INDEX, - }; - uint64_t guest_start; - uint64_t guest_end; - int pci_region; - pcibus_t pci_start; - pcibus_t pci_end; - intptr_t virt_start; - QXLDevMemSlot memslot; - int i; - - guest_start = le64_to_cpu(d->guest_slots[slot_id].slot.mem_start); - guest_end = le64_to_cpu(d->guest_slots[slot_id].slot.mem_end); - - trace_qxl_memslot_add_guest(d->id, slot_id, guest_start, guest_end); - - if (slot_id >= NUM_MEMSLOTS) { - qxl_set_guest_bug(d, "%s: slot_id >= NUM_MEMSLOTS %d >= %d", __func__, - slot_id, NUM_MEMSLOTS); - return 1; - } - if (guest_start > guest_end) { - qxl_set_guest_bug(d, "%s: guest_start > guest_end 0x%" PRIx64 - " > 0x%" PRIx64, __func__, guest_start, guest_end); - return 1; - } - - for (i = 0; i < ARRAY_SIZE(regions); i++) { - pci_region = regions[i]; - pci_start = d->pci.io_regions[pci_region].addr; - pci_end = pci_start + d->pci.io_regions[pci_region].size; - /* mapped? */ - if (pci_start == -1) { - continue; - } - /* start address in range ? */ - if (guest_start < pci_start || guest_start > pci_end) { - continue; - } - /* end address in range ? */ - if (guest_end > pci_end) { - continue; - } - /* passed */ - break; - } - if (i == ARRAY_SIZE(regions)) { - qxl_set_guest_bug(d, "%s: finished loop without match", __func__); - return 1; - } - - switch (pci_region) { - case QXL_RAM_RANGE_INDEX: - virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vga.vram); - break; - case QXL_VRAM_RANGE_INDEX: - case 4 /* vram 64bit */: - virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vram_bar); - break; - default: - /* should not happen */ - qxl_set_guest_bug(d, "%s: pci_region = %d", __func__, pci_region); - return 1; - } - - memslot.slot_id = slot_id; - memslot.slot_group_id = MEMSLOT_GROUP_GUEST; /* guest group */ - memslot.virt_start = virt_start + (guest_start - pci_start); - memslot.virt_end = virt_start + (guest_end - pci_start); - memslot.addr_delta = memslot.virt_start - delta; - memslot.generation = d->rom->slot_generation = 0; - qxl_rom_set_dirty(d); - - qemu_spice_add_memslot(&d->ssd, &memslot, async); - d->guest_slots[slot_id].ptr = (void*)memslot.virt_start; - d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start; - d->guest_slots[slot_id].delta = delta; - d->guest_slots[slot_id].active = 1; - return 0; -} - -static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id) -{ - qemu_spice_del_memslot(&d->ssd, MEMSLOT_GROUP_HOST, slot_id); - d->guest_slots[slot_id].active = 0; -} - -static void qxl_reset_memslots(PCIQXLDevice *d) -{ - qxl_spice_reset_memslots(d); - memset(&d->guest_slots, 0, sizeof(d->guest_slots)); -} - -static void qxl_reset_surfaces(PCIQXLDevice *d) -{ - trace_qxl_reset_surfaces(d->id); - d->mode = QXL_MODE_UNDEFINED; - qxl_spice_destroy_surfaces(d, QXL_SYNC); -} - -/* can be also called from spice server thread context */ -void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id) -{ - uint64_t phys = le64_to_cpu(pqxl); - uint32_t slot = (phys >> (64 - 8)) & 0xff; - uint64_t offset = phys & 0xffffffffffff; - - switch (group_id) { - case MEMSLOT_GROUP_HOST: - return (void *)(intptr_t)offset; - case MEMSLOT_GROUP_GUEST: - if (slot >= NUM_MEMSLOTS) { - qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot, - NUM_MEMSLOTS); - return NULL; - } - if (!qxl->guest_slots[slot].active) { - qxl_set_guest_bug(qxl, "inactive slot %d\n", slot); - return NULL; - } - if (offset < qxl->guest_slots[slot].delta) { - qxl_set_guest_bug(qxl, - "slot %d offset %"PRIu64" < delta %"PRIu64"\n", - slot, offset, qxl->guest_slots[slot].delta); - return NULL; - } - offset -= qxl->guest_slots[slot].delta; - if (offset > qxl->guest_slots[slot].size) { - qxl_set_guest_bug(qxl, - "slot %d offset %"PRIu64" > size %"PRIu64"\n", - slot, offset, qxl->guest_slots[slot].size); - return NULL; - } - return qxl->guest_slots[slot].ptr + offset; - } - return NULL; -} - -static void qxl_create_guest_primary_complete(PCIQXLDevice *qxl) -{ - /* for local rendering */ - qxl_render_resize(qxl); -} - -static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm, - qxl_async_io async) -{ - QXLDevSurfaceCreate surface; - QXLSurfaceCreate *sc = &qxl->guest_primary.surface; - uint32_t requested_height = le32_to_cpu(sc->height); - int requested_stride = le32_to_cpu(sc->stride); - - if (requested_stride == INT32_MIN || - abs(requested_stride) * (uint64_t)requested_height - > qxl->vgamem_size) { - qxl_set_guest_bug(qxl, "%s: requested primary larger than framebuffer" - " stride %d x height %" PRIu32 " > %" PRIu32, - __func__, requested_stride, requested_height, - qxl->vgamem_size); - return; - } - - if (qxl->mode == QXL_MODE_NATIVE) { - qxl_set_guest_bug(qxl, "%s: nop since already in QXL_MODE_NATIVE", - __func__); - } - qxl_exit_vga_mode(qxl); - - surface.format = le32_to_cpu(sc->format); - surface.height = le32_to_cpu(sc->height); - surface.mem = le64_to_cpu(sc->mem); - surface.position = le32_to_cpu(sc->position); - surface.stride = le32_to_cpu(sc->stride); - surface.width = le32_to_cpu(sc->width); - surface.type = le32_to_cpu(sc->type); - surface.flags = le32_to_cpu(sc->flags); - trace_qxl_create_guest_primary(qxl->id, sc->width, sc->height, sc->mem, - sc->format, sc->position); - trace_qxl_create_guest_primary_rest(qxl->id, sc->stride, sc->type, - sc->flags); - - if ((surface.stride & 0x3) != 0) { - qxl_set_guest_bug(qxl, "primary surface stride = %d %% 4 != 0", - surface.stride); - return; - } - - surface.mouse_mode = true; - surface.group_id = MEMSLOT_GROUP_GUEST; - if (loadvm) { - surface.flags |= QXL_SURF_FLAG_KEEP_DATA; - } - - qxl->mode = QXL_MODE_NATIVE; - qxl->cmdflags = 0; - qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface, async); - - if (async == QXL_SYNC) { - qxl_create_guest_primary_complete(qxl); - } -} - -/* return 1 if surface destoy was initiated (in QXL_ASYNC case) or - * done (in QXL_SYNC case), 0 otherwise. */ -static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async) -{ - if (d->mode == QXL_MODE_UNDEFINED) { - return 0; - } - trace_qxl_destroy_primary(d->id); - d->mode = QXL_MODE_UNDEFINED; - qemu_spice_destroy_primary_surface(&d->ssd, 0, async); - qxl_spice_reset_cursor(d); - return 1; -} - -static void qxl_set_mode(PCIQXLDevice *d, unsigned int modenr, int loadvm) -{ - pcibus_t start = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr; - pcibus_t end = d->pci.io_regions[QXL_RAM_RANGE_INDEX].size + start; - QXLMode *mode = d->modes->modes + modenr; - uint64_t devmem = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr; - QXLMemSlot slot = { - .mem_start = start, - .mem_end = end - }; - - if (modenr >= d->modes->n_modes) { - qxl_set_guest_bug(d, "mode number out of range"); - return; - } - - QXLSurfaceCreate surface = { - .width = mode->x_res, - .height = mode->y_res, - .stride = -mode->x_res * 4, - .format = SPICE_SURFACE_FMT_32_xRGB, - .flags = loadvm ? QXL_SURF_FLAG_KEEP_DATA : 0, - .mouse_mode = true, - .mem = devmem + d->shadow_rom.draw_area_offset, - }; - - trace_qxl_set_mode(d->id, modenr, mode->x_res, mode->y_res, mode->bits, - devmem); - if (!loadvm) { - qxl_hard_reset(d, 0); - } - - d->guest_slots[0].slot = slot; - assert(qxl_add_memslot(d, 0, devmem, QXL_SYNC) == 0); - - d->guest_primary.surface = surface; - qxl_create_guest_primary(d, 0, QXL_SYNC); - - d->mode = QXL_MODE_COMPAT; - d->cmdflags = QXL_COMMAND_FLAG_COMPAT; - if (mode->bits == 16) { - d->cmdflags |= QXL_COMMAND_FLAG_COMPAT_16BPP; - } - d->shadow_rom.mode = cpu_to_le32(modenr); - d->rom->mode = cpu_to_le32(modenr); - qxl_rom_set_dirty(d); -} - -static void ioport_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - PCIQXLDevice *d = opaque; - uint32_t io_port = addr; - qxl_async_io async = QXL_SYNC; - uint32_t orig_io_port = io_port; - - if (d->guest_bug && io_port != QXL_IO_RESET) { - return; - } - - if (d->revision <= QXL_REVISION_STABLE_V10 && - io_port > QXL_IO_FLUSH_RELEASE) { - qxl_set_guest_bug(d, "unsupported io %d for revision %d\n", - io_port, d->revision); - return; - } - - switch (io_port) { - case QXL_IO_RESET: - case QXL_IO_SET_MODE: - case QXL_IO_MEMSLOT_ADD: - case QXL_IO_MEMSLOT_DEL: - case QXL_IO_CREATE_PRIMARY: - case QXL_IO_UPDATE_IRQ: - case QXL_IO_LOG: - case QXL_IO_MEMSLOT_ADD_ASYNC: - case QXL_IO_CREATE_PRIMARY_ASYNC: - break; - default: - if (d->mode != QXL_MODE_VGA) { - break; - } - trace_qxl_io_unexpected_vga_mode(d->id, - addr, val, io_port_to_string(io_port)); - /* be nice to buggy guest drivers */ - if (io_port >= QXL_IO_UPDATE_AREA_ASYNC && - io_port < QXL_IO_RANGE_SIZE) { - qxl_send_events(d, QXL_INTERRUPT_IO_CMD); - } - return; - } - - /* we change the io_port to avoid ifdeffery in the main switch */ - orig_io_port = io_port; - switch (io_port) { - case QXL_IO_UPDATE_AREA_ASYNC: - io_port = QXL_IO_UPDATE_AREA; - goto async_common; - case QXL_IO_MEMSLOT_ADD_ASYNC: - io_port = QXL_IO_MEMSLOT_ADD; - goto async_common; - case QXL_IO_CREATE_PRIMARY_ASYNC: - io_port = QXL_IO_CREATE_PRIMARY; - goto async_common; - case QXL_IO_DESTROY_PRIMARY_ASYNC: - io_port = QXL_IO_DESTROY_PRIMARY; - goto async_common; - case QXL_IO_DESTROY_SURFACE_ASYNC: - io_port = QXL_IO_DESTROY_SURFACE_WAIT; - goto async_common; - case QXL_IO_DESTROY_ALL_SURFACES_ASYNC: - io_port = QXL_IO_DESTROY_ALL_SURFACES; - goto async_common; - case QXL_IO_FLUSH_SURFACES_ASYNC: - case QXL_IO_MONITORS_CONFIG_ASYNC: -async_common: - async = QXL_ASYNC; - qemu_mutex_lock(&d->async_lock); - if (d->current_async != QXL_UNDEFINED_IO) { - qxl_set_guest_bug(d, "%d async started before last (%d) complete", - io_port, d->current_async); - qemu_mutex_unlock(&d->async_lock); - return; - } - d->current_async = orig_io_port; - qemu_mutex_unlock(&d->async_lock); - break; - default: - break; - } - trace_qxl_io_write(d->id, qxl_mode_to_string(d->mode), - addr, io_port_to_string(addr), - val, size, async); - - switch (io_port) { - case QXL_IO_UPDATE_AREA: - { - QXLCookie *cookie = NULL; - QXLRect update = d->ram->update_area; - - if (d->ram->update_surface > d->ssd.num_surfaces) { - qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid surface id %d\n", - d->ram->update_surface); - break; - } - if (update.left >= update.right || update.top >= update.bottom || - update.left < 0 || update.top < 0) { - qxl_set_guest_bug(d, - "QXL_IO_UPDATE_AREA: invalid area (%ux%u)x(%ux%u)\n", - update.left, update.top, update.right, update.bottom); - if (update.left == update.right || update.top == update.bottom) { - /* old drivers may provide empty area, keep going */ - qxl_clear_guest_bug(d); - goto cancel_async; - } - break; - } - if (async == QXL_ASYNC) { - cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO, - QXL_IO_UPDATE_AREA_ASYNC); - cookie->u.area = update; - } - qxl_spice_update_area(d, d->ram->update_surface, - cookie ? &cookie->u.area : &update, - NULL, 0, 0, async, cookie); - break; - } - case QXL_IO_NOTIFY_CMD: - qemu_spice_wakeup(&d->ssd); - break; - case QXL_IO_NOTIFY_CURSOR: - qemu_spice_wakeup(&d->ssd); - break; - case QXL_IO_UPDATE_IRQ: - qxl_update_irq(d); - break; - case QXL_IO_NOTIFY_OOM: - if (!SPICE_RING_IS_EMPTY(&d->ram->release_ring)) { - break; - } - d->oom_running = 1; - qxl_spice_oom(d); - d->oom_running = 0; - break; - case QXL_IO_SET_MODE: - qxl_set_mode(d, val, 0); - break; - case QXL_IO_LOG: - trace_qxl_io_log(d->id, d->ram->log_buf); - if (d->guestdebug) { - fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), d->ram->log_buf); - } - break; - case QXL_IO_RESET: - qxl_hard_reset(d, 0); - break; - case QXL_IO_MEMSLOT_ADD: - if (val >= NUM_MEMSLOTS) { - qxl_set_guest_bug(d, "QXL_IO_MEMSLOT_ADD: val out of range"); - break; - } - if (d->guest_slots[val].active) { - qxl_set_guest_bug(d, - "QXL_IO_MEMSLOT_ADD: memory slot already active"); - break; - } - d->guest_slots[val].slot = d->ram->mem_slot; - qxl_add_memslot(d, val, 0, async); - break; - case QXL_IO_MEMSLOT_DEL: - if (val >= NUM_MEMSLOTS) { - qxl_set_guest_bug(d, "QXL_IO_MEMSLOT_DEL: val out of range"); - break; - } - qxl_del_memslot(d, val); - break; - case QXL_IO_CREATE_PRIMARY: - if (val != 0) { - qxl_set_guest_bug(d, "QXL_IO_CREATE_PRIMARY (async=%d): val != 0", - async); - goto cancel_async; - } - d->guest_primary.surface = d->ram->create_surface; - qxl_create_guest_primary(d, 0, async); - break; - case QXL_IO_DESTROY_PRIMARY: - if (val != 0) { - qxl_set_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0", - async); - goto cancel_async; - } - if (!qxl_destroy_primary(d, async)) { - trace_qxl_io_destroy_primary_ignored(d->id, - qxl_mode_to_string(d->mode)); - goto cancel_async; - } - break; - case QXL_IO_DESTROY_SURFACE_WAIT: - if (val >= d->ssd.num_surfaces) { - qxl_set_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):" - "%" PRIu64 " >= NUM_SURFACES", async, val); - goto cancel_async; - } - qxl_spice_destroy_surface_wait(d, val, async); - break; - case QXL_IO_FLUSH_RELEASE: { - QXLReleaseRing *ring = &d->ram->release_ring; - if (ring->prod - ring->cons + 1 == ring->num_items) { - fprintf(stderr, - "ERROR: no flush, full release ring [p%d,%dc]\n", - ring->prod, ring->cons); - } - qxl_push_free_res(d, 1 /* flush */); - break; - } - case QXL_IO_FLUSH_SURFACES_ASYNC: - qxl_spice_flush_surfaces_async(d); - break; - case QXL_IO_DESTROY_ALL_SURFACES: - d->mode = QXL_MODE_UNDEFINED; - qxl_spice_destroy_surfaces(d, async); - break; - case QXL_IO_MONITORS_CONFIG_ASYNC: - qxl_spice_monitors_config_async(d, 0); - break; - default: - qxl_set_guest_bug(d, "%s: unexpected ioport=0x%x\n", __func__, io_port); - } - return; -cancel_async: - if (async) { - qxl_send_events(d, QXL_INTERRUPT_IO_CMD); - qemu_mutex_lock(&d->async_lock); - d->current_async = QXL_UNDEFINED_IO; - qemu_mutex_unlock(&d->async_lock); - } -} - -static uint64_t ioport_read(void *opaque, hwaddr addr, - unsigned size) -{ - PCIQXLDevice *qxl = opaque; - - trace_qxl_io_read_unexpected(qxl->id); - return 0xff; -} - -static const MemoryRegionOps qxl_io_ops = { - .read = ioport_read, - .write = ioport_write, - .valid = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void qxl_update_irq_bh(void *opaque) -{ - PCIQXLDevice *d = opaque; - qxl_update_irq(d); -} - -static void qxl_send_events(PCIQXLDevice *d, uint32_t events) -{ - uint32_t old_pending; - uint32_t le_events = cpu_to_le32(events); - - trace_qxl_send_events(d->id, events); - if (!qemu_spice_display_is_running(&d->ssd)) { - /* spice-server tracks guest running state and should not do this */ - fprintf(stderr, "%s: spice-server bug: guest stopped, ignoring\n", - __func__); - trace_qxl_send_events_vm_stopped(d->id, events); - return; - } - old_pending = atomic_fetch_or(&d->ram->int_pending, le_events); - if ((old_pending & le_events) == le_events) { - return; - } - qemu_bh_schedule(d->update_irq); -} - -/* graphics console */ - -static void qxl_hw_update(void *opaque) -{ - PCIQXLDevice *qxl = opaque; - - qxl_render_update(qxl); -} - -static void qxl_dirty_surfaces(PCIQXLDevice *qxl) -{ - uintptr_t vram_start; - int i; - - if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) { - return; - } - - /* dirty the primary surface */ - qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset, - qxl->shadow_rom.surface0_area_size); - - vram_start = (uintptr_t)memory_region_get_ram_ptr(&qxl->vram_bar); - - /* dirty the off-screen surfaces */ - for (i = 0; i < qxl->ssd.num_surfaces; i++) { - QXLSurfaceCmd *cmd; - intptr_t surface_offset; - int surface_size; - - if (qxl->guest_surfaces.cmds[i] == 0) { - continue; - } - - cmd = qxl_phys2virt(qxl, qxl->guest_surfaces.cmds[i], - MEMSLOT_GROUP_GUEST); - assert(cmd); - assert(cmd->type == QXL_SURFACE_CMD_CREATE); - surface_offset = (intptr_t)qxl_phys2virt(qxl, - cmd->u.surface_create.data, - MEMSLOT_GROUP_GUEST); - assert(surface_offset); - surface_offset -= vram_start; - surface_size = cmd->u.surface_create.height * - abs(cmd->u.surface_create.stride); - trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size); - qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size); - } -} - -static void qxl_vm_change_state_handler(void *opaque, int running, - RunState state) -{ - PCIQXLDevice *qxl = opaque; - - if (running) { - /* - * if qxl_send_events was called from spice server context before - * migration ended, qxl_update_irq for these events might not have been - * called - */ - qxl_update_irq(qxl); - } else { - /* make sure surfaces are saved before migration */ - qxl_dirty_surfaces(qxl); - } -} - -/* display change listener */ - -static void display_update(DisplayChangeListener *dcl, - int x, int y, int w, int 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_switch(DisplayChangeListener *dcl, - struct DisplaySurface *surface) -{ - 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(DisplayChangeListener *dcl) -{ - PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); - - if (qxl->mode == QXL_MODE_VGA) { - qemu_spice_display_refresh(&qxl->ssd); - } -} - -static DisplayChangeListenerOps display_listener_ops = { - .dpy_name = "spice/qxl", - .dpy_gfx_update = display_update, - .dpy_gfx_switch = display_switch, - .dpy_refresh = display_refresh, -}; - -static void qxl_init_ramsize(PCIQXLDevice *qxl) -{ - /* vga mode framebuffer / primary surface (bar 0, first part) */ - if (qxl->vgamem_size_mb < 8) { - qxl->vgamem_size_mb = 8; - } - /* XXX: we round vgamem_size_mb up to a nearest power of two and it must be - * less than vga_common_init()'s maximum on qxl->vga.vram_size (512 now). - */ - if (qxl->vgamem_size_mb > 256) { - qxl->vgamem_size_mb = 256; - } - qxl->vgamem_size = qxl->vgamem_size_mb * 1024 * 1024; - - /* vga ram (bar 0, total) */ - if (qxl->ram_size_mb != -1) { - qxl->vga.vram_size = qxl->ram_size_mb * 1024 * 1024; - } - if (qxl->vga.vram_size < qxl->vgamem_size * 2) { - qxl->vga.vram_size = qxl->vgamem_size * 2; - } - - /* vram32 (surfaces, 32bit, bar 1) */ - if (qxl->vram32_size_mb != -1) { - qxl->vram32_size = qxl->vram32_size_mb * 1024 * 1024; - } - if (qxl->vram32_size < 4096) { - qxl->vram32_size = 4096; - } - - /* vram (surfaces, 64bit, bar 4+5) */ - if (qxl->vram_size_mb != -1) { - qxl->vram_size = qxl->vram_size_mb * 1024 * 1024; - } - if (qxl->vram_size < qxl->vram32_size) { - qxl->vram_size = qxl->vram32_size; - } - - if (qxl->revision == 1) { - qxl->vram32_size = 4096; - qxl->vram_size = 4096; - } - qxl->vgamem_size = pow2ceil(qxl->vgamem_size); - qxl->vga.vram_size = pow2ceil(qxl->vga.vram_size); - qxl->vram32_size = pow2ceil(qxl->vram32_size); - qxl->vram_size = pow2ceil(qxl->vram_size); -} - -static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp) -{ - uint8_t* config = qxl->pci.config; - uint32_t pci_device_rev; - uint32_t io_size; - - qxl->mode = QXL_MODE_UNDEFINED; - qxl->generation = 1; - qxl->num_memslots = NUM_MEMSLOTS; - qemu_mutex_init(&qxl->track_lock); - qemu_mutex_init(&qxl->async_lock); - qxl->current_async = QXL_UNDEFINED_IO; - qxl->guest_bug = 0; - - switch (qxl->revision) { - case 1: /* spice 0.4 -- qxl-1 */ - pci_device_rev = QXL_REVISION_STABLE_V04; - io_size = 8; - break; - case 2: /* spice 0.6 -- qxl-2 */ - pci_device_rev = QXL_REVISION_STABLE_V06; - io_size = 16; - break; - case 3: /* qxl-3 */ - pci_device_rev = QXL_REVISION_STABLE_V10; - io_size = 32; /* PCI region size must be pow2 */ - break; - case 4: /* qxl-4 */ - pci_device_rev = QXL_REVISION_STABLE_V12; - io_size = pow2ceil(QXL_IO_RANGE_SIZE); - break; - default: - error_setg(errp, "Invalid revision %d for qxl device (max %d)", - qxl->revision, QXL_DEFAULT_REVISION); - return; - } - - pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev); - pci_set_byte(&config[PCI_INTERRUPT_PIN], 1); - - qxl->rom_size = qxl_rom_size(); - memory_region_init_ram(&qxl->rom_bar, OBJECT(qxl), "qxl.vrom", - qxl->rom_size, &error_fatal); - vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev); - init_qxl_rom(qxl); - init_qxl_ram(qxl); - - qxl->guest_surfaces.cmds = g_new0(QXLPHYSICAL, qxl->ssd.num_surfaces); - memory_region_init_ram(&qxl->vram_bar, OBJECT(qxl), "qxl.vram", - qxl->vram_size, &error_fatal); - vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev); - memory_region_init_alias(&qxl->vram32_bar, OBJECT(qxl), "qxl.vram32", - &qxl->vram_bar, 0, qxl->vram32_size); - - memory_region_init_io(&qxl->io_bar, OBJECT(qxl), &qxl_io_ops, qxl, - "qxl-ioports", io_size); - if (qxl->id == 0) { - vga_dirty_log_start(&qxl->vga); - } - memory_region_set_flush_coalesced(&qxl->io_bar); - - - pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX, - PCI_BASE_ADDRESS_SPACE_IO, &qxl->io_bar); - - pci_register_bar(&qxl->pci, QXL_ROM_RANGE_INDEX, - PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->rom_bar); - - pci_register_bar(&qxl->pci, QXL_RAM_RANGE_INDEX, - PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vga.vram); - - pci_register_bar(&qxl->pci, QXL_VRAM_RANGE_INDEX, - PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vram32_bar); - - if (qxl->vram32_size < qxl->vram_size) { - /* - * Make the 64bit vram bar show up only in case it is - * configured to be larger than the 32bit vram bar. - */ - pci_register_bar(&qxl->pci, QXL_VRAM64_RANGE_INDEX, - PCI_BASE_ADDRESS_SPACE_MEMORY | - PCI_BASE_ADDRESS_MEM_TYPE_64 | - PCI_BASE_ADDRESS_MEM_PREFETCH, - &qxl->vram_bar); - } - - /* print pci bar details */ - dprint(qxl, 1, "ram/%s: %d MB [region 0]\n", - qxl->id == 0 ? "pri" : "sec", - qxl->vga.vram_size / (1024*1024)); - dprint(qxl, 1, "vram/32: %d MB [region 1]\n", - qxl->vram32_size / (1024*1024)); - dprint(qxl, 1, "vram/64: %d MB %s\n", - qxl->vram_size / (1024*1024), - qxl->vram32_size < qxl->vram_size ? "[region 4]" : "[unmapped]"); - - qxl->ssd.qxl.base.sif = &qxl_interface.base; - if (qemu_spice_add_display_interface(&qxl->ssd.qxl, qxl->vga.con) != 0) { - error_setg(errp, "qxl interface %d.%d not supported by spice-server", - SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR); - return; - } - qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl); - - qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl); - qxl_reset_state(qxl); - - qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl); - qxl->ssd.cursor_bh = qemu_bh_new(qemu_spice_cursor_refresh_bh, &qxl->ssd); -} - -static void qxl_realize_primary(PCIDevice *dev, Error **errp) -{ - PCIQXLDevice *qxl = PCI_QXL(dev); - VGACommonState *vga = &qxl->vga; - Error *local_err = NULL; - - qxl->id = 0; - qxl_init_ramsize(qxl); - vga->vbe_size = qxl->vgamem_size; - vga->vram_size_mb = qxl->vga.vram_size >> 20; - vga_common_init(vga, OBJECT(dev), true); - vga_init(vga, OBJECT(dev), - pci_address_space(dev), pci_address_space_io(dev), false); - portio_list_init(&qxl->vga_port_list, OBJECT(dev), qxl_vga_portio_list, - vga, "vga"); - portio_list_set_flush_coalesced(&qxl->vga_port_list); - portio_list_add(&qxl->vga_port_list, pci_address_space_io(dev), 0x3b0); - - vga->con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl); - qemu_spice_display_init_common(&qxl->ssd); - - qxl_realize_common(qxl, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - qxl->ssd.dcl.ops = &display_listener_ops; - qxl->ssd.dcl.con = vga->con; - register_displaychangelistener(&qxl->ssd.dcl); -} - -static void qxl_realize_secondary(PCIDevice *dev, Error **errp) -{ - static int device_id = 1; - PCIQXLDevice *qxl = PCI_QXL(dev); - - qxl->id = device_id++; - qxl_init_ramsize(qxl); - memory_region_init_ram(&qxl->vga.vram, OBJECT(dev), "qxl.vgavram", - qxl->vga.vram_size, &error_fatal); - vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev); - qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram); - qxl->vga.con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl); - - qxl_realize_common(qxl, errp); -} - -static void qxl_pre_save(void *opaque) -{ - PCIQXLDevice* d = opaque; - uint8_t *ram_start = d->vga.vram_ptr; - - trace_qxl_pre_save(d->id); - if (d->last_release == NULL) { - d->last_release_offset = 0; - } else { - d->last_release_offset = (uint8_t *)d->last_release - ram_start; - } - assert(d->last_release_offset < d->vga.vram_size); -} - -static int qxl_pre_load(void *opaque) -{ - PCIQXLDevice* d = opaque; - - trace_qxl_pre_load(d->id); - qxl_hard_reset(d, 1); - qxl_exit_vga_mode(d); - return 0; -} - -static void qxl_create_memslots(PCIQXLDevice *d) -{ - int i; - - for (i = 0; i < NUM_MEMSLOTS; i++) { - if (!d->guest_slots[i].active) { - continue; - } - qxl_add_memslot(d, i, 0, QXL_SYNC); - } -} - -static int qxl_post_load(void *opaque, int version) -{ - PCIQXLDevice* d = opaque; - uint8_t *ram_start = d->vga.vram_ptr; - QXLCommandExt *cmds; - int in, out, newmode; - - assert(d->last_release_offset < d->vga.vram_size); - if (d->last_release_offset == 0) { - d->last_release = NULL; - } else { - d->last_release = (QXLReleaseInfo *)(ram_start + d->last_release_offset); - } - - d->modes = (QXLModes*)((uint8_t*)d->rom + d->rom->modes_offset); - - trace_qxl_post_load(d->id, qxl_mode_to_string(d->mode)); - newmode = d->mode; - d->mode = QXL_MODE_UNDEFINED; - - switch (newmode) { - case QXL_MODE_UNDEFINED: - qxl_create_memslots(d); - break; - case QXL_MODE_VGA: - qxl_create_memslots(d); - qxl_enter_vga_mode(d); - break; - case QXL_MODE_NATIVE: - qxl_create_memslots(d); - qxl_create_guest_primary(d, 1, QXL_SYNC); - - /* replay surface-create and cursor-set commands */ - cmds = g_new0(QXLCommandExt, d->ssd.num_surfaces + 1); - for (in = 0, out = 0; in < d->ssd.num_surfaces; in++) { - if (d->guest_surfaces.cmds[in] == 0) { - continue; - } - cmds[out].cmd.data = d->guest_surfaces.cmds[in]; - cmds[out].cmd.type = QXL_CMD_SURFACE; - cmds[out].group_id = MEMSLOT_GROUP_GUEST; - out++; - } - if (d->guest_cursor) { - cmds[out].cmd.data = d->guest_cursor; - cmds[out].cmd.type = QXL_CMD_CURSOR; - cmds[out].group_id = MEMSLOT_GROUP_GUEST; - out++; - } - qxl_spice_loadvm_commands(d, cmds, out); - g_free(cmds); - if (d->guest_monitors_config) { - qxl_spice_monitors_config_async(d, 1); - } - break; - case QXL_MODE_COMPAT: - /* note: no need to call qxl_create_memslots, qxl_set_mode - * creates the mem slot. */ - qxl_set_mode(d, d->shadow_rom.mode, 1); - break; - } - return 0; -} - -#define QXL_SAVE_VERSION 21 - -static bool qxl_monitors_config_needed(void *opaque) -{ - PCIQXLDevice *qxl = opaque; - - return qxl->guest_monitors_config != 0; -} - - -static VMStateDescription qxl_memslot = { - .name = "qxl-memslot", - .version_id = QXL_SAVE_VERSION, - .minimum_version_id = QXL_SAVE_VERSION, - .fields = (VMStateField[]) { - VMSTATE_UINT64(slot.mem_start, struct guest_slots), - VMSTATE_UINT64(slot.mem_end, struct guest_slots), - VMSTATE_UINT32(active, struct guest_slots), - VMSTATE_END_OF_LIST() - } -}; - -static VMStateDescription qxl_surface = { - .name = "qxl-surface", - .version_id = QXL_SAVE_VERSION, - .minimum_version_id = QXL_SAVE_VERSION, - .fields = (VMStateField[]) { - VMSTATE_UINT32(width, QXLSurfaceCreate), - VMSTATE_UINT32(height, QXLSurfaceCreate), - VMSTATE_INT32(stride, QXLSurfaceCreate), - VMSTATE_UINT32(format, QXLSurfaceCreate), - VMSTATE_UINT32(position, QXLSurfaceCreate), - VMSTATE_UINT32(mouse_mode, QXLSurfaceCreate), - VMSTATE_UINT32(flags, QXLSurfaceCreate), - VMSTATE_UINT32(type, QXLSurfaceCreate), - VMSTATE_UINT64(mem, QXLSurfaceCreate), - VMSTATE_END_OF_LIST() - } -}; - -static VMStateDescription qxl_vmstate_monitors_config = { - .name = "qxl/monitors-config", - .version_id = 1, - .minimum_version_id = 1, - .needed = qxl_monitors_config_needed, - .fields = (VMStateField[]) { - VMSTATE_UINT64(guest_monitors_config, PCIQXLDevice), - VMSTATE_END_OF_LIST() - }, -}; - -static VMStateDescription qxl_vmstate = { - .name = "qxl", - .version_id = QXL_SAVE_VERSION, - .minimum_version_id = QXL_SAVE_VERSION, - .pre_save = qxl_pre_save, - .pre_load = qxl_pre_load, - .post_load = qxl_post_load, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(pci, PCIQXLDevice), - VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState), - VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice), - VMSTATE_UINT32(num_free_res, PCIQXLDevice), - VMSTATE_UINT32(last_release_offset, PCIQXLDevice), - VMSTATE_UINT32(mode, PCIQXLDevice), - VMSTATE_UINT32(ssd.unique, PCIQXLDevice), - VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice), - VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0, - qxl_memslot, struct guest_slots), - VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0, - qxl_surface, QXLSurfaceCreate), - VMSTATE_INT32_EQUAL(ssd.num_surfaces, PCIQXLDevice), - VMSTATE_VARRAY_INT32(guest_surfaces.cmds, PCIQXLDevice, - ssd.num_surfaces, 0, - vmstate_info_uint64, uint64_t), - VMSTATE_UINT64(guest_cursor, PCIQXLDevice), - VMSTATE_END_OF_LIST() - }, - .subsections = (const VMStateDescription*[]) { - &qxl_vmstate_monitors_config, - NULL - } -}; - -static Property qxl_properties[] = { - DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, - 64 * 1024 * 1024), - DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram32_size, - 64 * 1024 * 1024), - DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, - QXL_DEFAULT_REVISION), - DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0), - DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0), - DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0), - DEFINE_PROP_UINT32("ram_size_mb", PCIQXLDevice, ram_size_mb, -1), - DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, -1), - DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1), - DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16), - DEFINE_PROP_INT32("surfaces", PCIQXLDevice, ssd.num_surfaces, 1024), -#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */ - DEFINE_PROP_UINT16("max_outputs", PCIQXLDevice, max_outputs, 0), -#endif - DEFINE_PROP_END_OF_LIST(), -}; - -static void qxl_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->vendor_id = REDHAT_PCI_VENDOR_ID; - k->device_id = QXL_DEVICE_ID_STABLE; - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); - dc->reset = qxl_reset_handler; - dc->vmsd = &qxl_vmstate; - dc->props = qxl_properties; -} - -static const TypeInfo qxl_pci_type_info = { - .name = TYPE_PCI_QXL, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIQXLDevice), - .abstract = true, - .class_init = qxl_pci_class_init, -}; - -static void qxl_primary_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = qxl_realize_primary; - k->romfile = "vgabios-qxl.bin"; - k->class_id = PCI_CLASS_DISPLAY_VGA; - dc->desc = "Spice QXL GPU (primary, vga compatible)"; - dc->hotpluggable = false; -} - -static const TypeInfo qxl_primary_info = { - .name = "qxl-vga", - .parent = TYPE_PCI_QXL, - .class_init = qxl_primary_class_init, -}; - -static void qxl_secondary_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = qxl_realize_secondary; - k->class_id = PCI_CLASS_DISPLAY_OTHER; - dc->desc = "Spice QXL GPU (secondary)"; -} - -static const TypeInfo qxl_secondary_info = { - .name = "qxl", - .parent = TYPE_PCI_QXL, - .class_init = qxl_secondary_class_init, -}; - -static void qxl_register_types(void) -{ - type_register_static(&qxl_pci_type_info); - type_register_static(&qxl_primary_info); - type_register_static(&qxl_secondary_info); -} - -type_init(qxl_register_types) diff --git a/qemu/hw/display/qxl.h b/qemu/hw/display/qxl.h deleted file mode 100644 index 2ddf065e1..000000000 --- a/qemu/hw/display/qxl.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef HW_QXL_H -#define HW_QXL_H 1 - -#include "qemu-common.h" - -#include "ui/console.h" -#include "hw/hw.h" -#include "hw/pci/pci.h" -#include "vga_int.h" -#include "qemu/thread.h" - -#include "ui/qemu-spice.h" -#include "ui/spice-display.h" - -enum qxl_mode { - QXL_MODE_UNDEFINED, - QXL_MODE_VGA, - QXL_MODE_COMPAT, /* spice 0.4.x */ - QXL_MODE_NATIVE, -}; - -#ifndef QXL_VRAM64_RANGE_INDEX -#define QXL_VRAM64_RANGE_INDEX 4 -#endif - -#define QXL_UNDEFINED_IO UINT32_MAX - -#define QXL_NUM_DIRTY_RECTS 64 - -#define QXL_PAGE_BITS 12 -#define QXL_PAGE_SIZE (1 << QXL_PAGE_BITS); - -typedef struct PCIQXLDevice { - PCIDevice pci; - PortioList vga_port_list; - SimpleSpiceDisplay ssd; - int id; - uint32_t debug; - uint32_t guestdebug; - uint32_t cmdlog; - - uint32_t guest_bug; - - enum qxl_mode mode; - uint32_t cmdflags; - int generation; - uint32_t revision; - - int32_t num_memslots; - - uint32_t current_async; - QemuMutex async_lock; - - struct guest_slots { - QXLMemSlot slot; - void *ptr; - uint64_t size; - uint64_t delta; - uint32_t active; - } guest_slots[NUM_MEMSLOTS]; - - struct guest_primary { - QXLSurfaceCreate surface; - uint32_t commands; - uint32_t resized; - int32_t qxl_stride; - uint32_t abs_stride; - uint32_t bits_pp; - uint32_t bytes_pp; - uint8_t *data; - } guest_primary; - - struct surfaces { - QXLPHYSICAL *cmds; - uint32_t count; - uint32_t max; - } guest_surfaces; - QXLPHYSICAL guest_cursor; - - QXLPHYSICAL guest_monitors_config; - - QemuMutex track_lock; - - /* thread signaling */ - QEMUBH *update_irq; - - /* ram pci bar */ - QXLRam *ram; - VGACommonState vga; - uint32_t num_free_res; - QXLReleaseInfo *last_release; - uint32_t last_release_offset; - uint32_t oom_running; - uint32_t vgamem_size; - - /* rom pci bar */ - QXLRom shadow_rom; - QXLRom *rom; - QXLModes *modes; - uint32_t rom_size; - MemoryRegion rom_bar; -#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */ - uint16_t max_outputs; -#endif - - /* vram pci bar */ - uint32_t vram_size; - MemoryRegion vram_bar; - uint32_t vram32_size; - MemoryRegion vram32_bar; - - /* io bar */ - MemoryRegion io_bar; - - /* user-friendly properties (in megabytes) */ - uint32_t ram_size_mb; - uint32_t vram_size_mb; - uint32_t vram32_size_mb; - uint32_t vgamem_size_mb; - - /* qxl_render_update state */ - int render_update_cookie_num; - int num_dirty_rects; - QXLRect dirty[QXL_NUM_DIRTY_RECTS]; - QEMUBH *update_area_bh; -} PCIQXLDevice; - -#define TYPE_PCI_QXL "pci-qxl" -#define PCI_QXL(obj) OBJECT_CHECK(PCIQXLDevice, (obj), TYPE_PCI_QXL) - -#define PANIC_ON(x) if ((x)) { \ - printf("%s: PANIC %s failed\n", __FUNCTION__, #x); \ - abort(); \ -} - -#define dprint(_qxl, _level, _fmt, ...) \ - do { \ - if (_qxl->debug >= _level) { \ - fprintf(stderr, "qxl-%d: ", _qxl->id); \ - fprintf(stderr, _fmt, ## __VA_ARGS__); \ - } \ - } while (0) - -#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V12 - -/* qxl.c */ -void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); -void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) - GCC_FMT_ATTR(2, 3); - -void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, - struct QXLRect *area, struct QXLRect *dirty_rects, - uint32_t num_dirty_rects, - uint32_t clear_dirty_region, - qxl_async_io async, QXLCookie *cookie); -void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, - uint32_t count); -void qxl_spice_oom(PCIQXLDevice *qxl); -void qxl_spice_reset_memslots(PCIQXLDevice *qxl); -void qxl_spice_reset_image_cache(PCIQXLDevice *qxl); -void qxl_spice_reset_cursor(PCIQXLDevice *qxl); - -/* qxl-logger.c */ -int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id); -int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext); - -/* qxl-render.c */ -void qxl_render_resize(PCIQXLDevice *qxl); -void qxl_render_update(PCIQXLDevice *qxl); -int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext); -void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie); -void qxl_render_update_area_bh(void *opaque); - -#endif diff --git a/qemu/hw/display/sm501.c b/qemu/hw/display/sm501.c deleted file mode 100644 index 5f7101210..000000000 --- a/qemu/hw/display/sm501.c +++ /dev/null @@ -1,1458 +0,0 @@ -/* - * QEMU SM501 Device - * - * Copyright (c) 2008 Shin-ichiro KAWASAKI - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "qemu-common.h" -#include "cpu.h" -#include "hw/hw.h" -#include "hw/char/serial.h" -#include "ui/console.h" -#include "hw/devices.h" -#include "hw/sysbus.h" -#include "qemu/range.h" -#include "ui/pixel_ops.h" -#include "exec/address-spaces.h" - -/* - * Status: 2010/05/07 - * - Minimum implementation for Linux console : mmio regs and CRT layer. - * - 2D grapihcs acceleration partially supported : only fill rectangle. - * - * TODO: - * - Panel support - * - Touch panel support - * - USB support - * - UART support - * - More 2D graphics engine support - * - Performance tuning - */ - -//#define DEBUG_SM501 -//#define DEBUG_BITBLT - -#ifdef DEBUG_SM501 -#define SM501_DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else -#define SM501_DPRINTF(fmt, ...) do {} while(0) -#endif - - -#define MMIO_BASE_OFFSET 0x3e00000 - -/* SM501 register definitions taken from "linux/include/linux/sm501-regs.h" */ - -/* System Configuration area */ -/* System config base */ -#define SM501_SYS_CONFIG (0x000000) - -/* config 1 */ -#define SM501_SYSTEM_CONTROL (0x000000) - -#define SM501_SYSCTRL_PANEL_TRISTATE (1<<0) -#define SM501_SYSCTRL_MEM_TRISTATE (1<<1) -#define SM501_SYSCTRL_CRT_TRISTATE (1<<2) - -#define SM501_SYSCTRL_PCI_SLAVE_BURST_MASK (3<<4) -#define SM501_SYSCTRL_PCI_SLAVE_BURST_1 (0<<4) -#define SM501_SYSCTRL_PCI_SLAVE_BURST_2 (1<<4) -#define SM501_SYSCTRL_PCI_SLAVE_BURST_4 (2<<4) -#define SM501_SYSCTRL_PCI_SLAVE_BURST_8 (3<<4) - -#define SM501_SYSCTRL_PCI_CLOCK_RUN_EN (1<<6) -#define SM501_SYSCTRL_PCI_RETRY_DISABLE (1<<7) -#define SM501_SYSCTRL_PCI_SUBSYS_LOCK (1<<11) -#define SM501_SYSCTRL_PCI_BURST_READ_EN (1<<15) - -/* miscellaneous control */ - -#define SM501_MISC_CONTROL (0x000004) - -#define SM501_MISC_BUS_SH (0x0) -#define SM501_MISC_BUS_PCI (0x1) -#define SM501_MISC_BUS_XSCALE (0x2) -#define SM501_MISC_BUS_NEC (0x6) -#define SM501_MISC_BUS_MASK (0x7) - -#define SM501_MISC_VR_62MB (1<<3) -#define SM501_MISC_CDR_RESET (1<<7) -#define SM501_MISC_USB_LB (1<<8) -#define SM501_MISC_USB_SLAVE (1<<9) -#define SM501_MISC_BL_1 (1<<10) -#define SM501_MISC_MC (1<<11) -#define SM501_MISC_DAC_POWER (1<<12) -#define SM501_MISC_IRQ_INVERT (1<<16) -#define SM501_MISC_SH (1<<17) - -#define SM501_MISC_HOLD_EMPTY (0<<18) -#define SM501_MISC_HOLD_8 (1<<18) -#define SM501_MISC_HOLD_16 (2<<18) -#define SM501_MISC_HOLD_24 (3<<18) -#define SM501_MISC_HOLD_32 (4<<18) -#define SM501_MISC_HOLD_MASK (7<<18) - -#define SM501_MISC_FREQ_12 (1<<24) -#define SM501_MISC_PNL_24BIT (1<<25) -#define SM501_MISC_8051_LE (1<<26) - - - -#define SM501_GPIO31_0_CONTROL (0x000008) -#define SM501_GPIO63_32_CONTROL (0x00000C) -#define SM501_DRAM_CONTROL (0x000010) - -/* command list */ -#define SM501_ARBTRTN_CONTROL (0x000014) - -/* command list */ -#define SM501_COMMAND_LIST_STATUS (0x000024) - -/* interrupt debug */ -#define SM501_RAW_IRQ_STATUS (0x000028) -#define SM501_RAW_IRQ_CLEAR (0x000028) -#define SM501_IRQ_STATUS (0x00002C) -#define SM501_IRQ_MASK (0x000030) -#define SM501_DEBUG_CONTROL (0x000034) - -/* power management */ -#define SM501_POWERMODE_P2X_SRC (1<<29) -#define SM501_POWERMODE_V2X_SRC (1<<20) -#define SM501_POWERMODE_M_SRC (1<<12) -#define SM501_POWERMODE_M1_SRC (1<<4) - -#define SM501_CURRENT_GATE (0x000038) -#define SM501_CURRENT_CLOCK (0x00003C) -#define SM501_POWER_MODE_0_GATE (0x000040) -#define SM501_POWER_MODE_0_CLOCK (0x000044) -#define SM501_POWER_MODE_1_GATE (0x000048) -#define SM501_POWER_MODE_1_CLOCK (0x00004C) -#define SM501_SLEEP_MODE_GATE (0x000050) -#define SM501_POWER_MODE_CONTROL (0x000054) - -/* power gates for units within the 501 */ -#define SM501_GATE_HOST (0) -#define SM501_GATE_MEMORY (1) -#define SM501_GATE_DISPLAY (2) -#define SM501_GATE_2D_ENGINE (3) -#define SM501_GATE_CSC (4) -#define SM501_GATE_ZVPORT (5) -#define SM501_GATE_GPIO (6) -#define SM501_GATE_UART0 (7) -#define SM501_GATE_UART1 (8) -#define SM501_GATE_SSP (10) -#define SM501_GATE_USB_HOST (11) -#define SM501_GATE_USB_GADGET (12) -#define SM501_GATE_UCONTROLLER (17) -#define SM501_GATE_AC97 (18) - -/* panel clock */ -#define SM501_CLOCK_P2XCLK (24) -/* crt clock */ -#define SM501_CLOCK_V2XCLK (16) -/* main clock */ -#define SM501_CLOCK_MCLK (8) -/* SDRAM controller clock */ -#define SM501_CLOCK_M1XCLK (0) - -/* config 2 */ -#define SM501_PCI_MASTER_BASE (0x000058) -#define SM501_ENDIAN_CONTROL (0x00005C) -#define SM501_DEVICEID (0x000060) -/* 0x050100A0 */ - -#define SM501_DEVICEID_SM501 (0x05010000) -#define SM501_DEVICEID_IDMASK (0xffff0000) -#define SM501_DEVICEID_REVMASK (0x000000ff) - -#define SM501_PLLCLOCK_COUNT (0x000064) -#define SM501_MISC_TIMING (0x000068) -#define SM501_CURRENT_SDRAM_CLOCK (0x00006C) - -#define SM501_PROGRAMMABLE_PLL_CONTROL (0x000074) - -/* GPIO base */ -#define SM501_GPIO (0x010000) -#define SM501_GPIO_DATA_LOW (0x00) -#define SM501_GPIO_DATA_HIGH (0x04) -#define SM501_GPIO_DDR_LOW (0x08) -#define SM501_GPIO_DDR_HIGH (0x0C) -#define SM501_GPIO_IRQ_SETUP (0x10) -#define SM501_GPIO_IRQ_STATUS (0x14) -#define SM501_GPIO_IRQ_RESET (0x14) - -/* I2C controller base */ -#define SM501_I2C (0x010040) -#define SM501_I2C_BYTE_COUNT (0x00) -#define SM501_I2C_CONTROL (0x01) -#define SM501_I2C_STATUS (0x02) -#define SM501_I2C_RESET (0x02) -#define SM501_I2C_SLAVE_ADDRESS (0x03) -#define SM501_I2C_DATA (0x04) - -/* SSP base */ -#define SM501_SSP (0x020000) - -/* Uart 0 base */ -#define SM501_UART0 (0x030000) - -/* Uart 1 base */ -#define SM501_UART1 (0x030020) - -/* USB host port base */ -#define SM501_USB_HOST (0x040000) - -/* USB slave/gadget base */ -#define SM501_USB_GADGET (0x060000) - -/* USB slave/gadget data port base */ -#define SM501_USB_GADGET_DATA (0x070000) - -/* Display controller/video engine base */ -#define SM501_DC (0x080000) - -/* common defines for the SM501 address registers */ -#define SM501_ADDR_FLIP (1<<31) -#define SM501_ADDR_EXT (1<<27) -#define SM501_ADDR_CS1 (1<<26) -#define SM501_ADDR_MASK (0x3f << 26) - -#define SM501_FIFO_MASK (0x3 << 16) -#define SM501_FIFO_1 (0x0 << 16) -#define SM501_FIFO_3 (0x1 << 16) -#define SM501_FIFO_7 (0x2 << 16) -#define SM501_FIFO_11 (0x3 << 16) - -/* common registers for panel and the crt */ -#define SM501_OFF_DC_H_TOT (0x000) -#define SM501_OFF_DC_V_TOT (0x008) -#define SM501_OFF_DC_H_SYNC (0x004) -#define SM501_OFF_DC_V_SYNC (0x00C) - -#define SM501_DC_PANEL_CONTROL (0x000) - -#define SM501_DC_PANEL_CONTROL_FPEN (1<<27) -#define SM501_DC_PANEL_CONTROL_BIAS (1<<26) -#define SM501_DC_PANEL_CONTROL_DATA (1<<25) -#define SM501_DC_PANEL_CONTROL_VDD (1<<24) -#define SM501_DC_PANEL_CONTROL_DP (1<<23) - -#define SM501_DC_PANEL_CONTROL_TFT_888 (0<<21) -#define SM501_DC_PANEL_CONTROL_TFT_333 (1<<21) -#define SM501_DC_PANEL_CONTROL_TFT_444 (2<<21) - -#define SM501_DC_PANEL_CONTROL_DE (1<<20) - -#define SM501_DC_PANEL_CONTROL_LCD_TFT (0<<18) -#define SM501_DC_PANEL_CONTROL_LCD_STN8 (1<<18) -#define SM501_DC_PANEL_CONTROL_LCD_STN12 (2<<18) - -#define SM501_DC_PANEL_CONTROL_CP (1<<14) -#define SM501_DC_PANEL_CONTROL_VSP (1<<13) -#define SM501_DC_PANEL_CONTROL_HSP (1<<12) -#define SM501_DC_PANEL_CONTROL_CK (1<<9) -#define SM501_DC_PANEL_CONTROL_TE (1<<8) -#define SM501_DC_PANEL_CONTROL_VPD (1<<7) -#define SM501_DC_PANEL_CONTROL_VP (1<<6) -#define SM501_DC_PANEL_CONTROL_HPD (1<<5) -#define SM501_DC_PANEL_CONTROL_HP (1<<4) -#define SM501_DC_PANEL_CONTROL_GAMMA (1<<3) -#define SM501_DC_PANEL_CONTROL_EN (1<<2) - -#define SM501_DC_PANEL_CONTROL_8BPP (0<<0) -#define SM501_DC_PANEL_CONTROL_16BPP (1<<0) -#define SM501_DC_PANEL_CONTROL_32BPP (2<<0) - - -#define SM501_DC_PANEL_PANNING_CONTROL (0x004) -#define SM501_DC_PANEL_COLOR_KEY (0x008) -#define SM501_DC_PANEL_FB_ADDR (0x00C) -#define SM501_DC_PANEL_FB_OFFSET (0x010) -#define SM501_DC_PANEL_FB_WIDTH (0x014) -#define SM501_DC_PANEL_FB_HEIGHT (0x018) -#define SM501_DC_PANEL_TL_LOC (0x01C) -#define SM501_DC_PANEL_BR_LOC (0x020) -#define SM501_DC_PANEL_H_TOT (0x024) -#define SM501_DC_PANEL_H_SYNC (0x028) -#define SM501_DC_PANEL_V_TOT (0x02C) -#define SM501_DC_PANEL_V_SYNC (0x030) -#define SM501_DC_PANEL_CUR_LINE (0x034) - -#define SM501_DC_VIDEO_CONTROL (0x040) -#define SM501_DC_VIDEO_FB0_ADDR (0x044) -#define SM501_DC_VIDEO_FB_WIDTH (0x048) -#define SM501_DC_VIDEO_FB0_LAST_ADDR (0x04C) -#define SM501_DC_VIDEO_TL_LOC (0x050) -#define SM501_DC_VIDEO_BR_LOC (0x054) -#define SM501_DC_VIDEO_SCALE (0x058) -#define SM501_DC_VIDEO_INIT_SCALE (0x05C) -#define SM501_DC_VIDEO_YUV_CONSTANTS (0x060) -#define SM501_DC_VIDEO_FB1_ADDR (0x064) -#define SM501_DC_VIDEO_FB1_LAST_ADDR (0x068) - -#define SM501_DC_VIDEO_ALPHA_CONTROL (0x080) -#define SM501_DC_VIDEO_ALPHA_FB_ADDR (0x084) -#define SM501_DC_VIDEO_ALPHA_FB_OFFSET (0x088) -#define SM501_DC_VIDEO_ALPHA_FB_LAST_ADDR (0x08C) -#define SM501_DC_VIDEO_ALPHA_TL_LOC (0x090) -#define SM501_DC_VIDEO_ALPHA_BR_LOC (0x094) -#define SM501_DC_VIDEO_ALPHA_SCALE (0x098) -#define SM501_DC_VIDEO_ALPHA_INIT_SCALE (0x09C) -#define SM501_DC_VIDEO_ALPHA_CHROMA_KEY (0x0A0) -#define SM501_DC_VIDEO_ALPHA_COLOR_LOOKUP (0x0A4) - -#define SM501_DC_PANEL_HWC_BASE (0x0F0) -#define SM501_DC_PANEL_HWC_ADDR (0x0F0) -#define SM501_DC_PANEL_HWC_LOC (0x0F4) -#define SM501_DC_PANEL_HWC_COLOR_1_2 (0x0F8) -#define SM501_DC_PANEL_HWC_COLOR_3 (0x0FC) - -#define SM501_HWC_EN (1<<31) - -#define SM501_OFF_HWC_ADDR (0x00) -#define SM501_OFF_HWC_LOC (0x04) -#define SM501_OFF_HWC_COLOR_1_2 (0x08) -#define SM501_OFF_HWC_COLOR_3 (0x0C) - -#define SM501_DC_ALPHA_CONTROL (0x100) -#define SM501_DC_ALPHA_FB_ADDR (0x104) -#define SM501_DC_ALPHA_FB_OFFSET (0x108) -#define SM501_DC_ALPHA_TL_LOC (0x10C) -#define SM501_DC_ALPHA_BR_LOC (0x110) -#define SM501_DC_ALPHA_CHROMA_KEY (0x114) -#define SM501_DC_ALPHA_COLOR_LOOKUP (0x118) - -#define SM501_DC_CRT_CONTROL (0x200) - -#define SM501_DC_CRT_CONTROL_TVP (1<<15) -#define SM501_DC_CRT_CONTROL_CP (1<<14) -#define SM501_DC_CRT_CONTROL_VSP (1<<13) -#define SM501_DC_CRT_CONTROL_HSP (1<<12) -#define SM501_DC_CRT_CONTROL_VS (1<<11) -#define SM501_DC_CRT_CONTROL_BLANK (1<<10) -#define SM501_DC_CRT_CONTROL_SEL (1<<9) -#define SM501_DC_CRT_CONTROL_TE (1<<8) -#define SM501_DC_CRT_CONTROL_PIXEL_MASK (0xF << 4) -#define SM501_DC_CRT_CONTROL_GAMMA (1<<3) -#define SM501_DC_CRT_CONTROL_ENABLE (1<<2) - -#define SM501_DC_CRT_CONTROL_8BPP (0<<0) -#define SM501_DC_CRT_CONTROL_16BPP (1<<0) -#define SM501_DC_CRT_CONTROL_32BPP (2<<0) - -#define SM501_DC_CRT_FB_ADDR (0x204) -#define SM501_DC_CRT_FB_OFFSET (0x208) -#define SM501_DC_CRT_H_TOT (0x20C) -#define SM501_DC_CRT_H_SYNC (0x210) -#define SM501_DC_CRT_V_TOT (0x214) -#define SM501_DC_CRT_V_SYNC (0x218) -#define SM501_DC_CRT_SIGNATURE_ANALYZER (0x21C) -#define SM501_DC_CRT_CUR_LINE (0x220) -#define SM501_DC_CRT_MONITOR_DETECT (0x224) - -#define SM501_DC_CRT_HWC_BASE (0x230) -#define SM501_DC_CRT_HWC_ADDR (0x230) -#define SM501_DC_CRT_HWC_LOC (0x234) -#define SM501_DC_CRT_HWC_COLOR_1_2 (0x238) -#define SM501_DC_CRT_HWC_COLOR_3 (0x23C) - -#define SM501_DC_PANEL_PALETTE (0x400) - -#define SM501_DC_VIDEO_PALETTE (0x800) - -#define SM501_DC_CRT_PALETTE (0xC00) - -/* Zoom Video port base */ -#define SM501_ZVPORT (0x090000) - -/* AC97/I2S base */ -#define SM501_AC97 (0x0A0000) - -/* 8051 micro controller base */ -#define SM501_UCONTROLLER (0x0B0000) - -/* 8051 micro controller SRAM base */ -#define SM501_UCONTROLLER_SRAM (0x0C0000) - -/* DMA base */ -#define SM501_DMA (0x0D0000) - -/* 2d engine base */ -#define SM501_2D_ENGINE (0x100000) -#define SM501_2D_SOURCE (0x00) -#define SM501_2D_DESTINATION (0x04) -#define SM501_2D_DIMENSION (0x08) -#define SM501_2D_CONTROL (0x0C) -#define SM501_2D_PITCH (0x10) -#define SM501_2D_FOREGROUND (0x14) -#define SM501_2D_BACKGROUND (0x18) -#define SM501_2D_STRETCH (0x1C) -#define SM501_2D_COLOR_COMPARE (0x20) -#define SM501_2D_COLOR_COMPARE_MASK (0x24) -#define SM501_2D_MASK (0x28) -#define SM501_2D_CLIP_TL (0x2C) -#define SM501_2D_CLIP_BR (0x30) -#define SM501_2D_MONO_PATTERN_LOW (0x34) -#define SM501_2D_MONO_PATTERN_HIGH (0x38) -#define SM501_2D_WINDOW_WIDTH (0x3C) -#define SM501_2D_SOURCE_BASE (0x40) -#define SM501_2D_DESTINATION_BASE (0x44) -#define SM501_2D_ALPHA (0x48) -#define SM501_2D_WRAP (0x4C) -#define SM501_2D_STATUS (0x50) - -#define SM501_CSC_Y_SOURCE_BASE (0xC8) -#define SM501_CSC_CONSTANTS (0xCC) -#define SM501_CSC_Y_SOURCE_X (0xD0) -#define SM501_CSC_Y_SOURCE_Y (0xD4) -#define SM501_CSC_U_SOURCE_BASE (0xD8) -#define SM501_CSC_V_SOURCE_BASE (0xDC) -#define SM501_CSC_SOURCE_DIMENSION (0xE0) -#define SM501_CSC_SOURCE_PITCH (0xE4) -#define SM501_CSC_DESTINATION (0xE8) -#define SM501_CSC_DESTINATION_DIMENSION (0xEC) -#define SM501_CSC_DESTINATION_PITCH (0xF0) -#define SM501_CSC_SCALE_FACTOR (0xF4) -#define SM501_CSC_DESTINATION_BASE (0xF8) -#define SM501_CSC_CONTROL (0xFC) - -/* 2d engine data port base */ -#define SM501_2D_ENGINE_DATA (0x110000) - -/* end of register definitions */ - -#define SM501_HWC_WIDTH (64) -#define SM501_HWC_HEIGHT (64) - -/* SM501 local memory size taken from "linux/drivers/mfd/sm501.c" */ -static const uint32_t sm501_mem_local_size[] = { - [0] = 4*1024*1024, - [1] = 8*1024*1024, - [2] = 16*1024*1024, - [3] = 32*1024*1024, - [4] = 64*1024*1024, - [5] = 2*1024*1024, -}; -#define get_local_mem_size(s) sm501_mem_local_size[(s)->local_mem_size_index] - -typedef struct SM501State { - /* graphic console status */ - QemuConsole *con; - - /* status & internal resources */ - hwaddr base; - uint32_t local_mem_size_index; - uint8_t * local_mem; - MemoryRegion local_mem_region; - uint32_t last_width; - uint32_t last_height; - - /* mmio registers */ - uint32_t system_control; - uint32_t misc_control; - uint32_t gpio_31_0_control; - uint32_t gpio_63_32_control; - uint32_t dram_control; - uint32_t irq_mask; - uint32_t misc_timing; - uint32_t power_mode_control; - - uint32_t uart0_ier; - uint32_t uart0_lcr; - uint32_t uart0_mcr; - uint32_t uart0_scr; - - uint8_t dc_palette[0x400 * 3]; - - uint32_t dc_panel_control; - uint32_t dc_panel_panning_control; - uint32_t dc_panel_fb_addr; - uint32_t dc_panel_fb_offset; - uint32_t dc_panel_fb_width; - uint32_t dc_panel_fb_height; - uint32_t dc_panel_tl_location; - uint32_t dc_panel_br_location; - uint32_t dc_panel_h_total; - uint32_t dc_panel_h_sync; - uint32_t dc_panel_v_total; - uint32_t dc_panel_v_sync; - - uint32_t dc_panel_hwc_addr; - uint32_t dc_panel_hwc_location; - uint32_t dc_panel_hwc_color_1_2; - uint32_t dc_panel_hwc_color_3; - - uint32_t dc_crt_control; - uint32_t dc_crt_fb_addr; - uint32_t dc_crt_fb_offset; - uint32_t dc_crt_h_total; - uint32_t dc_crt_h_sync; - uint32_t dc_crt_v_total; - uint32_t dc_crt_v_sync; - - uint32_t dc_crt_hwc_addr; - uint32_t dc_crt_hwc_location; - uint32_t dc_crt_hwc_color_1_2; - uint32_t dc_crt_hwc_color_3; - - uint32_t twoD_source; - uint32_t twoD_destination; - uint32_t twoD_dimension; - uint32_t twoD_control; - uint32_t twoD_pitch; - uint32_t twoD_foreground; - uint32_t twoD_stretch; - uint32_t twoD_color_compare_mask; - uint32_t twoD_mask; - uint32_t twoD_window_width; - uint32_t twoD_source_base; - uint32_t twoD_destination_base; - -} SM501State; - -static uint32_t get_local_mem_size_index(uint32_t size) -{ - uint32_t norm_size = 0; - int i, index = 0; - - for (i = 0; i < ARRAY_SIZE(sm501_mem_local_size); i++) { - uint32_t new_size = sm501_mem_local_size[i]; - if (new_size >= size) { - if (norm_size == 0 || norm_size > new_size) { - norm_size = new_size; - index = i; - } - } - } - - return index; -} - -/** - * Check the availability of hardware cursor. - * @param crt 0 for PANEL, 1 for CRT. - */ -static inline int is_hwc_enabled(SM501State *state, int crt) -{ - uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr; - return addr & 0x80000000; -} - -/** - * Get the address which holds cursor pattern data. - * @param crt 0 for PANEL, 1 for CRT. - */ -static inline uint32_t get_hwc_address(SM501State *state, int crt) -{ - uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr; - return (addr & 0x03FFFFF0)/* >> 4*/; -} - -/** - * Get the cursor position in y coordinate. - * @param crt 0 for PANEL, 1 for CRT. - */ -static inline uint32_t get_hwc_y(SM501State *state, int crt) -{ - uint32_t location = crt ? state->dc_crt_hwc_location - : state->dc_panel_hwc_location; - return (location & 0x07FF0000) >> 16; -} - -/** - * Get the cursor position in x coordinate. - * @param crt 0 for PANEL, 1 for CRT. - */ -static inline uint32_t get_hwc_x(SM501State *state, int crt) -{ - uint32_t location = crt ? state->dc_crt_hwc_location - : state->dc_panel_hwc_location; - return location & 0x000007FF; -} - -/** - * Get the cursor position in x coordinate. - * @param crt 0 for PANEL, 1 for CRT. - * @param index 0, 1, 2 or 3 which specifies color of corsor dot. - */ -static inline uint16_t get_hwc_color(SM501State *state, int crt, int index) -{ - uint32_t color_reg = 0; - uint16_t color_565 = 0; - - if (index == 0) { - return 0; - } - - switch (index) { - case 1: - case 2: - color_reg = crt ? state->dc_crt_hwc_color_1_2 - : state->dc_panel_hwc_color_1_2; - break; - case 3: - color_reg = crt ? state->dc_crt_hwc_color_3 - : state->dc_panel_hwc_color_3; - break; - default: - printf("invalid hw cursor color.\n"); - abort(); - } - - switch (index) { - case 1: - case 3: - color_565 = (uint16_t)(color_reg & 0xFFFF); - break; - case 2: - color_565 = (uint16_t)((color_reg >> 16) & 0xFFFF); - break; - } - return color_565; -} - -static int within_hwc_y_range(SM501State *state, int y, int crt) -{ - int hwc_y = get_hwc_y(state, crt); - return (hwc_y <= y && y < hwc_y + SM501_HWC_HEIGHT); -} - -static void sm501_2d_operation(SM501State * s) -{ - /* obtain operation parameters */ - int operation = (s->twoD_control >> 16) & 0x1f; - int rtl = s->twoD_control & 0x8000000; - int src_x = (s->twoD_source >> 16) & 0x01FFF; - int src_y = s->twoD_source & 0xFFFF; - int dst_x = (s->twoD_destination >> 16) & 0x01FFF; - int dst_y = s->twoD_destination & 0xFFFF; - int operation_width = (s->twoD_dimension >> 16) & 0x1FFF; - int operation_height = s->twoD_dimension & 0xFFFF; - uint32_t color = s->twoD_foreground; - int format_flags = (s->twoD_stretch >> 20) & 0x3; - int addressing = (s->twoD_stretch >> 16) & 0xF; - - /* 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; - - if (addressing != 0x0) { - printf("%s: only XY addressing is supported.\n", __func__); - abort(); - } - - if ((s->twoD_source_base & 0x08000000) || - (s->twoD_destination_base & 0x08000000)) { - printf("%s: only local memory is supported.\n", __func__); - abort(); - } - - switch (operation) { - case 0x00: /* copy area */ -#define COPY_AREA(_bpp, _pixel_type, rtl) { \ - int y, x, index_d, index_s; \ - for (y = 0; y < operation_height; y++) { \ - for (x = 0; x < operation_width; x++) { \ - if (rtl) { \ - index_s = ((src_y - y) * src_width + src_x - x) * _bpp; \ - index_d = ((dst_y - y) * dst_width + dst_x - x) * _bpp; \ - } else { \ - 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];\ - } \ - } \ - } - switch (format_flags) { - case 0: - COPY_AREA(1, uint8_t, rtl); - break; - case 1: - COPY_AREA(2, uint16_t, rtl); - break; - case 2: - COPY_AREA(4, uint32_t, rtl); - break; - } - break; - - case 0x01: /* fill rectangle */ -#define FILL_RECT(_bpp, _pixel_type) { \ - int y, x; \ - for (y = 0; y < operation_height; y++) { \ - for (x = 0; x < operation_width; x++) { \ - int index = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \ - *(_pixel_type*)&dst[index] = (_pixel_type)color; \ - } \ - } \ - } - - switch (format_flags) { - case 0: - FILL_RECT(1, uint8_t); - break; - case 1: - FILL_RECT(2, uint16_t); - break; - case 2: - FILL_RECT(4, uint32_t); - break; - } - break; - - default: - printf("non-implemented SM501 2D operation. %d\n", operation); - abort(); - break; - } -} - -static uint64_t sm501_system_config_read(void *opaque, hwaddr addr, - unsigned size) -{ - SM501State * s = (SM501State *)opaque; - uint32_t ret = 0; - SM501_DPRINTF("sm501 system config regs : read addr=%x\n", (int)addr); - - switch(addr) { - case SM501_SYSTEM_CONTROL: - ret = s->system_control; - break; - case SM501_MISC_CONTROL: - ret = s->misc_control; - break; - case SM501_GPIO31_0_CONTROL: - ret = s->gpio_31_0_control; - break; - case SM501_GPIO63_32_CONTROL: - ret = s->gpio_63_32_control; - break; - case SM501_DEVICEID: - ret = 0x050100A0; - break; - case SM501_DRAM_CONTROL: - ret = (s->dram_control & 0x07F107C0) | s->local_mem_size_index << 13; - break; - case SM501_IRQ_MASK: - ret = s->irq_mask; - break; - case SM501_MISC_TIMING: - /* TODO : simulate gate control */ - ret = s->misc_timing; - break; - case SM501_CURRENT_GATE: - /* TODO : simulate gate control */ - ret = 0x00021807; - break; - case SM501_CURRENT_CLOCK: - ret = 0x2A1A0A09; - break; - case SM501_POWER_MODE_CONTROL: - ret = s->power_mode_control; - break; - - default: - printf("sm501 system config : not implemented register read." - " addr=%x\n", (int)addr); - abort(); - } - - return ret; -} - -static void sm501_system_config_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - SM501State * s = (SM501State *)opaque; - SM501_DPRINTF("sm501 system config regs : write addr=%x, val=%x\n", - (uint32_t)addr, (uint32_t)value); - - switch(addr) { - case SM501_SYSTEM_CONTROL: - s->system_control = value & 0xE300B8F7; - break; - case SM501_MISC_CONTROL: - s->misc_control = value & 0xFF7FFF20; - break; - case SM501_GPIO31_0_CONTROL: - s->gpio_31_0_control = value; - break; - case SM501_GPIO63_32_CONTROL: - s->gpio_63_32_control = value; - break; - case SM501_DRAM_CONTROL: - s->local_mem_size_index = (value >> 13) & 0x7; - /* rODO : check validity of size change */ - s->dram_control |= value & 0x7FFFFFC3; - break; - case SM501_IRQ_MASK: - s->irq_mask = value; - break; - case SM501_MISC_TIMING: - s->misc_timing = value & 0xF31F1FFF; - break; - case SM501_POWER_MODE_0_GATE: - case SM501_POWER_MODE_1_GATE: - case SM501_POWER_MODE_0_CLOCK: - case SM501_POWER_MODE_1_CLOCK: - /* TODO : simulate gate & clock control */ - break; - case SM501_POWER_MODE_CONTROL: - s->power_mode_control = value & 0x00000003; - break; - - default: - printf("sm501 system config : not implemented register write." - " addr=%x, val=%x\n", (int)addr, (uint32_t)value); - abort(); - } -} - -static const MemoryRegionOps sm501_system_config_ops = { - .read = sm501_system_config_read, - .write = sm501_system_config_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static uint32_t sm501_palette_read(void *opaque, hwaddr addr) -{ - SM501State * s = (SM501State *)opaque; - SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr); - - /* TODO : consider BYTE/WORD access */ - /* TODO : consider endian */ - - assert(range_covers_byte(0, 0x400 * 3, addr)); - return *(uint32_t*)&s->dc_palette[addr]; -} - -static void sm501_palette_write(void *opaque, - hwaddr addr, uint32_t value) -{ - SM501State * s = (SM501State *)opaque; - SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n", - (int)addr, value); - - /* TODO : consider BYTE/WORD access */ - /* TODO : consider endian */ - - assert(range_covers_byte(0, 0x400 * 3, addr)); - *(uint32_t*)&s->dc_palette[addr] = value; -} - -static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr, - unsigned size) -{ - SM501State * s = (SM501State *)opaque; - uint32_t ret = 0; - SM501_DPRINTF("sm501 disp ctrl regs : read addr=%x\n", (int)addr); - - switch(addr) { - - case SM501_DC_PANEL_CONTROL: - ret = s->dc_panel_control; - break; - case SM501_DC_PANEL_PANNING_CONTROL: - ret = s->dc_panel_panning_control; - break; - case SM501_DC_PANEL_FB_ADDR: - ret = s->dc_panel_fb_addr; - break; - case SM501_DC_PANEL_FB_OFFSET: - ret = s->dc_panel_fb_offset; - break; - case SM501_DC_PANEL_FB_WIDTH: - ret = s->dc_panel_fb_width; - break; - case SM501_DC_PANEL_FB_HEIGHT: - ret = s->dc_panel_fb_height; - break; - case SM501_DC_PANEL_TL_LOC: - ret = s->dc_panel_tl_location; - break; - case SM501_DC_PANEL_BR_LOC: - ret = s->dc_panel_br_location; - break; - - case SM501_DC_PANEL_H_TOT: - ret = s->dc_panel_h_total; - break; - case SM501_DC_PANEL_H_SYNC: - ret = s->dc_panel_h_sync; - break; - case SM501_DC_PANEL_V_TOT: - ret = s->dc_panel_v_total; - break; - case SM501_DC_PANEL_V_SYNC: - ret = s->dc_panel_v_sync; - break; - - case SM501_DC_CRT_CONTROL: - ret = s->dc_crt_control; - break; - case SM501_DC_CRT_FB_ADDR: - ret = s->dc_crt_fb_addr; - break; - case SM501_DC_CRT_FB_OFFSET: - ret = s->dc_crt_fb_offset; - break; - case SM501_DC_CRT_H_TOT: - ret = s->dc_crt_h_total; - break; - case SM501_DC_CRT_H_SYNC: - ret = s->dc_crt_h_sync; - break; - case SM501_DC_CRT_V_TOT: - ret = s->dc_crt_v_total; - break; - case SM501_DC_CRT_V_SYNC: - ret = s->dc_crt_v_sync; - break; - - case SM501_DC_CRT_HWC_ADDR: - ret = s->dc_crt_hwc_addr; - break; - case SM501_DC_CRT_HWC_LOC: - ret = s->dc_crt_hwc_location; - break; - case SM501_DC_CRT_HWC_COLOR_1_2: - ret = s->dc_crt_hwc_color_1_2; - break; - case SM501_DC_CRT_HWC_COLOR_3: - ret = s->dc_crt_hwc_color_3; - break; - - case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4: - ret = sm501_palette_read(opaque, addr - SM501_DC_PANEL_PALETTE); - break; - - default: - printf("sm501 disp ctrl : not implemented register read." - " addr=%x\n", (int)addr); - abort(); - } - - return ret; -} - -static void sm501_disp_ctrl_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - SM501State * s = (SM501State *)opaque; - SM501_DPRINTF("sm501 disp ctrl regs : write addr=%x, val=%x\n", - (unsigned)addr, (unsigned)value); - - switch(addr) { - case SM501_DC_PANEL_CONTROL: - s->dc_panel_control = value & 0x0FFF73FF; - break; - case SM501_DC_PANEL_PANNING_CONTROL: - s->dc_panel_panning_control = value & 0xFF3FFF3F; - break; - case SM501_DC_PANEL_FB_ADDR: - s->dc_panel_fb_addr = value & 0x8FFFFFF0; - break; - case SM501_DC_PANEL_FB_OFFSET: - s->dc_panel_fb_offset = value & 0x3FF03FF0; - break; - case SM501_DC_PANEL_FB_WIDTH: - s->dc_panel_fb_width = value & 0x0FFF0FFF; - break; - case SM501_DC_PANEL_FB_HEIGHT: - s->dc_panel_fb_height = value & 0x0FFF0FFF; - break; - case SM501_DC_PANEL_TL_LOC: - s->dc_panel_tl_location = value & 0x07FF07FF; - break; - case SM501_DC_PANEL_BR_LOC: - s->dc_panel_br_location = value & 0x07FF07FF; - break; - - case SM501_DC_PANEL_H_TOT: - s->dc_panel_h_total = value & 0x0FFF0FFF; - break; - case SM501_DC_PANEL_H_SYNC: - s->dc_panel_h_sync = value & 0x00FF0FFF; - break; - case SM501_DC_PANEL_V_TOT: - s->dc_panel_v_total = value & 0x0FFF0FFF; - break; - case SM501_DC_PANEL_V_SYNC: - s->dc_panel_v_sync = value & 0x003F0FFF; - break; - - case SM501_DC_PANEL_HWC_ADDR: - s->dc_panel_hwc_addr = value & 0x8FFFFFF0; - break; - case SM501_DC_PANEL_HWC_LOC: - s->dc_panel_hwc_location = value & 0x0FFF0FFF; - break; - case SM501_DC_PANEL_HWC_COLOR_1_2: - s->dc_panel_hwc_color_1_2 = value; - break; - case SM501_DC_PANEL_HWC_COLOR_3: - s->dc_panel_hwc_color_3 = value & 0x0000FFFF; - break; - - case SM501_DC_CRT_CONTROL: - s->dc_crt_control = value & 0x0003FFFF; - break; - case SM501_DC_CRT_FB_ADDR: - s->dc_crt_fb_addr = value & 0x8FFFFFF0; - break; - case SM501_DC_CRT_FB_OFFSET: - s->dc_crt_fb_offset = value & 0x3FF03FF0; - break; - case SM501_DC_CRT_H_TOT: - s->dc_crt_h_total = value & 0x0FFF0FFF; - break; - case SM501_DC_CRT_H_SYNC: - s->dc_crt_h_sync = value & 0x00FF0FFF; - break; - case SM501_DC_CRT_V_TOT: - s->dc_crt_v_total = value & 0x0FFF0FFF; - break; - case SM501_DC_CRT_V_SYNC: - s->dc_crt_v_sync = value & 0x003F0FFF; - break; - - case SM501_DC_CRT_HWC_ADDR: - s->dc_crt_hwc_addr = value & 0x8FFFFFF0; - break; - case SM501_DC_CRT_HWC_LOC: - s->dc_crt_hwc_location = value & 0x0FFF0FFF; - break; - case SM501_DC_CRT_HWC_COLOR_1_2: - s->dc_crt_hwc_color_1_2 = value; - break; - case SM501_DC_CRT_HWC_COLOR_3: - s->dc_crt_hwc_color_3 = value & 0x0000FFFF; - break; - - case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4: - sm501_palette_write(opaque, addr - SM501_DC_PANEL_PALETTE, value); - break; - - default: - printf("sm501 disp ctrl : not implemented register write." - " addr=%x, val=%x\n", (int)addr, (unsigned)value); - abort(); - } -} - -static const MemoryRegionOps sm501_disp_ctrl_ops = { - .read = sm501_disp_ctrl_read, - .write = sm501_disp_ctrl_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr, - unsigned size) -{ - SM501State * s = (SM501State *)opaque; - uint32_t ret = 0; - SM501_DPRINTF("sm501 2d engine regs : read addr=%x\n", (int)addr); - - switch(addr) { - case SM501_2D_SOURCE_BASE: - ret = s->twoD_source_base; - break; - default: - printf("sm501 disp ctrl : not implemented register read." - " addr=%x\n", (int)addr); - abort(); - } - - return ret; -} - -static void sm501_2d_engine_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - SM501State * s = (SM501State *)opaque; - SM501_DPRINTF("sm501 2d engine regs : write addr=%x, val=%x\n", - (unsigned)addr, (unsigned)value); - - switch(addr) { - case SM501_2D_SOURCE: - s->twoD_source = value; - break; - case SM501_2D_DESTINATION: - s->twoD_destination = value; - break; - case SM501_2D_DIMENSION: - s->twoD_dimension = value; - break; - case SM501_2D_CONTROL: - s->twoD_control = value; - - /* do 2d operation if start flag is set. */ - if (value & 0x80000000) { - sm501_2d_operation(s); - s->twoD_control &= ~0x80000000; /* start flag down */ - } - - break; - case SM501_2D_PITCH: - s->twoD_pitch = value; - break; - case SM501_2D_FOREGROUND: - s->twoD_foreground = value; - break; - case SM501_2D_STRETCH: - s->twoD_stretch = value; - break; - case SM501_2D_COLOR_COMPARE_MASK: - s->twoD_color_compare_mask = value; - break; - case SM501_2D_MASK: - s->twoD_mask = value; - break; - case SM501_2D_WINDOW_WIDTH: - s->twoD_window_width = value; - break; - case SM501_2D_SOURCE_BASE: - s->twoD_source_base = value; - break; - case SM501_2D_DESTINATION_BASE: - s->twoD_destination_base = value; - break; - default: - printf("sm501 2d engine : not implemented register write." - " addr=%x, val=%x\n", (int)addr, (unsigned)value); - abort(); - } -} - -static const MemoryRegionOps sm501_2d_engine_ops = { - .read = sm501_2d_engine_read, - .write = sm501_2d_engine_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -/* draw line functions for all console modes */ - -typedef void draw_line_func(uint8_t *d, const uint8_t *s, - int width, const uint32_t *pal); - -typedef void draw_hwc_line_func(SM501State * s, int crt, uint8_t * palette, - int c_y, uint8_t *d, int width); - -#define DEPTH 8 -#include "sm501_template.h" - -#define DEPTH 15 -#include "sm501_template.h" - -#define BGR_FORMAT -#define DEPTH 15 -#include "sm501_template.h" - -#define DEPTH 16 -#include "sm501_template.h" - -#define BGR_FORMAT -#define DEPTH 16 -#include "sm501_template.h" - -#define DEPTH 32 -#include "sm501_template.h" - -#define BGR_FORMAT -#define DEPTH 32 -#include "sm501_template.h" - -static draw_line_func * draw_line8_funcs[] = { - draw_line8_8, - draw_line8_15, - draw_line8_16, - draw_line8_32, - draw_line8_32bgr, - draw_line8_15bgr, - draw_line8_16bgr, -}; - -static draw_line_func * draw_line16_funcs[] = { - draw_line16_8, - draw_line16_15, - draw_line16_16, - draw_line16_32, - draw_line16_32bgr, - draw_line16_15bgr, - draw_line16_16bgr, -}; - -static draw_line_func * draw_line32_funcs[] = { - draw_line32_8, - draw_line32_15, - draw_line32_16, - draw_line32_32, - draw_line32_32bgr, - draw_line32_15bgr, - draw_line32_16bgr, -}; - -static draw_hwc_line_func * draw_hwc_line_funcs[] = { - draw_hwc_line_8, - draw_hwc_line_15, - draw_hwc_line_16, - draw_hwc_line_32, - draw_hwc_line_32bgr, - draw_hwc_line_15bgr, - draw_hwc_line_16bgr, -}; - -static inline int get_depth_index(DisplaySurface *surface) -{ - switch (surface_bits_per_pixel(surface)) { - default: - case 8: - return 0; - case 15: - return 1; - case 16: - return 2; - case 32: - 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 = 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(surface); - draw_line_func * draw_line = NULL; - draw_hwc_line_func * draw_hwc_line = NULL; - int full_update = 0; - int y_start = -1; - ram_addr_t page_min = ~0l; - ram_addr_t page_max = 0l; - ram_addr_t offset = 0; - - /* choose draw_line function */ - switch (s->dc_crt_control & 3) { - case SM501_DC_CRT_CONTROL_8BPP: - src_bpp = 1; - draw_line = draw_line8_funcs[ds_depth_index]; - break; - case SM501_DC_CRT_CONTROL_16BPP: - src_bpp = 2; - draw_line = draw_line16_funcs[ds_depth_index]; - break; - case SM501_DC_CRT_CONTROL_32BPP: - src_bpp = 4; - draw_line = draw_line32_funcs[ds_depth_index]; - break; - default: - printf("sm501 draw crt : invalid DC_CRT_CONTROL=%x.\n", - s->dc_crt_control); - abort(); - break; - } - - /* set up to draw hardware cursor */ - if (is_hwc_enabled(s, 1)) { - int i; - - /* get cursor palette */ - for (i = 0; i < 3; i++) { - uint16_t rgb565 = get_hwc_color(s, 1, i + 1); - hwc_palette[i * 3 + 0] = (rgb565 & 0xf800) >> 8; /* red */ - hwc_palette[i * 3 + 1] = (rgb565 & 0x07e0) >> 3; /* green */ - hwc_palette[i * 3 + 2] = (rgb565 & 0x001f) << 3; /* blue */ - } - - /* choose cursor draw line function */ - draw_hwc_line = draw_hwc_line_funcs[ds_depth_index]; - } - - /* adjust console size */ - if (s->last_width != width || s->last_height != 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; - } - - /* draw each line according to conditions */ - memory_region_sync_dirty_bitmap(&s->local_mem_region); - for (y = 0; y < height; y++) { - int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0; - int update = full_update || update_hwc; - ram_addr_t page0 = offset; - ram_addr_t page1 = offset + width * src_bpp - 1; - - /* check dirty flags for each line */ - update = memory_region_get_dirty(&s->local_mem_region, page0, - page1 - page0, DIRTY_MEMORY_VGA); - - /* draw line and change status */ - if (update) { - uint8_t *d = surface_data(surface); - d += y * width * dst_bpp; - - /* draw graphics layer */ - draw_line(d, src, width, palette); - - /* draw haredware cursor */ - if (update_hwc) { - draw_hwc_line(s, 1, hwc_palette, y - get_hwc_y(s, 1), d, width); - } - - if (y_start < 0) - y_start = y; - if (page0 < page_min) - page_min = page0; - if (page1 > page_max) - page_max = page1; - } else { - if (y_start >= 0) { - /* flush to display */ - dpy_gfx_update(s->con, 0, y_start, width, y - y_start); - y_start = -1; - } - } - - src += width * src_bpp; - offset += width * src_bpp; - } - - /* complete flush to display */ - if (y_start >= 0) - dpy_gfx_update(s->con, 0, y_start, width, y - y_start); - - /* clear dirty flags */ - if (page_min != ~0l) { - memory_region_reset_dirty(&s->local_mem_region, - page_min, page_max + TARGET_PAGE_SIZE, - DIRTY_MEMORY_VGA); - } -} - -static void sm501_update_display(void *opaque) -{ - SM501State * s = (SM501State *)opaque; - - if (s->dc_crt_control & SM501_DC_CRT_CONTROL_ENABLE) - sm501_draw_crt(s); -} - -static const GraphicHwOps sm501_ops = { - .gfx_update = sm501_update_display, -}; - -void sm501_init(MemoryRegion *address_space_mem, uint32_t base, - uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr) -{ - SM501State * s; - DeviceState *dev; - MemoryRegion *sm501_system_config = g_new(MemoryRegion, 1); - MemoryRegion *sm501_disp_ctrl = g_new(MemoryRegion, 1); - MemoryRegion *sm501_2d_engine = g_new(MemoryRegion, 1); - - /* allocate management data region */ - s = (SM501State *)g_malloc0(sizeof(SM501State)); - s->base = base; - s->local_mem_size_index - = get_local_mem_size_index(local_mem_bytes); - SM501_DPRINTF("local mem size=%x. index=%d\n", get_local_mem_size(s), - s->local_mem_size_index); - s->system_control = 0x00100000; - s->misc_control = 0x00001000; /* assumes SH, active=low */ - s->dc_panel_control = 0x00010000; - s->dc_crt_control = 0x00010000; - - /* allocate local memory */ - memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local", - local_mem_bytes, &error_fatal); - vmstate_register_ram_global(&s->local_mem_region); - memory_region_set_log(&s->local_mem_region, true, DIRTY_MEMORY_VGA); - s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region); - memory_region_add_subregion(address_space_mem, base, &s->local_mem_region); - - /* map mmio */ - memory_region_init_io(sm501_system_config, NULL, &sm501_system_config_ops, s, - "sm501-system-config", 0x6c); - memory_region_add_subregion(address_space_mem, base + MMIO_BASE_OFFSET, - sm501_system_config); - memory_region_init_io(sm501_disp_ctrl, NULL, &sm501_disp_ctrl_ops, s, - "sm501-disp-ctrl", 0x1000); - memory_region_add_subregion(address_space_mem, - base + MMIO_BASE_OFFSET + SM501_DC, - sm501_disp_ctrl); - memory_region_init_io(sm501_2d_engine, NULL, &sm501_2d_engine_ops, s, - "sm501-2d-engine", 0x54); - memory_region_add_subregion(address_space_mem, - base + MMIO_BASE_OFFSET + SM501_2D_ENGINE, - sm501_2d_engine); - - /* bridge to usb host emulation module */ - dev = qdev_create(NULL, "sysbus-ohci"); - qdev_prop_set_uint32(dev, "num-ports", 2); - qdev_prop_set_uint64(dev, "dma-offset", base); - qdev_init_nofail(dev); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, - base + MMIO_BASE_OFFSET + SM501_USB_HOST); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq); - - /* bridge to serial emulation module */ - if (chr) { - serial_mm_init(address_space_mem, - base + MMIO_BASE_OFFSET + SM501_UART0, 2, - NULL, /* TODO : chain irq to IRL */ - 115200, chr, DEVICE_NATIVE_ENDIAN); - } - - /* create qemu graphic console */ - s->con = graphic_console_init(DEVICE(dev), 0, &sm501_ops, s); -} diff --git a/qemu/hw/display/sm501_template.h b/qemu/hw/display/sm501_template.h deleted file mode 100644 index f33e499be..000000000 --- a/qemu/hw/display/sm501_template.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Pixel drawing function templates for QEMU SM501 Device - * - * Copyright (c) 2008 Shin-ichiro KAWASAKI - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if DEPTH == 8 -#define BPP 1 -#define PIXEL_TYPE uint8_t -#elif DEPTH == 15 || DEPTH == 16 -#define BPP 2 -#define PIXEL_TYPE uint16_t -#elif DEPTH == 32 -#define BPP 4 -#define PIXEL_TYPE uint32_t -#else -#error unsupport depth -#endif - -#ifdef BGR_FORMAT -#define PIXEL_NAME glue(DEPTH, bgr) -#else -#define PIXEL_NAME DEPTH -#endif /* BGR_FORMAT */ - - -static void glue(draw_line8_, PIXEL_NAME)( - uint8_t *d, const uint8_t *s, int width, const uint32_t *pal) -{ - uint8_t v, r, g, b; - do { - v = ldub_p(s); - r = (pal[v] >> 16) & 0xff; - g = (pal[v] >> 8) & 0xff; - b = (pal[v] >> 0) & 0xff; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); - s ++; - d += BPP; - } while (-- width != 0); -} - -static void glue(draw_line16_, PIXEL_NAME)( - uint8_t *d, const uint8_t *s, int width, const uint32_t *pal) -{ - uint16_t rgb565; - uint8_t r, g, b; - - do { - rgb565 = lduw_p(s); - r = ((rgb565 >> 11) & 0x1f) << 3; - g = ((rgb565 >> 5) & 0x3f) << 2; - b = ((rgb565 >> 0) & 0x1f) << 3; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); - s += 2; - d += BPP; - } while (-- width != 0); -} - -static void glue(draw_line32_, PIXEL_NAME)( - uint8_t *d, const uint8_t *s, int width, const uint32_t *pal) -{ - uint8_t r, g, b; - - do { - ldub_p(s); -#if defined(TARGET_WORDS_BIGENDIAN) - r = s[1]; - g = s[2]; - b = s[3]; -#else - b = s[0]; - g = s[1]; - r = s[2]; -#endif - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); - s += 4; - d += BPP; - } while (-- width != 0); -} - -/** - * Draw hardware cursor image on the given line. - */ -static void glue(draw_hwc_line_, PIXEL_NAME)(SM501State * s, int crt, - uint8_t * palette, int c_y, uint8_t *d, int width) -{ - int x, i; - uint8_t bitset = 0; - - /* get hardware cursor pattern */ - uint32_t cursor_addr = get_hwc_address(s, crt); - assert(0 <= c_y && c_y < SM501_HWC_HEIGHT); - cursor_addr += 64 * c_y / 4; /* 4 pixels per byte */ - cursor_addr += s->base; - - /* get cursor position */ - x = get_hwc_x(s, crt); - d += x * BPP; - - for (i = 0; i < SM501_HWC_WIDTH && x + i < width; i++) { - uint8_t v; - - /* get pixel value */ - if (i % 4 == 0) { - bitset = ldub_phys(&address_space_memory, cursor_addr); - cursor_addr++; - } - v = bitset & 3; - bitset >>= 2; - - /* write pixel */ - if (v) { - v--; - uint8_t r = palette[v * 3 + 0]; - uint8_t g = palette[v * 3 + 1]; - uint8_t b = palette[v * 3 + 2]; - ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); - } - d += BPP; - } -} - -#undef DEPTH -#undef BPP -#undef PIXEL_TYPE -#undef PIXEL_NAME -#undef BGR_FORMAT diff --git a/qemu/hw/display/ssd0303.c b/qemu/hw/display/ssd0303.c deleted file mode 100644 index d3017563f..000000000 --- a/qemu/hw/display/ssd0303.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * SSD0303 OLED controller with OSRAM Pictiva 96x16 display. - * - * Copyright (c) 2006-2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licensed under the GPL. - */ - -/* The controller can support a variety of different displays, but we only - implement one. Most of the commends relating to brightness and geometry - setup are ignored. */ -#include "qemu/osdep.h" -#include "hw/i2c/i2c.h" -#include "ui/console.h" - -//#define DEBUG_SSD0303 1 - -#ifdef DEBUG_SSD0303 -#define DPRINTF(fmt, ...) \ -do { printf("ssd0303: " fmt , ## __VA_ARGS__); } while (0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "ssd0303: error: " fmt , ## __VA_ARGS__); exit(1);} while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "ssd0303: error: " fmt , ## __VA_ARGS__);} while (0) -#endif - -/* Scaling factor for pixels. */ -#define MAGNIFY 4 - -enum ssd0303_mode -{ - SSD0303_IDLE, - SSD0303_DATA, - SSD0303_CMD -}; - -enum ssd0303_cmd { - SSD0303_CMD_NONE, - SSD0303_CMD_SKIP1 -}; - -#define TYPE_SSD0303 "ssd0303" -#define SSD0303(obj) OBJECT_CHECK(ssd0303_state, (obj), TYPE_SSD0303) - -typedef struct { - I2CSlave parent_obj; - - QemuConsole *con; - int row; - int col; - int start_line; - int mirror; - int flash; - int enabled; - int inverse; - int redraw; - enum ssd0303_mode mode; - enum ssd0303_cmd cmd_state; - uint8_t framebuffer[132*8]; -} ssd0303_state; - -static int ssd0303_recv(I2CSlave *i2c) -{ - BADF("Reads not implemented\n"); - return -1; -} - -static int ssd0303_send(I2CSlave *i2c, uint8_t data) -{ - ssd0303_state *s = SSD0303(i2c); - enum ssd0303_cmd old_cmd_state; - - switch (s->mode) { - case SSD0303_IDLE: - DPRINTF("byte 0x%02x\n", data); - if (data == 0x80) - s->mode = SSD0303_CMD; - else if (data == 0x40) - s->mode = SSD0303_DATA; - else - BADF("Unexpected byte 0x%x\n", data); - break; - case SSD0303_DATA: - DPRINTF("data 0x%02x\n", data); - if (s->col < 132) { - s->framebuffer[s->col + s->row * 132] = data; - s->col++; - s->redraw = 1; - } - break; - case SSD0303_CMD: - old_cmd_state = s->cmd_state; - s->cmd_state = SSD0303_CMD_NONE; - switch (old_cmd_state) { - case SSD0303_CMD_NONE: - DPRINTF("cmd 0x%02x\n", data); - s->mode = SSD0303_IDLE; - switch (data) { - case 0x00 ... 0x0f: /* Set lower column address. */ - s->col = (s->col & 0xf0) | (data & 0xf); - break; - case 0x10 ... 0x20: /* Set higher column address. */ - s->col = (s->col & 0x0f) | ((data & 0xf) << 4); - break; - case 0x40 ... 0x7f: /* Set start line. */ - s->start_line = 0; - break; - case 0x81: /* Set contrast (Ignored). */ - s->cmd_state = SSD0303_CMD_SKIP1; - break; - case 0xa0: /* Mirror off. */ - s->mirror = 0; - break; - case 0xa1: /* Mirror off. */ - s->mirror = 1; - break; - case 0xa4: /* Entire display off. */ - s->flash = 0; - break; - case 0xa5: /* Entire display on. */ - s->flash = 1; - break; - case 0xa6: /* Inverse off. */ - s->inverse = 0; - break; - case 0xa7: /* Inverse on. */ - s->inverse = 1; - break; - case 0xa8: /* Set multiplied ratio (Ignored). */ - s->cmd_state = SSD0303_CMD_SKIP1; - break; - case 0xad: /* DC-DC power control. */ - s->cmd_state = SSD0303_CMD_SKIP1; - break; - case 0xae: /* Display off. */ - s->enabled = 0; - break; - case 0xaf: /* Display on. */ - s->enabled = 1; - break; - case 0xb0 ... 0xbf: /* Set Page address. */ - s->row = data & 7; - break; - case 0xc0 ... 0xc8: /* Set COM output direction (Ignored). */ - break; - case 0xd3: /* Set display offset (Ignored). */ - s->cmd_state = SSD0303_CMD_SKIP1; - break; - case 0xd5: /* Set display clock (Ignored). */ - s->cmd_state = SSD0303_CMD_SKIP1; - break; - case 0xd8: /* Set color and power mode (Ignored). */ - s->cmd_state = SSD0303_CMD_SKIP1; - break; - case 0xd9: /* Set pre-charge period (Ignored). */ - s->cmd_state = SSD0303_CMD_SKIP1; - break; - case 0xda: /* Set COM pin configuration (Ignored). */ - s->cmd_state = SSD0303_CMD_SKIP1; - break; - case 0xdb: /* Set VCOM dselect level (Ignored). */ - s->cmd_state = SSD0303_CMD_SKIP1; - break; - case 0xe3: /* no-op. */ - break; - default: - BADF("Unknown command: 0x%x\n", data); - } - break; - case SSD0303_CMD_SKIP1: - DPRINTF("skip 0x%02x\n", data); - break; - } - break; - } - return 0; -} - -static void ssd0303_event(I2CSlave *i2c, enum i2c_event event) -{ - ssd0303_state *s = SSD0303(i2c); - - switch (event) { - case I2C_FINISH: - s->mode = SSD0303_IDLE; - break; - case I2C_START_RECV: - case I2C_START_SEND: - case I2C_NACK: - /* Nothing to do. */ - break; - } -} - -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; - int y; - int line; - char *colors[2]; - char colortab[MAGNIFY * 8]; - int dest_width; - uint8_t mask; - - if (!s->redraw) - return; - - switch (surface_bits_per_pixel(surface)) { - case 0: - return; - case 15: - dest_width = 2; - break; - case 16: - dest_width = 2; - break; - case 24: - dest_width = 3; - break; - case 32: - dest_width = 4; - break; - default: - BADF("Bad color depth\n"); - return; - } - dest_width *= MAGNIFY; - memset(colortab, 0xff, dest_width); - memset(colortab + dest_width, 0, dest_width); - if (s->flash) { - colors[0] = colortab; - colors[1] = colortab; - } else if (s->inverse) { - colors[0] = colortab; - colors[1] = colortab + dest_width; - } else { - colors[0] = colortab + dest_width; - colors[1] = colortab; - } - dest = surface_data(surface); - for (y = 0; y < 16; y++) { - line = (y + s->start_line) & 63; - src = s->framebuffer + 132 * (line >> 3) + 36; - mask = 1 << (line & 7); - for (x = 0; x < 96; x++) { - memcpy(dest, colors[(*src & mask) != 0], dest_width); - dest += dest_width; - src++; - } - for (x = 1; x < MAGNIFY; x++) { - memcpy(dest, dest - dest_width * 96, dest_width * 96); - dest += dest_width * 96; - } - } - s->redraw = 0; - dpy_gfx_update(s->con, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY); -} - -static void ssd0303_invalidate_display(void * opaque) -{ - ssd0303_state *s = (ssd0303_state *)opaque; - s->redraw = 1; -} - -static const VMStateDescription vmstate_ssd0303 = { - .name = "ssd0303_oled", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_INT32(row, ssd0303_state), - VMSTATE_INT32(col, ssd0303_state), - VMSTATE_INT32(start_line, ssd0303_state), - VMSTATE_INT32(mirror, ssd0303_state), - VMSTATE_INT32(flash, ssd0303_state), - VMSTATE_INT32(enabled, ssd0303_state), - VMSTATE_INT32(inverse, ssd0303_state), - VMSTATE_INT32(redraw, ssd0303_state), - VMSTATE_UINT32(mode, ssd0303_state), - VMSTATE_UINT32(cmd_state, ssd0303_state), - VMSTATE_BUFFER(framebuffer, ssd0303_state), - VMSTATE_I2C_SLAVE(parent_obj, ssd0303_state), - VMSTATE_END_OF_LIST() - } -}; - -static const GraphicHwOps ssd0303_ops = { - .invalidate = ssd0303_invalidate_display, - .gfx_update = ssd0303_update_display, -}; - -static int ssd0303_init(I2CSlave *i2c) -{ - ssd0303_state *s = SSD0303(i2c); - - s->con = graphic_console_init(DEVICE(i2c), 0, &ssd0303_ops, s); - qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY); - return 0; -} - -static void ssd0303_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); - - k->init = ssd0303_init; - k->event = ssd0303_event; - k->recv = ssd0303_recv; - k->send = ssd0303_send; - dc->vmsd = &vmstate_ssd0303; -} - -static const TypeInfo ssd0303_info = { - .name = TYPE_SSD0303, - .parent = TYPE_I2C_SLAVE, - .instance_size = sizeof(ssd0303_state), - .class_init = ssd0303_class_init, -}; - -static void ssd0303_register_types(void) -{ - type_register_static(&ssd0303_info); -} - -type_init(ssd0303_register_types) diff --git a/qemu/hw/display/ssd0323.c b/qemu/hw/display/ssd0323.c deleted file mode 100644 index 14c1bf339..000000000 --- a/qemu/hw/display/ssd0323.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * SSD0323 OLED controller with OSRAM Pictiva 128x64 display. - * - * Copyright (c) 2006-2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licensed under the GPL. - */ - -/* The controller can support a variety of different displays, but we only - implement one. Most of the commends relating to brightness and geometry - setup are ignored. */ -#include "qemu/osdep.h" -#include "hw/ssi/ssi.h" -#include "ui/console.h" - -//#define DEBUG_SSD0323 1 - -#ifdef DEBUG_SSD0323 -#define DPRINTF(fmt, ...) \ -do { printf("ssd0323: " fmt , ## __VA_ARGS__); } while (0) -#define BADF(fmt, ...) \ -do { \ - fprintf(stderr, "ssd0323: error: " fmt , ## __VA_ARGS__); abort(); \ -} while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "ssd0323: error: " fmt , ## __VA_ARGS__);} while (0) -#endif - -/* Scaling factor for pixels. */ -#define MAGNIFY 4 - -#define REMAP_SWAP_COLUMN 0x01 -#define REMAP_SWAP_NYBBLE 0x02 -#define REMAP_VERTICAL 0x04 -#define REMAP_SWAP_COM 0x10 -#define REMAP_SPLIT_COM 0x40 - -enum ssd0323_mode -{ - SSD0323_CMD, - SSD0323_DATA -}; - -typedef struct { - SSISlave ssidev; - QemuConsole *con; - - int cmd_len; - int cmd; - int cmd_data[8]; - int row; - int row_start; - int row_end; - int col; - int col_start; - int col_end; - int redraw; - int remap; - enum ssd0323_mode mode; - uint8_t framebuffer[128 * 80 / 2]; -} ssd0323_state; - -static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data) -{ - ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev); - - switch (s->mode) { - case SSD0323_DATA: - DPRINTF("data 0x%02x\n", data); - s->framebuffer[s->col + s->row * 64] = data; - if (s->remap & REMAP_VERTICAL) { - s->row++; - if (s->row > s->row_end) { - s->row = s->row_start; - s->col++; - } - if (s->col > s->col_end) { - s->col = s->col_start; - } - } else { - s->col++; - if (s->col > s->col_end) { - s->row++; - s->col = s->col_start; - } - if (s->row > s->row_end) { - s->row = s->row_start; - } - } - s->redraw = 1; - break; - case SSD0323_CMD: - DPRINTF("cmd 0x%02x\n", data); - if (s->cmd_len == 0) { - s->cmd = data; - } else { - s->cmd_data[s->cmd_len - 1] = data; - } - s->cmd_len++; - switch (s->cmd) { -#define DATA(x) if (s->cmd_len <= (x)) return 0 - case 0x15: /* Set column. */ - DATA(2); - s->col = s->col_start = s->cmd_data[0] % 64; - s->col_end = s->cmd_data[1] % 64; - break; - case 0x75: /* Set row. */ - DATA(2); - s->row = s->row_start = s->cmd_data[0] % 80; - s->row_end = s->cmd_data[1] % 80; - break; - case 0x81: /* Set contrast */ - DATA(1); - break; - case 0x84: case 0x85: case 0x86: /* Max current. */ - DATA(0); - break; - case 0xa0: /* Set remapping. */ - /* FIXME: Implement this. */ - DATA(1); - s->remap = s->cmd_data[0]; - break; - case 0xa1: /* Set display start line. */ - case 0xa2: /* Set display offset. */ - /* FIXME: Implement these. */ - DATA(1); - break; - case 0xa4: /* Normal mode. */ - case 0xa5: /* All on. */ - case 0xa6: /* All off. */ - case 0xa7: /* Inverse. */ - /* FIXME: Implement these. */ - DATA(0); - break; - case 0xa8: /* Set multiplex ratio. */ - case 0xad: /* Set DC-DC converter. */ - DATA(1); - /* Ignored. Don't care. */ - break; - case 0xae: /* Display off. */ - case 0xaf: /* Display on. */ - DATA(0); - /* TODO: Implement power control. */ - break; - case 0xb1: /* Set phase length. */ - case 0xb2: /* Set row period. */ - case 0xb3: /* Set clock rate. */ - case 0xbc: /* Set precharge. */ - case 0xbe: /* Set VCOMH. */ - case 0xbf: /* Set segment low. */ - DATA(1); - /* Ignored. Don't care. */ - break; - case 0xb8: /* Set grey scale table. */ - /* FIXME: Implement this. */ - DATA(8); - break; - case 0xe3: /* NOP. */ - DATA(0); - break; - case 0xff: /* Nasty hack because we don't handle chip selects - properly. */ - break; - default: - BADF("Unknown command: 0x%x\n", data); - } - s->cmd_len = 0; - return 0; - } - return 0; -} - -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; - int y; - int i; - int line; - char *colors[16]; - char colortab[MAGNIFY * 64]; - char *p; - int dest_width; - - if (!s->redraw) - return; - - switch (surface_bits_per_pixel(surface)) { - case 0: - return; - case 15: - dest_width = 2; - break; - case 16: - dest_width = 2; - break; - case 24: - dest_width = 3; - break; - case 32: - dest_width = 4; - break; - default: - BADF("Bad color depth\n"); - return; - } - p = colortab; - for (i = 0; i < 16; i++) { - int n; - colors[i] = p; - switch (surface_bits_per_pixel(surface)) { - case 15: - n = i * 2 + (i >> 3); - p[0] = n | (n << 5); - p[1] = (n << 2) | (n >> 3); - break; - case 16: - n = i * 2 + (i >> 3); - p[0] = n | (n << 6) | ((n << 1) & 0x20); - p[1] = (n << 3) | (n >> 2); - break; - case 24: - case 32: - n = (i << 4) | i; - p[0] = p[1] = p[2] = n; - break; - default: - BADF("Bad color depth\n"); - return; - } - p += dest_width; - } - /* TODO: Implement row/column remapping. */ - dest = surface_data(surface); - for (y = 0; y < 64; y++) { - line = y; - src = s->framebuffer + 64 * line; - for (x = 0; x < 64; x++) { - int val; - val = *src >> 4; - for (i = 0; i < MAGNIFY; i++) { - memcpy(dest, colors[val], dest_width); - dest += dest_width; - } - val = *src & 0xf; - for (i = 0; i < MAGNIFY; i++) { - memcpy(dest, colors[val], dest_width); - dest += dest_width; - } - src++; - } - for (i = 1; i < MAGNIFY; i++) { - memcpy(dest, dest - dest_width * MAGNIFY * 128, - dest_width * 128 * MAGNIFY); - dest += dest_width * 128 * MAGNIFY; - } - } - s->redraw = 0; - dpy_gfx_update(s->con, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY); -} - -static void ssd0323_invalidate_display(void * opaque) -{ - ssd0323_state *s = (ssd0323_state *)opaque; - s->redraw = 1; -} - -/* Command/data input. */ -static void ssd0323_cd(void *opaque, int n, int level) -{ - ssd0323_state *s = (ssd0323_state *)opaque; - DPRINTF("%s mode\n", level ? "Data" : "Command"); - s->mode = level ? SSD0323_DATA : SSD0323_CMD; -} - -static void ssd0323_save(QEMUFile *f, void *opaque) -{ - SSISlave *ss = SSI_SLAVE(opaque); - ssd0323_state *s = (ssd0323_state *)opaque; - int i; - - qemu_put_be32(f, s->cmd_len); - qemu_put_be32(f, s->cmd); - for (i = 0; i < 8; i++) - qemu_put_be32(f, s->cmd_data[i]); - qemu_put_be32(f, s->row); - qemu_put_be32(f, s->row_start); - qemu_put_be32(f, s->row_end); - qemu_put_be32(f, s->col); - qemu_put_be32(f, s->col_start); - qemu_put_be32(f, s->col_end); - qemu_put_be32(f, s->redraw); - qemu_put_be32(f, s->remap); - qemu_put_be32(f, s->mode); - qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer)); - - qemu_put_be32(f, ss->cs); -} - -static int ssd0323_load(QEMUFile *f, void *opaque, int version_id) -{ - SSISlave *ss = SSI_SLAVE(opaque); - ssd0323_state *s = (ssd0323_state *)opaque; - int i; - - if (version_id != 1) - return -EINVAL; - - s->cmd_len = qemu_get_be32(f); - if (s->cmd_len < 0 || s->cmd_len > ARRAY_SIZE(s->cmd_data)) { - return -EINVAL; - } - s->cmd = qemu_get_be32(f); - for (i = 0; i < 8; i++) - s->cmd_data[i] = qemu_get_be32(f); - s->row = qemu_get_be32(f); - if (s->row < 0 || s->row >= 80) { - return -EINVAL; - } - s->row_start = qemu_get_be32(f); - if (s->row_start < 0 || s->row_start >= 80) { - return -EINVAL; - } - s->row_end = qemu_get_be32(f); - if (s->row_end < 0 || s->row_end >= 80) { - return -EINVAL; - } - s->col = qemu_get_be32(f); - if (s->col < 0 || s->col >= 64) { - return -EINVAL; - } - s->col_start = qemu_get_be32(f); - if (s->col_start < 0 || s->col_start >= 64) { - return -EINVAL; - } - s->col_end = qemu_get_be32(f); - if (s->col_end < 0 || s->col_end >= 64) { - return -EINVAL; - } - s->redraw = qemu_get_be32(f); - s->remap = qemu_get_be32(f); - s->mode = qemu_get_be32(f); - if (s->mode != SSD0323_CMD && s->mode != SSD0323_DATA) { - return -EINVAL; - } - qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer)); - - ss->cs = qemu_get_be32(f); - - return 0; -} - -static const GraphicHwOps ssd0323_ops = { - .invalidate = ssd0323_invalidate_display, - .gfx_update = ssd0323_update_display, -}; - -static int ssd0323_init(SSISlave *d) -{ - DeviceState *dev = DEVICE(d); - ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, d); - - s->col_end = 63; - s->row_end = 79; - s->con = graphic_console_init(dev, 0, &ssd0323_ops, s); - qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY); - - qdev_init_gpio_in(dev, ssd0323_cd, 1); - - register_savevm(dev, "ssd0323_oled", -1, 1, - ssd0323_save, ssd0323_load, s); - return 0; -} - -static void ssd0323_class_init(ObjectClass *klass, void *data) -{ - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); - - k->init = ssd0323_init; - k->transfer = ssd0323_transfer; - k->cs_polarity = SSI_CS_HIGH; -} - -static const TypeInfo ssd0323_info = { - .name = "ssd0323", - .parent = TYPE_SSI_SLAVE, - .instance_size = sizeof(ssd0323_state), - .class_init = ssd0323_class_init, -}; - -static void ssd03232_register_types(void) -{ - type_register_static(&ssd0323_info); -} - -type_init(ssd03232_register_types) diff --git a/qemu/hw/display/tc6393xb.c b/qemu/hw/display/tc6393xb.c deleted file mode 100644 index da3ceceb0..000000000 --- a/qemu/hw/display/tc6393xb.c +++ /dev/null @@ -1,598 +0,0 @@ -/* - * Toshiba TC6393XB I/O Controller. - * Found in Sharp Zaurus SL-6000 (tosa) or some - * Toshiba e-Series PDAs. - * - * Most features are currently unsupported!!! - * - * This code is licensed under the GNU GPL v2. - * - * 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/osdep.h" -#include "qapi/error.h" -#include "hw/hw.h" -#include "hw/devices.h" -#include "hw/block/flash.h" -#include "ui/console.h" -#include "ui/pixel_ops.h" -#include "sysemu/block-backend.h" -#include "sysemu/blockdev.h" - -#define IRQ_TC6393_NAND 0 -#define IRQ_TC6393_MMC 1 -#define IRQ_TC6393_OHCI 2 -#define IRQ_TC6393_SERIAL 3 -#define IRQ_TC6393_FB 4 - -#define TC6393XB_NR_IRQS 8 - -#define TC6393XB_GPIOS 16 - -#define SCR_REVID 0x08 /* b Revision ID */ -#define SCR_ISR 0x50 /* b Interrupt Status */ -#define SCR_IMR 0x52 /* b Interrupt Mask */ -#define SCR_IRR 0x54 /* b Interrupt Routing */ -#define SCR_GPER 0x60 /* w GP Enable */ -#define SCR_GPI_SR(i) (0x64 + (i)) /* b3 GPI Status */ -#define SCR_GPI_IMR(i) (0x68 + (i)) /* b3 GPI INT Mask */ -#define SCR_GPI_EDER(i) (0x6c + (i)) /* b3 GPI Edge Detect Enable */ -#define SCR_GPI_LIR(i) (0x70 + (i)) /* b3 GPI Level Invert */ -#define SCR_GPO_DSR(i) (0x78 + (i)) /* b3 GPO Data Set */ -#define SCR_GPO_DOECR(i) (0x7c + (i)) /* b3 GPO Data OE Control */ -#define SCR_GP_IARCR(i) (0x80 + (i)) /* b3 GP Internal Active Register Control */ -#define SCR_GP_IARLCR(i) (0x84 + (i)) /* b3 GP INTERNAL Active Register Level Control */ -#define SCR_GPI_BCR(i) (0x88 + (i)) /* b3 GPI Buffer Control */ -#define SCR_GPA_IARCR 0x8c /* w GPa Internal Active Register Control */ -#define SCR_GPA_IARLCR 0x90 /* w GPa Internal Active Register Level Control */ -#define SCR_GPA_BCR 0x94 /* w GPa Buffer Control */ -#define SCR_CCR 0x98 /* w Clock Control */ -#define SCR_PLL2CR 0x9a /* w PLL2 Control */ -#define SCR_PLL1CR 0x9c /* l PLL1 Control */ -#define SCR_DIARCR 0xa0 /* b Device Internal Active Register Control */ -#define SCR_DBOCR 0xa1 /* b Device Buffer Off Control */ -#define SCR_FER 0xe0 /* b Function Enable */ -#define SCR_MCR 0xe4 /* w Mode Control */ -#define SCR_CONFIG 0xfc /* b Configuration Control */ -#define SCR_DEBUG 0xff /* b Debug */ - -#define NAND_CFG_COMMAND 0x04 /* w Command */ -#define NAND_CFG_BASE 0x10 /* l Control Base Address */ -#define NAND_CFG_INTP 0x3d /* b Interrupt Pin */ -#define NAND_CFG_INTE 0x48 /* b Int Enable */ -#define NAND_CFG_EC 0x4a /* b Event Control */ -#define NAND_CFG_ICC 0x4c /* b Internal Clock Control */ -#define NAND_CFG_ECCC 0x5b /* b ECC Control */ -#define NAND_CFG_NFTC 0x60 /* b NAND Flash Transaction Control */ -#define NAND_CFG_NFM 0x61 /* b NAND Flash Monitor */ -#define NAND_CFG_NFPSC 0x62 /* b NAND Flash Power Supply Control */ -#define NAND_CFG_NFDC 0x63 /* b NAND Flash Detect Control */ - -#define NAND_DATA 0x00 /* l Data */ -#define NAND_MODE 0x04 /* b Mode */ -#define NAND_STATUS 0x05 /* b Status */ -#define NAND_ISR 0x06 /* b Interrupt Status */ -#define NAND_IMR 0x07 /* b Interrupt Mask */ - -#define NAND_MODE_WP 0x80 -#define NAND_MODE_CE 0x10 -#define NAND_MODE_ALE 0x02 -#define NAND_MODE_CLE 0x01 -#define NAND_MODE_ECC_MASK 0x60 -#define NAND_MODE_ECC_EN 0x20 -#define NAND_MODE_ECC_READ 0x40 -#define NAND_MODE_ECC_RST 0x60 - -struct TC6393xbState { - MemoryRegion iomem; - qemu_irq irq; - qemu_irq *sub_irqs; - struct { - uint8_t ISR; - uint8_t IMR; - uint8_t IRR; - uint16_t GPER; - uint8_t GPI_SR[3]; - uint8_t GPI_IMR[3]; - uint8_t GPI_EDER[3]; - uint8_t GPI_LIR[3]; - uint8_t GP_IARCR[3]; - uint8_t GP_IARLCR[3]; - uint8_t GPI_BCR[3]; - uint16_t GPA_IARCR; - uint16_t GPA_IARLCR; - uint16_t CCR; - uint16_t PLL2CR; - uint32_t PLL1CR; - uint8_t DIARCR; - uint8_t DBOCR; - uint8_t FER; - uint16_t MCR; - uint8_t CONFIG; - uint8_t DEBUG; - } scr; - uint32_t gpio_dir; - uint32_t gpio_level; - uint32_t prev_level; - qemu_irq handler[TC6393XB_GPIOS]; - qemu_irq *gpio_in; - - struct { - uint8_t mode; - uint8_t isr; - uint8_t imr; - } nand; - int nand_enable; - uint32_t nand_phys; - DeviceState *flash; - ECCState ecc; - - QemuConsole *con; - MemoryRegion vram; - uint16_t *vram_ptr; - uint32_t scr_width, scr_height; /* in pixels */ - qemu_irq l3v; - unsigned blank : 1, - blanked : 1; -}; - -qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s) -{ - return s->gpio_in; -} - -static void tc6393xb_gpio_set(void *opaque, int line, int level) -{ -// TC6393xbState *s = opaque; - - if (line > TC6393XB_GPIOS) { - printf("%s: No GPIO pin %i\n", __FUNCTION__, line); - return; - } - - // FIXME: how does the chip reflect the GPIO input level change? -} - -void tc6393xb_gpio_out_set(TC6393xbState *s, int line, - qemu_irq handler) -{ - if (line >= TC6393XB_GPIOS) { - fprintf(stderr, "TC6393xb: no GPIO pin %d\n", line); - return; - } - - s->handler[line] = handler; -} - -static void tc6393xb_gpio_handler_update(TC6393xbState *s) -{ - uint32_t level, diff; - int bit; - - level = s->gpio_level & s->gpio_dir; - - for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) { - bit = ctz32(diff); - qemu_set_irq(s->handler[bit], (level >> bit) & 1); - } - - s->prev_level = level; -} - -qemu_irq tc6393xb_l3v_get(TC6393xbState *s) -{ - return s->l3v; -} - -static void tc6393xb_l3v(void *opaque, int line, int level) -{ - TC6393xbState *s = opaque; - s->blank = !level; - fprintf(stderr, "L3V: %d\n", level); -} - -static void tc6393xb_sub_irq(void *opaque, int line, int level) { - TC6393xbState *s = opaque; - uint8_t isr = s->scr.ISR; - if (level) - isr |= 1 << line; - else - isr &= ~(1 << line); - s->scr.ISR = isr; - qemu_set_irq(s->irq, isr & s->scr.IMR); -} - -#define SCR_REG_B(N) \ - case SCR_ ##N: return s->scr.N -#define SCR_REG_W(N) \ - case SCR_ ##N: return s->scr.N; \ - case SCR_ ##N + 1: return s->scr.N >> 8; -#define SCR_REG_L(N) \ - case SCR_ ##N: return s->scr.N; \ - case SCR_ ##N + 1: return s->scr.N >> 8; \ - case SCR_ ##N + 2: return s->scr.N >> 16; \ - case SCR_ ##N + 3: return s->scr.N >> 24; -#define SCR_REG_A(N) \ - case SCR_ ##N(0): return s->scr.N[0]; \ - case SCR_ ##N(1): return s->scr.N[1]; \ - case SCR_ ##N(2): return s->scr.N[2] - -static uint32_t tc6393xb_scr_readb(TC6393xbState *s, hwaddr addr) -{ - switch (addr) { - case SCR_REVID: - return 3; - case SCR_REVID+1: - return 0; - SCR_REG_B(ISR); - SCR_REG_B(IMR); - SCR_REG_B(IRR); - SCR_REG_W(GPER); - SCR_REG_A(GPI_SR); - SCR_REG_A(GPI_IMR); - SCR_REG_A(GPI_EDER); - SCR_REG_A(GPI_LIR); - case SCR_GPO_DSR(0): - case SCR_GPO_DSR(1): - case SCR_GPO_DSR(2): - return (s->gpio_level >> ((addr - SCR_GPO_DSR(0)) * 8)) & 0xff; - case SCR_GPO_DOECR(0): - case SCR_GPO_DOECR(1): - case SCR_GPO_DOECR(2): - return (s->gpio_dir >> ((addr - SCR_GPO_DOECR(0)) * 8)) & 0xff; - SCR_REG_A(GP_IARCR); - SCR_REG_A(GP_IARLCR); - SCR_REG_A(GPI_BCR); - SCR_REG_W(GPA_IARCR); - SCR_REG_W(GPA_IARLCR); - SCR_REG_W(CCR); - SCR_REG_W(PLL2CR); - SCR_REG_L(PLL1CR); - SCR_REG_B(DIARCR); - SCR_REG_B(DBOCR); - SCR_REG_B(FER); - SCR_REG_W(MCR); - SCR_REG_B(CONFIG); - SCR_REG_B(DEBUG); - } - fprintf(stderr, "tc6393xb_scr: unhandled read at %08x\n", (uint32_t) addr); - return 0; -} -#undef SCR_REG_B -#undef SCR_REG_W -#undef SCR_REG_L -#undef SCR_REG_A - -#define SCR_REG_B(N) \ - case SCR_ ##N: s->scr.N = value; return; -#define SCR_REG_W(N) \ - case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); return; \ - case SCR_ ##N + 1: s->scr.N = (s->scr.N & 0xff) | (value << 8); return -#define SCR_REG_L(N) \ - case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); return; \ - case SCR_ ##N + 1: s->scr.N = (s->scr.N & ~(0xff << 8)) | (value & (0xff << 8)); return; \ - case SCR_ ##N + 2: s->scr.N = (s->scr.N & ~(0xff << 16)) | (value & (0xff << 16)); return; \ - case SCR_ ##N + 3: s->scr.N = (s->scr.N & ~(0xff << 24)) | (value & (0xff << 24)); return; -#define SCR_REG_A(N) \ - case SCR_ ##N(0): s->scr.N[0] = value; return; \ - case SCR_ ##N(1): s->scr.N[1] = value; return; \ - case SCR_ ##N(2): s->scr.N[2] = value; return - -static void tc6393xb_scr_writeb(TC6393xbState *s, hwaddr addr, uint32_t value) -{ - switch (addr) { - SCR_REG_B(ISR); - SCR_REG_B(IMR); - SCR_REG_B(IRR); - SCR_REG_W(GPER); - SCR_REG_A(GPI_SR); - SCR_REG_A(GPI_IMR); - SCR_REG_A(GPI_EDER); - SCR_REG_A(GPI_LIR); - case SCR_GPO_DSR(0): - case SCR_GPO_DSR(1): - case SCR_GPO_DSR(2): - s->gpio_level = (s->gpio_level & ~(0xff << ((addr - SCR_GPO_DSR(0))*8))) | ((value & 0xff) << ((addr - SCR_GPO_DSR(0))*8)); - tc6393xb_gpio_handler_update(s); - return; - case SCR_GPO_DOECR(0): - case SCR_GPO_DOECR(1): - case SCR_GPO_DOECR(2): - s->gpio_dir = (s->gpio_dir & ~(0xff << ((addr - SCR_GPO_DOECR(0))*8))) | ((value & 0xff) << ((addr - SCR_GPO_DOECR(0))*8)); - tc6393xb_gpio_handler_update(s); - return; - SCR_REG_A(GP_IARCR); - SCR_REG_A(GP_IARLCR); - SCR_REG_A(GPI_BCR); - SCR_REG_W(GPA_IARCR); - SCR_REG_W(GPA_IARLCR); - SCR_REG_W(CCR); - SCR_REG_W(PLL2CR); - SCR_REG_L(PLL1CR); - SCR_REG_B(DIARCR); - SCR_REG_B(DBOCR); - SCR_REG_B(FER); - SCR_REG_W(MCR); - SCR_REG_B(CONFIG); - SCR_REG_B(DEBUG); - } - fprintf(stderr, "tc6393xb_scr: unhandled write at %08x: %02x\n", - (uint32_t) addr, value & 0xff); -} -#undef SCR_REG_B -#undef SCR_REG_W -#undef SCR_REG_L -#undef SCR_REG_A - -static void tc6393xb_nand_irq(TC6393xbState *s) { - qemu_set_irq(s->sub_irqs[IRQ_TC6393_NAND], - (s->nand.imr & 0x80) && (s->nand.imr & s->nand.isr)); -} - -static uint32_t tc6393xb_nand_cfg_readb(TC6393xbState *s, hwaddr addr) { - switch (addr) { - case NAND_CFG_COMMAND: - return s->nand_enable ? 2 : 0; - case NAND_CFG_BASE: - case NAND_CFG_BASE + 1: - case NAND_CFG_BASE + 2: - case NAND_CFG_BASE + 3: - return s->nand_phys >> (addr - NAND_CFG_BASE); - } - fprintf(stderr, "tc6393xb_nand_cfg: unhandled read at %08x\n", (uint32_t) addr); - return 0; -} -static void tc6393xb_nand_cfg_writeb(TC6393xbState *s, hwaddr addr, uint32_t value) { - switch (addr) { - case NAND_CFG_COMMAND: - s->nand_enable = (value & 0x2); - return; - case NAND_CFG_BASE: - case NAND_CFG_BASE + 1: - case NAND_CFG_BASE + 2: - case NAND_CFG_BASE + 3: - s->nand_phys &= ~(0xff << ((addr - NAND_CFG_BASE) * 8)); - s->nand_phys |= (value & 0xff) << ((addr - NAND_CFG_BASE) * 8); - return; - } - fprintf(stderr, "tc6393xb_nand_cfg: unhandled write at %08x: %02x\n", - (uint32_t) addr, value & 0xff); -} - -static uint32_t tc6393xb_nand_readb(TC6393xbState *s, hwaddr addr) { - switch (addr) { - case NAND_DATA + 0: - case NAND_DATA + 1: - case NAND_DATA + 2: - case NAND_DATA + 3: - return nand_getio(s->flash); - case NAND_MODE: - return s->nand.mode; - case NAND_STATUS: - return 0x14; - case NAND_ISR: - return s->nand.isr; - case NAND_IMR: - return s->nand.imr; - } - fprintf(stderr, "tc6393xb_nand: unhandled read at %08x\n", (uint32_t) addr); - return 0; -} -static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value) { -// fprintf(stderr, "tc6393xb_nand: write at %08x: %02x\n", -// (uint32_t) addr, value & 0xff); - switch (addr) { - case NAND_DATA + 0: - case NAND_DATA + 1: - case NAND_DATA + 2: - case NAND_DATA + 3: - nand_setio(s->flash, value); - s->nand.isr |= 1; - tc6393xb_nand_irq(s); - return; - case NAND_MODE: - s->nand.mode = value; - nand_setpins(s->flash, - value & NAND_MODE_CLE, - value & NAND_MODE_ALE, - !(value & NAND_MODE_CE), - value & NAND_MODE_WP, - 0); // FIXME: gnd - switch (value & NAND_MODE_ECC_MASK) { - case NAND_MODE_ECC_RST: - ecc_reset(&s->ecc); - break; - case NAND_MODE_ECC_READ: - // FIXME - break; - case NAND_MODE_ECC_EN: - ecc_reset(&s->ecc); - } - return; - case NAND_ISR: - s->nand.isr = value; - tc6393xb_nand_irq(s); - return; - case NAND_IMR: - s->nand.imr = value; - tc6393xb_nand_irq(s); - return; - } - fprintf(stderr, "tc6393xb_nand: unhandled write at %08x: %02x\n", - (uint32_t) addr, value & 0xff); -} - -#define BITS 8 -#include "tc6393xb_template.h" -#define BITS 15 -#include "tc6393xb_template.h" -#define BITS 16 -#include "tc6393xb_template.h" -#define BITS 24 -#include "tc6393xb_template.h" -#define BITS 32 -#include "tc6393xb_template.h" - -static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update) -{ - DisplaySurface *surface = qemu_console_surface(s->con); - - switch (surface_bits_per_pixel(surface)) { - case 8: - tc6393xb_draw_graphic8(s); - break; - case 15: - tc6393xb_draw_graphic15(s); - break; - case 16: - tc6393xb_draw_graphic16(s); - break; - case 24: - tc6393xb_draw_graphic24(s); - break; - case 32: - tc6393xb_draw_graphic32(s); - break; - default: - printf("tc6393xb: unknown depth %d\n", - surface_bits_per_pixel(surface)); - return; - } - - 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 * surface_bytes_per_pixel(surface); - d = surface_data(surface); - for(i = 0; i < s->scr_height; i++) { - memset(d, 0, w); - d += surface_stride(surface); - } - - 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) - return; - - full_update = 0; - if (s->blanked != s->blank) { - s->blanked = s->blank; - full_update = 1; - } - 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) - tc6393xb_draw_blank(s, full_update); - else - tc6393xb_draw_graphic(s, full_update); -} - - -static uint64_t tc6393xb_readb(void *opaque, hwaddr addr, - unsigned size) -{ - TC6393xbState *s = opaque; - - switch (addr >> 8) { - case 0: - return tc6393xb_scr_readb(s, addr & 0xff); - case 1: - return tc6393xb_nand_cfg_readb(s, addr & 0xff); - }; - - if ((addr &~0xff) == s->nand_phys && s->nand_enable) { -// return tc6393xb_nand_readb(s, addr & 0xff); - uint8_t d = tc6393xb_nand_readb(s, addr & 0xff); -// fprintf(stderr, "tc6393xb_nand: read at %08x: %02hhx\n", (uint32_t) addr, d); - return d; - } - -// fprintf(stderr, "tc6393xb: unhandled read at %08x\n", (uint32_t) addr); - return 0; -} - -static void tc6393xb_writeb(void *opaque, hwaddr addr, - uint64_t value, unsigned size) { - TC6393xbState *s = opaque; - - switch (addr >> 8) { - case 0: - tc6393xb_scr_writeb(s, addr & 0xff, value); - return; - case 1: - tc6393xb_nand_cfg_writeb(s, addr & 0xff, value); - return; - }; - - if ((addr &~0xff) == s->nand_phys && s->nand_enable) - tc6393xb_nand_writeb(s, addr & 0xff, value); - else - fprintf(stderr, "tc6393xb: unhandled write at %08x: %02x\n", - (uint32_t) addr, (int)value & 0xff); -} - -static const GraphicHwOps tc6393xb_gfx_ops = { - .gfx_update = tc6393xb_update_display, -}; - -TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq) -{ - TC6393xbState *s; - DriveInfo *nand; - static const MemoryRegionOps tc6393xb_ops = { - .read = tc6393xb_readb, - .write = tc6393xb_writeb, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, - }; - - s = (TC6393xbState *) g_malloc0(sizeof(TC6393xbState)); - s->irq = irq; - s->gpio_in = qemu_allocate_irqs(tc6393xb_gpio_set, s, TC6393XB_GPIOS); - - s->l3v = qemu_allocate_irq(tc6393xb_l3v, s, 0); - s->blanked = 1; - - s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS); - - nand = drive_get(IF_MTD, 0, 0); - s->flash = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL, - NAND_MFR_TOSHIBA, 0x76); - - memory_region_init_io(&s->iomem, NULL, &tc6393xb_ops, s, "tc6393xb", 0x10000); - memory_region_add_subregion(sysmem, base, &s->iomem); - - memory_region_init_ram(&s->vram, NULL, "tc6393xb.vram", 0x100000, - &error_fatal); - vmstate_register_ram_global(&s->vram); - s->vram_ptr = memory_region_get_ram_ptr(&s->vram); - memory_region_add_subregion(sysmem, base + 0x100000, &s->vram); - s->scr_width = 480; - s->scr_height = 640; - s->con = graphic_console_init(NULL, 0, &tc6393xb_gfx_ops, s); - - return s; -} diff --git a/qemu/hw/display/tc6393xb_template.h b/qemu/hw/display/tc6393xb_template.h deleted file mode 100644 index 78629c07f..000000000 --- a/qemu/hw/display/tc6393xb_template.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Toshiba TC6393XB I/O Controller. - * Found in Sharp Zaurus SL-6000 (tosa) or some - * Toshiba e-Series PDAs. - * - * FB support code. Based on G364 fb emulator - * - * Copyright (c) 2007 Hervé Poussineau - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - */ - -#if BITS == 8 -# define SET_PIXEL(addr, color) (*(uint8_t *)addr = color) -#elif BITS == 15 || BITS == 16 -# define SET_PIXEL(addr, color) (*(uint16_t *)addr = color) -#elif BITS == 24 -# define SET_PIXEL(addr, color) \ - do { \ - addr[0] = color; \ - addr[1] = (color) >> 8; \ - addr[2] = (color) >> 16; \ - } while (0) -#elif BITS == 32 -# define SET_PIXEL(addr, color) (*(uint32_t *)addr = color) -#else -# error unknown bit depth -#endif - - -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 = 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 += surface_stride(surface); -#else - int j; - for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) { - uint16_t color = *data_buffer; - uint32_t dest_color = glue(rgb_to_pixel, BITS)( - ((color & 0xf800) * 0x108) >> 11, - ((color & 0x7e0) * 0x41) >> 9, - ((color & 0x1f) * 0x21) >> 2 - ); - SET_PIXEL(data_display, dest_color); - } -#endif - } -} - -#undef BITS -#undef SET_PIXEL diff --git a/qemu/hw/display/tcx.c b/qemu/hw/display/tcx.c deleted file mode 100644 index 8e26aae80..000000000 --- a/qemu/hw/display/tcx.c +++ /dev/null @@ -1,1106 +0,0 @@ -/* - * QEMU TCX Frame buffer - * - * Copyright (c) 2003-2005 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "qemu-common.h" -#include "cpu.h" /* FIXME shouldn't use TARGET_PAGE_SIZE */ -#include "ui/console.h" -#include "ui/pixel_ops.h" -#include "hw/loader.h" -#include "hw/sysbus.h" -#include "qemu/error-report.h" - -#define TCX_ROM_FILE "QEMU,tcx.bin" -#define FCODE_MAX_ROM_SIZE 0x10000 - -#define MAXX 1024 -#define MAXY 768 -#define TCX_DAC_NREGS 16 -#define TCX_THC_NREGS 0x1000 -#define TCX_DHC_NREGS 0x4000 -#define TCX_TEC_NREGS 0x1000 -#define TCX_ALT_NREGS 0x8000 -#define TCX_STIP_NREGS 0x800000 -#define TCX_BLIT_NREGS 0x800000 -#define TCX_RSTIP_NREGS 0x800000 -#define TCX_RBLIT_NREGS 0x800000 - -#define TCX_THC_MISC 0x818 -#define TCX_THC_CURSXY 0x8fc -#define TCX_THC_CURSMASK 0x900 -#define TCX_THC_CURSBITS 0x980 - -#define TYPE_TCX "SUNW,tcx" -#define TCX(obj) OBJECT_CHECK(TCXState, (obj), TYPE_TCX) - -typedef struct TCXState { - SysBusDevice parent_obj; - - QemuConsole *con; - qemu_irq irq; - uint8_t *vram; - uint32_t *vram24, *cplane; - hwaddr prom_addr; - MemoryRegion rom; - MemoryRegion vram_mem; - MemoryRegion vram_8bit; - MemoryRegion vram_24bit; - MemoryRegion stip; - MemoryRegion blit; - MemoryRegion vram_cplane; - MemoryRegion rstip; - MemoryRegion rblit; - MemoryRegion tec; - MemoryRegion dac; - MemoryRegion thc; - MemoryRegion dhc; - MemoryRegion alt; - MemoryRegion thc24; - - ram_addr_t vram24_offset, cplane_offset; - uint32_t tmpblit; - uint32_t vram_size; - uint32_t palette[260]; - uint8_t r[260], g[260], b[260]; - uint16_t width, height, depth; - uint8_t dac_index, dac_state; - uint32_t thcmisc; - uint32_t cursmask[32]; - uint32_t cursbits[32]; - uint16_t cursx; - uint16_t cursy; -} TCXState; - -static void tcx_set_dirty(TCXState *s) -{ - memory_region_set_dirty(&s->vram_mem, 0, MAXX * MAXY); -} - -static inline int tcx24_check_dirty(TCXState *s, ram_addr_t page, - ram_addr_t page24, ram_addr_t cpage) -{ - int ret; - - ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE, - DIRTY_MEMORY_VGA); - ret |= memory_region_get_dirty(&s->vram_mem, page24, TARGET_PAGE_SIZE * 4, - DIRTY_MEMORY_VGA); - ret |= memory_region_get_dirty(&s->vram_mem, cpage, TARGET_PAGE_SIZE * 4, - DIRTY_MEMORY_VGA); - return ret; -} - -static inline void tcx24_reset_dirty(TCXState *ts, ram_addr_t page_min, - ram_addr_t page_max, ram_addr_t page24, - ram_addr_t cpage) -{ - memory_region_reset_dirty(&ts->vram_mem, - page_min, - (page_max - page_min) + TARGET_PAGE_SIZE, - DIRTY_MEMORY_VGA); - memory_region_reset_dirty(&ts->vram_mem, - page24 + page_min * 4, - (page_max - page_min) * 4 + TARGET_PAGE_SIZE, - DIRTY_MEMORY_VGA); - memory_region_reset_dirty(&ts->vram_mem, - cpage + page_min * 4, - (page_max - page_min) * 4 + TARGET_PAGE_SIZE, - DIRTY_MEMORY_VGA); -} - -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 (surface_bits_per_pixel(surface)) { - default: - case 8: - s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]); - break; - case 15: - s->palette[i] = rgb_to_pixel15(s->r[i], s->g[i], s->b[i]); - break; - case 16: - s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]); - break; - case 32: - if (is_surface_bgr(surface)) { - s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]); - } else { - s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]); - } - break; - } - } - tcx_set_dirty(s); -} - -static void tcx_draw_line32(TCXState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - int x; - uint8_t val; - uint32_t *p = (uint32_t *)d; - - for (x = 0; x < width; x++) { - val = *s++; - *p++ = s1->palette[val]; - } -} - -static void tcx_draw_line16(TCXState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - int x; - uint8_t val; - uint16_t *p = (uint16_t *)d; - - for (x = 0; x < width; x++) { - val = *s++; - *p++ = s1->palette[val]; - } -} - -static void tcx_draw_line8(TCXState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - int x; - uint8_t val; - - for(x = 0; x < width; x++) { - val = *s++; - *d++ = s1->palette[val]; - } -} - -static void tcx_draw_cursor32(TCXState *s1, uint8_t *d, - int y, int width) -{ - int x, len; - uint32_t mask, bits; - uint32_t *p = (uint32_t *)d; - - y = y - s1->cursy; - mask = s1->cursmask[y]; - bits = s1->cursbits[y]; - len = MIN(width - s1->cursx, 32); - p = &p[s1->cursx]; - for (x = 0; x < len; x++) { - if (mask & 0x80000000) { - if (bits & 0x80000000) { - *p = s1->palette[259]; - } else { - *p = s1->palette[258]; - } - } - p++; - mask <<= 1; - bits <<= 1; - } -} - -static void tcx_draw_cursor16(TCXState *s1, uint8_t *d, - int y, int width) -{ - int x, len; - uint32_t mask, bits; - uint16_t *p = (uint16_t *)d; - - y = y - s1->cursy; - mask = s1->cursmask[y]; - bits = s1->cursbits[y]; - len = MIN(width - s1->cursx, 32); - p = &p[s1->cursx]; - for (x = 0; x < len; x++) { - if (mask & 0x80000000) { - if (bits & 0x80000000) { - *p = s1->palette[259]; - } else { - *p = s1->palette[258]; - } - } - p++; - mask <<= 1; - bits <<= 1; - } -} - -static void tcx_draw_cursor8(TCXState *s1, uint8_t *d, - int y, int width) -{ - int x, len; - uint32_t mask, bits; - - y = y - s1->cursy; - mask = s1->cursmask[y]; - bits = s1->cursbits[y]; - len = MIN(width - s1->cursx, 32); - d = &d[s1->cursx]; - for (x = 0; x < len; x++) { - if (mask & 0x80000000) { - if (bits & 0x80000000) { - *d = s1->palette[259]; - } else { - *d = s1->palette[258]; - } - } - d++; - mask <<= 1; - bits <<= 1; - } -} - -/* - XXX Could be much more optimal: - * detect if line/page/whole screen is in 24 bit mode - * if destination is also BGR, use memcpy - */ -static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d, - const uint8_t *s, int width, - 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(surface); - for(x = 0; x < width; x++, s++, s24++) { - if (be32_to_cpu(*cplane) & 0x03000000) { - /* 24-bit direct, BGR order */ - p8 = (uint8_t *)s24; - p8++; - b = *p8++; - g = *p8++; - r = *p8; - if (bgr) - dval = rgb_to_pixel32bgr(r, g, b); - else - dval = rgb_to_pixel32(r, g, b); - } else { - /* 8-bit pseudocolor */ - val = *s; - dval = s1->palette[val]; - } - *p++ = dval; - cplane++; - } -} - -/* Fixed line length 1024 allows us to do nice tricks not possible on - VGA... */ - -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); - void (*fc)(TCXState *s1, uint8_t *dst, int y, int width); - - if (surface_bits_per_pixel(surface) == 0) { - return; - } - - page = 0; - y_start = -1; - page_min = -1; - page_max = 0; - d = surface_data(surface); - s = ts->vram; - dd = surface_stride(surface); - ds = 1024; - - switch (surface_bits_per_pixel(surface)) { - case 32: - f = tcx_draw_line32; - fc = tcx_draw_cursor32; - break; - case 15: - case 16: - f = tcx_draw_line16; - fc = tcx_draw_cursor16; - break; - default: - case 8: - f = tcx_draw_line8; - fc = tcx_draw_cursor8; - break; - case 0: - return; - } - - memory_region_sync_dirty_bitmap(&ts->vram_mem); - for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE) { - if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE, - DIRTY_MEMORY_VGA)) { - if (y_start < 0) - y_start = y; - if (page < page_min) - page_min = page; - if (page > page_max) - page_max = page; - - f(ts, d, s, ts->width); - if (y >= ts->cursy && y < ts->cursy + 32 && ts->cursx < ts->width) { - fc(ts, d, y, ts->width); - } - d += dd; - s += ds; - y++; - - f(ts, d, s, ts->width); - if (y >= ts->cursy && y < ts->cursy + 32 && ts->cursx < ts->width) { - fc(ts, d, y, ts->width); - } - d += dd; - s += ds; - y++; - - f(ts, d, s, ts->width); - if (y >= ts->cursy && y < ts->cursy + 32 && ts->cursx < ts->width) { - fc(ts, d, y, ts->width); - } - d += dd; - s += ds; - y++; - - f(ts, d, s, ts->width); - if (y >= ts->cursy && y < ts->cursy + 32 && ts->cursx < ts->width) { - fc(ts, d, y, ts->width); - } - d += dd; - s += ds; - y++; - } else { - if (y_start >= 0) { - /* flush to display */ - dpy_gfx_update(ts->con, 0, y_start, - ts->width, y - y_start); - y_start = -1; - } - d += dd * 4; - s += ds * 4; - y += 4; - } - } - if (y_start >= 0) { - /* flush to display */ - dpy_gfx_update(ts->con, 0, y_start, - ts->width, y - y_start); - } - /* reset modified pages */ - if (page_max >= page_min) { - memory_region_reset_dirty(&ts->vram_mem, - page_min, - (page_max - page_min) + TARGET_PAGE_SIZE, - DIRTY_MEMORY_VGA); - } -} - -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 (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 = surface_data(surface); - s = ts->vram; - s24 = ts->vram24; - cptr = ts->cplane; - dd = surface_stride(surface); - ds = 1024; - - memory_region_sync_dirty_bitmap(&ts->vram_mem); - for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE, - page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) { - if (tcx24_check_dirty(ts, page, page24, cpage)) { - if (y_start < 0) - y_start = y; - if (page < page_min) - page_min = page; - if (page > page_max) - page_max = page; - tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); - if (y >= ts->cursy && y < ts->cursy+32 && ts->cursx < ts->width) { - tcx_draw_cursor32(ts, d, y, ts->width); - } - d += dd; - s += ds; - cptr += ds; - s24 += ds; - y++; - tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); - if (y >= ts->cursy && y < ts->cursy+32 && ts->cursx < ts->width) { - tcx_draw_cursor32(ts, d, y, ts->width); - } - d += dd; - s += ds; - cptr += ds; - s24 += ds; - y++; - tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); - if (y >= ts->cursy && y < ts->cursy+32 && ts->cursx < ts->width) { - tcx_draw_cursor32(ts, d, y, ts->width); - } - d += dd; - s += ds; - cptr += ds; - s24 += ds; - y++; - tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); - if (y >= ts->cursy && y < ts->cursy+32 && ts->cursx < ts->width) { - tcx_draw_cursor32(ts, d, y, ts->width); - } - d += dd; - s += ds; - cptr += ds; - s24 += ds; - y++; - } else { - if (y_start >= 0) { - /* flush to display */ - dpy_gfx_update(ts->con, 0, y_start, - ts->width, y - y_start); - y_start = -1; - } - d += dd * 4; - s += ds * 4; - cptr += ds * 4; - s24 += ds * 4; - y += 4; - } - } - if (y_start >= 0) { - /* flush to display */ - dpy_gfx_update(ts->con, 0, y_start, - ts->width, y - y_start); - } - /* reset modified pages */ - if (page_max >= page_min) { - tcx24_reset_dirty(ts, page_min, page_max, page24, cpage); - } -} - -static void tcx_invalidate_display(void *opaque) -{ - TCXState *s = opaque; - - tcx_set_dirty(s); - qemu_console_resize(s->con, s->width, s->height); -} - -static void tcx24_invalidate_display(void *opaque) -{ - TCXState *s = opaque; - - tcx_set_dirty(s); - qemu_console_resize(s->con, s->width, s->height); -} - -static int vmstate_tcx_post_load(void *opaque, int version_id) -{ - TCXState *s = opaque; - - update_palette_entries(s, 0, 256); - tcx_set_dirty(s); - return 0; -} - -static const VMStateDescription vmstate_tcx = { - .name ="tcx", - .version_id = 4, - .minimum_version_id = 4, - .post_load = vmstate_tcx_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT16(height, TCXState), - VMSTATE_UINT16(width, TCXState), - VMSTATE_UINT16(depth, TCXState), - VMSTATE_BUFFER(r, TCXState), - VMSTATE_BUFFER(g, TCXState), - VMSTATE_BUFFER(b, TCXState), - VMSTATE_UINT8(dac_index, TCXState), - VMSTATE_UINT8(dac_state, TCXState), - VMSTATE_END_OF_LIST() - } -}; - -static void tcx_reset(DeviceState *d) -{ - TCXState *s = TCX(d); - - /* Initialize palette */ - memset(s->r, 0, 260); - memset(s->g, 0, 260); - memset(s->b, 0, 260); - s->r[255] = s->g[255] = s->b[255] = 255; - s->r[256] = s->g[256] = s->b[256] = 255; - s->r[258] = s->g[258] = s->b[258] = 255; - update_palette_entries(s, 0, 260); - memset(s->vram, 0, MAXX*MAXY); - memory_region_reset_dirty(&s->vram_mem, 0, MAXX * MAXY * (1 + 4 + 4), - DIRTY_MEMORY_VGA); - s->dac_index = 0; - s->dac_state = 0; - s->cursx = 0xf000; /* Put cursor off screen */ - s->cursy = 0xf000; -} - -static uint64_t tcx_dac_readl(void *opaque, hwaddr addr, - unsigned size) -{ - TCXState *s = opaque; - uint32_t val = 0; - - switch (s->dac_state) { - case 0: - val = s->r[s->dac_index] << 24; - s->dac_state++; - break; - case 1: - val = s->g[s->dac_index] << 24; - s->dac_state++; - break; - case 2: - val = s->b[s->dac_index] << 24; - s->dac_index = (s->dac_index + 1) & 0xff; /* Index autoincrement */ - default: - s->dac_state = 0; - break; - } - - return val; -} - -static void tcx_dac_writel(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - TCXState *s = opaque; - unsigned index; - - switch (addr) { - case 0: /* Address */ - s->dac_index = val >> 24; - s->dac_state = 0; - break; - case 4: /* Pixel colours */ - case 12: /* Overlay (cursor) colours */ - if (addr & 8) { - index = (s->dac_index & 3) + 256; - } else { - index = s->dac_index; - } - switch (s->dac_state) { - case 0: - s->r[index] = val >> 24; - update_palette_entries(s, index, index + 1); - s->dac_state++; - break; - case 1: - s->g[index] = val >> 24; - update_palette_entries(s, index, index + 1); - s->dac_state++; - break; - case 2: - s->b[index] = val >> 24; - update_palette_entries(s, index, index + 1); - s->dac_index = (s->dac_index + 1) & 0xff; /* Index autoincrement */ - default: - s->dac_state = 0; - break; - } - break; - default: /* Control registers */ - break; - } -} - -static const MemoryRegionOps tcx_dac_ops = { - .read = tcx_dac_readl, - .write = tcx_dac_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static uint64_t tcx_stip_readl(void *opaque, hwaddr addr, - unsigned size) -{ - return 0; -} - -static void tcx_stip_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - TCXState *s = opaque; - int i; - uint32_t col; - - if (!(addr & 4)) { - s->tmpblit = val; - } else { - addr = (addr >> 3) & 0xfffff; - col = cpu_to_be32(s->tmpblit); - if (s->depth == 24) { - for (i = 0; i < 32; i++) { - if (val & 0x80000000) { - s->vram[addr + i] = s->tmpblit; - s->vram24[addr + i] = col; - } - val <<= 1; - } - } else { - for (i = 0; i < 32; i++) { - if (val & 0x80000000) { - s->vram[addr + i] = s->tmpblit; - } - val <<= 1; - } - } - memory_region_set_dirty(&s->vram_mem, addr, 32); - } -} - -static void tcx_rstip_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - TCXState *s = opaque; - int i; - uint32_t col; - - if (!(addr & 4)) { - s->tmpblit = val; - } else { - addr = (addr >> 3) & 0xfffff; - col = cpu_to_be32(s->tmpblit); - if (s->depth == 24) { - for (i = 0; i < 32; i++) { - if (val & 0x80000000) { - s->vram[addr + i] = s->tmpblit; - s->vram24[addr + i] = col; - s->cplane[addr + i] = col; - } - val <<= 1; - } - } else { - for (i = 0; i < 32; i++) { - if (val & 0x80000000) { - s->vram[addr + i] = s->tmpblit; - } - val <<= 1; - } - } - memory_region_set_dirty(&s->vram_mem, addr, 32); - } -} - -static const MemoryRegionOps tcx_stip_ops = { - .read = tcx_stip_readl, - .write = tcx_stip_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static const MemoryRegionOps tcx_rstip_ops = { - .read = tcx_stip_readl, - .write = tcx_rstip_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static uint64_t tcx_blit_readl(void *opaque, hwaddr addr, - unsigned size) -{ - return 0; -} - -static void tcx_blit_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - TCXState *s = opaque; - uint32_t adsr, len; - int i; - - if (!(addr & 4)) { - s->tmpblit = val; - } else { - addr = (addr >> 3) & 0xfffff; - adsr = val & 0xffffff; - len = ((val >> 24) & 0x1f) + 1; - if (adsr == 0xffffff) { - memset(&s->vram[addr], s->tmpblit, len); - if (s->depth == 24) { - val = s->tmpblit & 0xffffff; - val = cpu_to_be32(val); - for (i = 0; i < len; i++) { - s->vram24[addr + i] = val; - } - } - } else { - memcpy(&s->vram[addr], &s->vram[adsr], len); - if (s->depth == 24) { - memcpy(&s->vram24[addr], &s->vram24[adsr], len * 4); - } - } - memory_region_set_dirty(&s->vram_mem, addr, len); - } -} - -static void tcx_rblit_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - TCXState *s = opaque; - uint32_t adsr, len; - int i; - - if (!(addr & 4)) { - s->tmpblit = val; - } else { - addr = (addr >> 3) & 0xfffff; - adsr = val & 0xffffff; - len = ((val >> 24) & 0x1f) + 1; - if (adsr == 0xffffff) { - memset(&s->vram[addr], s->tmpblit, len); - if (s->depth == 24) { - val = s->tmpblit & 0xffffff; - val = cpu_to_be32(val); - for (i = 0; i < len; i++) { - s->vram24[addr + i] = val; - s->cplane[addr + i] = val; - } - } - } else { - memcpy(&s->vram[addr], &s->vram[adsr], len); - if (s->depth == 24) { - memcpy(&s->vram24[addr], &s->vram24[adsr], len * 4); - memcpy(&s->cplane[addr], &s->cplane[adsr], len * 4); - } - } - memory_region_set_dirty(&s->vram_mem, addr, len); - } -} - -static const MemoryRegionOps tcx_blit_ops = { - .read = tcx_blit_readl, - .write = tcx_blit_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static const MemoryRegionOps tcx_rblit_ops = { - .read = tcx_blit_readl, - .write = tcx_rblit_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static void tcx_invalidate_cursor_position(TCXState *s) -{ - int ymin, ymax, start, end; - - /* invalidate only near the cursor */ - ymin = s->cursy; - if (ymin >= s->height) { - return; - } - ymax = MIN(s->height, ymin + 32); - start = ymin * 1024; - end = ymax * 1024; - - memory_region_set_dirty(&s->vram_mem, start, end-start); -} - -static uint64_t tcx_thc_readl(void *opaque, hwaddr addr, - unsigned size) -{ - TCXState *s = opaque; - uint64_t val; - - if (addr == TCX_THC_MISC) { - val = s->thcmisc | 0x02000000; - } else { - val = 0; - } - return val; -} - -static void tcx_thc_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - TCXState *s = opaque; - - if (addr == TCX_THC_CURSXY) { - tcx_invalidate_cursor_position(s); - s->cursx = val >> 16; - s->cursy = val; - tcx_invalidate_cursor_position(s); - } else if (addr >= TCX_THC_CURSMASK && addr < TCX_THC_CURSMASK + 128) { - s->cursmask[(addr - TCX_THC_CURSMASK) >> 2] = val; - tcx_invalidate_cursor_position(s); - } else if (addr >= TCX_THC_CURSBITS && addr < TCX_THC_CURSBITS + 128) { - s->cursbits[(addr - TCX_THC_CURSBITS) >> 2] = val; - tcx_invalidate_cursor_position(s); - } else if (addr == TCX_THC_MISC) { - s->thcmisc = val; - } - -} - -static const MemoryRegionOps tcx_thc_ops = { - .read = tcx_thc_readl, - .write = tcx_thc_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static uint64_t tcx_dummy_readl(void *opaque, hwaddr addr, - unsigned size) -{ - return 0; -} - -static void tcx_dummy_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - return; -} - -static const MemoryRegionOps tcx_dummy_ops = { - .read = tcx_dummy_readl, - .write = tcx_dummy_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static const GraphicHwOps tcx_ops = { - .invalidate = tcx_invalidate_display, - .gfx_update = tcx_update_display, -}; - -static const GraphicHwOps tcx24_ops = { - .invalidate = tcx24_invalidate_display, - .gfx_update = tcx24_update_display, -}; - -static void tcx_initfn(Object *obj) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - TCXState *s = TCX(obj); - - memory_region_init_ram(&s->rom, obj, "tcx.prom", FCODE_MAX_ROM_SIZE, - &error_fatal); - memory_region_set_readonly(&s->rom, true); - sysbus_init_mmio(sbd, &s->rom); - - /* 2/STIP : Stippler */ - memory_region_init_io(&s->stip, obj, &tcx_stip_ops, s, "tcx.stip", - TCX_STIP_NREGS); - sysbus_init_mmio(sbd, &s->stip); - - /* 3/BLIT : Blitter */ - memory_region_init_io(&s->blit, obj, &tcx_blit_ops, s, "tcx.blit", - TCX_BLIT_NREGS); - sysbus_init_mmio(sbd, &s->blit); - - /* 5/RSTIP : Raw Stippler */ - memory_region_init_io(&s->rstip, obj, &tcx_rstip_ops, s, "tcx.rstip", - TCX_RSTIP_NREGS); - sysbus_init_mmio(sbd, &s->rstip); - - /* 6/RBLIT : Raw Blitter */ - memory_region_init_io(&s->rblit, obj, &tcx_rblit_ops, s, "tcx.rblit", - TCX_RBLIT_NREGS); - sysbus_init_mmio(sbd, &s->rblit); - - /* 7/TEC : ??? */ - memory_region_init_io(&s->tec, obj, &tcx_dummy_ops, s, "tcx.tec", - TCX_TEC_NREGS); - sysbus_init_mmio(sbd, &s->tec); - - /* 8/CMAP : DAC */ - memory_region_init_io(&s->dac, obj, &tcx_dac_ops, s, "tcx.dac", - TCX_DAC_NREGS); - sysbus_init_mmio(sbd, &s->dac); - - /* 9/THC : Cursor */ - memory_region_init_io(&s->thc, obj, &tcx_thc_ops, s, "tcx.thc", - TCX_THC_NREGS); - sysbus_init_mmio(sbd, &s->thc); - - /* 11/DHC : ??? */ - memory_region_init_io(&s->dhc, obj, &tcx_dummy_ops, s, "tcx.dhc", - TCX_DHC_NREGS); - sysbus_init_mmio(sbd, &s->dhc); - - /* 12/ALT : ??? */ - memory_region_init_io(&s->alt, obj, &tcx_dummy_ops, s, "tcx.alt", - TCX_ALT_NREGS); - sysbus_init_mmio(sbd, &s->alt); -} - -static void tcx_realizefn(DeviceState *dev, Error **errp) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - TCXState *s = TCX(dev); - ram_addr_t vram_offset = 0; - int size, ret; - uint8_t *vram_base; - char *fcode_filename; - - memory_region_init_ram(&s->vram_mem, OBJECT(s), "tcx.vram", - s->vram_size * (1 + 4 + 4), &error_fatal); - vmstate_register_ram_global(&s->vram_mem); - memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA); - vram_base = memory_region_get_ram_ptr(&s->vram_mem); - - /* 10/ROM : FCode ROM */ - vmstate_register_ram_global(&s->rom); - fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, TCX_ROM_FILE); - if (fcode_filename) { - ret = load_image_targphys(fcode_filename, s->prom_addr, - FCODE_MAX_ROM_SIZE); - g_free(fcode_filename); - if (ret < 0 || ret > FCODE_MAX_ROM_SIZE) { - error_report("tcx: could not load prom '%s'", TCX_ROM_FILE); - } - } - - /* 0/DFB8 : 8-bit plane */ - s->vram = vram_base; - size = s->vram_size; - memory_region_init_alias(&s->vram_8bit, OBJECT(s), "tcx.vram.8bit", - &s->vram_mem, vram_offset, size); - sysbus_init_mmio(sbd, &s->vram_8bit); - vram_offset += size; - vram_base += size; - - /* 1/DFB24 : 24bit plane */ - size = s->vram_size * 4; - s->vram24 = (uint32_t *)vram_base; - s->vram24_offset = vram_offset; - memory_region_init_alias(&s->vram_24bit, OBJECT(s), "tcx.vram.24bit", - &s->vram_mem, vram_offset, size); - sysbus_init_mmio(sbd, &s->vram_24bit); - vram_offset += size; - vram_base += size; - - /* 4/RDFB32 : Raw Framebuffer */ - size = s->vram_size * 4; - s->cplane = (uint32_t *)vram_base; - s->cplane_offset = vram_offset; - memory_region_init_alias(&s->vram_cplane, OBJECT(s), "tcx.vram.cplane", - &s->vram_mem, vram_offset, size); - sysbus_init_mmio(sbd, &s->vram_cplane); - - /* 9/THC24bits : NetBSD writes here even with 8-bit display: dummy */ - if (s->depth == 8) { - memory_region_init_io(&s->thc24, OBJECT(s), &tcx_dummy_ops, s, - "tcx.thc24", TCX_THC_NREGS); - sysbus_init_mmio(sbd, &s->thc24); - } - - sysbus_init_irq(sbd, &s->irq); - - if (s->depth == 8) { - s->con = graphic_console_init(DEVICE(dev), 0, &tcx_ops, s); - } else { - s->con = graphic_console_init(DEVICE(dev), 0, &tcx24_ops, s); - } - s->thcmisc = 0; - - qemu_console_resize(s->con, s->width, s->height); -} - -static Property tcx_properties[] = { - DEFINE_PROP_UINT32("vram_size", TCXState, vram_size, -1), - DEFINE_PROP_UINT16("width", TCXState, width, -1), - DEFINE_PROP_UINT16("height", TCXState, height, -1), - DEFINE_PROP_UINT16("depth", TCXState, depth, -1), - DEFINE_PROP_UINT64("prom_addr", TCXState, prom_addr, -1), - DEFINE_PROP_END_OF_LIST(), -}; - -static void tcx_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = tcx_realizefn; - dc->reset = tcx_reset; - dc->vmsd = &vmstate_tcx; - dc->props = tcx_properties; -} - -static const TypeInfo tcx_info = { - .name = TYPE_TCX, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(TCXState), - .instance_init = tcx_initfn, - .class_init = tcx_class_init, -}; - -static void tcx_register_types(void) -{ - type_register_static(&tcx_info); -} - -type_init(tcx_register_types) diff --git a/qemu/hw/display/vga-helpers.h b/qemu/hw/display/vga-helpers.h deleted file mode 100644 index 94f6de204..000000000 --- a/qemu/hw/display/vga-helpers.h +++ /dev/null @@ -1,439 +0,0 @@ -/* - * QEMU VGA Emulator templates - * - * Copyright (c) 2003 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -static inline void vga_draw_glyph_line(uint8_t *d, uint32_t font_data, - uint32_t xorcol, uint32_t bgcol) -{ - ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; - ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; -} - -static void vga_draw_glyph8(uint8_t *d, int linesize, - const uint8_t *font_ptr, int h, - uint32_t fgcol, uint32_t bgcol) -{ - uint32_t font_data, xorcol; - - xorcol = bgcol ^ fgcol; - do { - font_data = font_ptr[0]; - vga_draw_glyph_line(d, font_data, xorcol, bgcol); - font_ptr += 4; - d += linesize; - } while (--h); -} - -static void vga_draw_glyph16(uint8_t *d, int linesize, - const uint8_t *font_ptr, int h, - uint32_t fgcol, uint32_t bgcol) -{ - uint32_t font_data, xorcol; - - xorcol = bgcol ^ fgcol; - do { - font_data = font_ptr[0]; - vga_draw_glyph_line(d, expand4to8[font_data >> 4], - xorcol, bgcol); - vga_draw_glyph_line(d + 32, expand4to8[font_data & 0x0f], - xorcol, bgcol); - font_ptr += 4; - d += linesize; - } while (--h); -} - -static void vga_draw_glyph9(uint8_t *d, int linesize, - const uint8_t *font_ptr, int h, - uint32_t fgcol, uint32_t bgcol, int dup9) -{ - uint32_t font_data, xorcol, v; - - xorcol = bgcol ^ fgcol; - do { - font_data = font_ptr[0]; - ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; - ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; - v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[7] = v; - if (dup9) - ((uint32_t *)d)[8] = v; - else - ((uint32_t *)d)[8] = bgcol; - font_ptr += 4; - d += linesize; - } while (--h); -} - -/* - * 4 color mode - */ -static void vga_draw_line2(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - uint32_t plane_mask, *palette, data, v; - int x; - - palette = s1->last_palette; - plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; - width >>= 3; - for(x = 0; x < width; x++) { - data = ((uint32_t *)s)[0]; - data &= plane_mask; - v = expand2[GET_PLANE(data, 0)]; - v |= expand2[GET_PLANE(data, 2)] << 2; - ((uint32_t *)d)[0] = palette[v >> 12]; - ((uint32_t *)d)[1] = palette[(v >> 8) & 0xf]; - ((uint32_t *)d)[2] = palette[(v >> 4) & 0xf]; - ((uint32_t *)d)[3] = palette[(v >> 0) & 0xf]; - - v = expand2[GET_PLANE(data, 1)]; - v |= expand2[GET_PLANE(data, 3)] << 2; - ((uint32_t *)d)[4] = palette[v >> 12]; - ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf]; - ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; - ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; - d += 32; - s += 4; - } -} - -#define PUT_PIXEL2(d, n, v) \ -((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v) - -/* - * 4 color mode, dup2 horizontal - */ -static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - uint32_t plane_mask, *palette, data, v; - int x; - - palette = s1->last_palette; - plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; - width >>= 3; - for(x = 0; x < width; x++) { - data = ((uint32_t *)s)[0]; - data &= plane_mask; - v = expand2[GET_PLANE(data, 0)]; - v |= expand2[GET_PLANE(data, 2)] << 2; - PUT_PIXEL2(d, 0, palette[v >> 12]); - PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]); - PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]); - PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]); - - v = expand2[GET_PLANE(data, 1)]; - v |= expand2[GET_PLANE(data, 3)] << 2; - PUT_PIXEL2(d, 4, palette[v >> 12]); - PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); - PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); - PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); - d += 64; - s += 4; - } -} - -/* - * 16 color mode - */ -static void vga_draw_line4(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - uint32_t plane_mask, data, v, *palette; - int x; - - palette = s1->last_palette; - plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; - width >>= 3; - for(x = 0; x < width; x++) { - data = ((uint32_t *)s)[0]; - data &= plane_mask; - v = expand4[GET_PLANE(data, 0)]; - v |= expand4[GET_PLANE(data, 1)] << 1; - v |= expand4[GET_PLANE(data, 2)] << 2; - v |= expand4[GET_PLANE(data, 3)] << 3; - ((uint32_t *)d)[0] = palette[v >> 28]; - ((uint32_t *)d)[1] = palette[(v >> 24) & 0xf]; - ((uint32_t *)d)[2] = palette[(v >> 20) & 0xf]; - ((uint32_t *)d)[3] = palette[(v >> 16) & 0xf]; - ((uint32_t *)d)[4] = palette[(v >> 12) & 0xf]; - ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf]; - ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; - ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; - d += 32; - s += 4; - } -} - -/* - * 16 color mode, dup2 horizontal - */ -static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - uint32_t plane_mask, data, v, *palette; - int x; - - palette = s1->last_palette; - plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; - width >>= 3; - for(x = 0; x < width; x++) { - data = ((uint32_t *)s)[0]; - data &= plane_mask; - v = expand4[GET_PLANE(data, 0)]; - v |= expand4[GET_PLANE(data, 1)] << 1; - v |= expand4[GET_PLANE(data, 2)] << 2; - v |= expand4[GET_PLANE(data, 3)] << 3; - PUT_PIXEL2(d, 0, palette[v >> 28]); - PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]); - PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]); - PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]); - PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]); - PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); - PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); - PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); - d += 64; - s += 4; - } -} - -/* - * 256 color mode, double pixels - * - * XXX: add plane_mask support (never used in standard VGA modes) - */ -static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - uint32_t *palette; - int x; - - palette = s1->last_palette; - width >>= 3; - for(x = 0; x < width; x++) { - PUT_PIXEL2(d, 0, palette[s[0]]); - PUT_PIXEL2(d, 1, palette[s[1]]); - PUT_PIXEL2(d, 2, palette[s[2]]); - PUT_PIXEL2(d, 3, palette[s[3]]); - d += 32; - s += 4; - } -} - -/* - * standard 256 color mode - * - * XXX: add plane_mask support (never used in standard VGA modes) - */ -static void vga_draw_line8(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - uint32_t *palette; - int x; - - palette = s1->last_palette; - width >>= 3; - for(x = 0; x < width; x++) { - ((uint32_t *)d)[0] = palette[s[0]]; - ((uint32_t *)d)[1] = palette[s[1]]; - ((uint32_t *)d)[2] = palette[s[2]]; - ((uint32_t *)d)[3] = palette[s[3]]; - ((uint32_t *)d)[4] = palette[s[4]]; - ((uint32_t *)d)[5] = palette[s[5]]; - ((uint32_t *)d)[6] = palette[s[6]]; - ((uint32_t *)d)[7] = palette[s[7]]; - d += 32; - s += 8; - } -} - -/* - * 15 bit color - */ -static void vga_draw_line15_le(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - int w; - uint32_t v, r, g, b; - - w = width; - do { - v = lduw_le_p((void *)s); - r = (v >> 7) & 0xf8; - g = (v >> 2) & 0xf8; - b = (v << 3) & 0xf8; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 2; - d += 4; - } while (--w != 0); -} - -static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - int w; - uint32_t v, r, g, b; - - w = width; - do { - v = lduw_be_p((void *)s); - r = (v >> 7) & 0xf8; - g = (v >> 2) & 0xf8; - b = (v << 3) & 0xf8; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 2; - d += 4; - } while (--w != 0); -} - -/* - * 16 bit color - */ -static void vga_draw_line16_le(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - int w; - uint32_t v, r, g, b; - - w = width; - do { - v = lduw_le_p((void *)s); - r = (v >> 8) & 0xf8; - g = (v >> 3) & 0xfc; - b = (v << 3) & 0xf8; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 2; - d += 4; - } while (--w != 0); -} - -static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - int w; - uint32_t v, r, g, b; - - w = width; - do { - v = lduw_be_p((void *)s); - r = (v >> 8) & 0xf8; - g = (v >> 3) & 0xfc; - b = (v << 3) & 0xf8; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 2; - d += 4; - } while (--w != 0); -} - -/* - * 24 bit color - */ -static void vga_draw_line24_le(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - int w; - uint32_t r, g, b; - - w = width; - do { - b = s[0]; - g = s[1]; - r = s[2]; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 3; - d += 4; - } while (--w != 0); -} - -static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - int w; - uint32_t r, g, b; - - w = width; - do { - r = s[0]; - g = s[1]; - b = s[2]; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 3; - d += 4; - } while (--w != 0); -} - -/* - * 32 bit color - */ -static void vga_draw_line32_le(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ -#ifndef HOST_WORDS_BIGENDIAN - memcpy(d, s, width * 4); -#else - int w; - uint32_t r, g, b; - - w = width; - do { - b = s[0]; - g = s[1]; - r = s[2]; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 4; - d += 4; - } while (--w != 0); -#endif -} - -static void vga_draw_line32_be(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) -{ -#ifdef HOST_WORDS_BIGENDIAN - memcpy(d, s, width * 4); -#else - int w; - uint32_t r, g, b; - - w = width; - do { - r = s[1]; - g = s[2]; - b = s[3]; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 4; - d += 4; - } while (--w != 0); -#endif -} diff --git a/qemu/hw/display/vga-isa-mm.c b/qemu/hw/display/vga-isa-mm.c deleted file mode 100644 index 51ccbccc4..000000000 --- a/qemu/hw/display/vga-isa-mm.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * QEMU ISA MM VGA Emulator. - * - * Copyright (c) 2003 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "ui/console.h" -#include "hw/i386/pc.h" -#include "vga_int.h" -#include "ui/pixel_ops.h" -#include "qemu/timer.h" - -#define VGA_RAM_SIZE (8192 * 1024) - -typedef struct ISAVGAMMState { - VGACommonState vga; - int it_shift; -} ISAVGAMMState; - -/* Memory mapped interface */ -static uint32_t vga_mm_readb (void *opaque, hwaddr addr) -{ - ISAVGAMMState *s = opaque; - - return vga_ioport_read(&s->vga, addr >> s->it_shift) & 0xff; -} - -static void vga_mm_writeb (void *opaque, - hwaddr addr, uint32_t value) -{ - ISAVGAMMState *s = opaque; - - vga_ioport_write(&s->vga, addr >> s->it_shift, value & 0xff); -} - -static uint32_t vga_mm_readw (void *opaque, hwaddr addr) -{ - ISAVGAMMState *s = opaque; - - return vga_ioport_read(&s->vga, addr >> s->it_shift) & 0xffff; -} - -static void vga_mm_writew (void *opaque, - hwaddr addr, uint32_t value) -{ - ISAVGAMMState *s = opaque; - - vga_ioport_write(&s->vga, addr >> s->it_shift, value & 0xffff); -} - -static uint32_t vga_mm_readl (void *opaque, hwaddr addr) -{ - ISAVGAMMState *s = opaque; - - return vga_ioport_read(&s->vga, addr >> s->it_shift); -} - -static void vga_mm_writel (void *opaque, - hwaddr addr, uint32_t value) -{ - ISAVGAMMState *s = opaque; - - vga_ioport_write(&s->vga, addr >> s->it_shift, value); -} - -static const MemoryRegionOps vga_mm_ctrl_ops = { - .old_mmio = { - .read = { - vga_mm_readb, - vga_mm_readw, - vga_mm_readl, - }, - .write = { - vga_mm_writeb, - vga_mm_writew, - vga_mm_writel, - }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void vga_mm_init(ISAVGAMMState *s, hwaddr vram_base, - hwaddr ctrl_base, int it_shift, - MemoryRegion *address_space) -{ - MemoryRegion *s_ioport_ctrl, *vga_io_memory; - - s->it_shift = it_shift; - s_ioport_ctrl = g_malloc(sizeof(*s_ioport_ctrl)); - memory_region_init_io(s_ioport_ctrl, NULL, &vga_mm_ctrl_ops, s, - "vga-mm-ctrl", 0x100000); - memory_region_set_flush_coalesced(s_ioport_ctrl); - - vga_io_memory = g_malloc(sizeof(*vga_io_memory)); - /* XXX: endianness? */ - memory_region_init_io(vga_io_memory, NULL, &vga_mem_ops, &s->vga, - "vga-mem", 0x20000); - - vmstate_register(NULL, 0, &vmstate_vga_common, s); - - memory_region_add_subregion(address_space, ctrl_base, s_ioport_ctrl); - s->vga.bank_offset = 0; - memory_region_add_subregion(address_space, - vram_base + 0x000a0000, vga_io_memory); - memory_region_set_coalescing(vga_io_memory); -} - -int isa_vga_mm_init(hwaddr vram_base, - hwaddr ctrl_base, int it_shift, - MemoryRegion *address_space) -{ - ISAVGAMMState *s; - - s = g_malloc0(sizeof(*s)); - - s->vga.vram_size_mb = VGA_RAM_SIZE >> 20; - vga_common_init(&s->vga, NULL, true); - vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space); - - s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s); - - vga_init_vbe(&s->vga, NULL, address_space); - return 0; -} diff --git a/qemu/hw/display/vga-isa.c b/qemu/hw/display/vga-isa.c deleted file mode 100644 index f5aff1cbe..000000000 --- a/qemu/hw/display/vga-isa.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * QEMU ISA VGA Emulator. - * - * see docs/specs/standard-vga.txt for virtual hardware specs. - * - * Copyright (c) 2003 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "ui/console.h" -#include "hw/i386/pc.h" -#include "vga_int.h" -#include "ui/pixel_ops.h" -#include "qemu/timer.h" -#include "hw/loader.h" - -#define TYPE_ISA_VGA "isa-vga" -#define ISA_VGA(obj) OBJECT_CHECK(ISAVGAState, (obj), TYPE_ISA_VGA) - -typedef struct ISAVGAState { - ISADevice parent_obj; - - struct VGACommonState state; -} ISAVGAState; - -static void vga_isa_reset(DeviceState *dev) -{ - ISAVGAState *d = ISA_VGA(dev); - VGACommonState *s = &d->state; - - vga_common_reset(s); -} - -static void vga_isa_realizefn(DeviceState *dev, Error **errp) -{ - ISADevice *isadev = ISA_DEVICE(dev); - ISAVGAState *d = ISA_VGA(dev); - VGACommonState *s = &d->state; - MemoryRegion *vga_io_memory; - const MemoryRegionPortio *vga_ports, *vbe_ports; - - vga_common_init(s, OBJECT(dev), true); - s->legacy_address_space = isa_address_space(isadev); - vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports); - isa_register_portio_list(isadev, 0x3b0, vga_ports, s, "vga"); - if (vbe_ports) { - isa_register_portio_list(isadev, 0x1ce, vbe_ports, s, "vbe"); - } - memory_region_add_subregion_overlap(isa_address_space(isadev), - 0x000a0000, - vga_io_memory, 1); - memory_region_set_coalescing(vga_io_memory); - s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s); - - vga_init_vbe(s, OBJECT(dev), isa_address_space(isadev)); - /* ROM BIOS */ - rom_add_vga(VGABIOS_FILENAME); -} - -static Property vga_isa_properties[] = { - DEFINE_PROP_UINT32("vgamem_mb", ISAVGAState, state.vram_size_mb, 8), - DEFINE_PROP_END_OF_LIST(), -}; - -static void vga_isa_class_initfn(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = vga_isa_realizefn; - dc->reset = vga_isa_reset; - dc->vmsd = &vmstate_vga_common; - dc->props = vga_isa_properties; - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); -} - -static const TypeInfo vga_isa_info = { - .name = TYPE_ISA_VGA, - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(ISAVGAState), - .class_init = vga_isa_class_initfn, -}; - -static void vga_isa_register_types(void) -{ - type_register_static(&vga_isa_info); -} - -type_init(vga_isa_register_types) diff --git a/qemu/hw/display/vga-pci.c b/qemu/hw/display/vga-pci.c deleted file mode 100644 index ac9a76499..000000000 --- a/qemu/hw/display/vga-pci.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * QEMU PCI VGA Emulator. - * - * see docs/specs/standard-vga.txt for virtual hardware specs. - * - * Copyright (c) 2003 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "ui/console.h" -#include "hw/pci/pci.h" -#include "vga_int.h" -#include "ui/pixel_ops.h" -#include "qemu/timer.h" -#include "hw/loader.h" - -#define PCI_VGA_IOPORT_OFFSET 0x400 -#define PCI_VGA_IOPORT_SIZE (0x3e0 - 0x3c0) -#define PCI_VGA_BOCHS_OFFSET 0x500 -#define PCI_VGA_BOCHS_SIZE (0x0b * 2) -#define PCI_VGA_QEXT_OFFSET 0x600 -#define PCI_VGA_QEXT_SIZE (2 * 4) -#define PCI_VGA_MMIO_SIZE 0x1000 - -#define PCI_VGA_QEXT_REG_SIZE (0 * 4) -#define PCI_VGA_QEXT_REG_BYTEORDER (1 * 4) -#define PCI_VGA_QEXT_LITTLE_ENDIAN 0x1e1e1e1e -#define PCI_VGA_QEXT_BIG_ENDIAN 0xbebebebe - -enum vga_pci_flags { - PCI_VGA_FLAG_ENABLE_MMIO = 1, - PCI_VGA_FLAG_ENABLE_QEXT = 2, -}; - -typedef struct PCIVGAState { - PCIDevice dev; - VGACommonState vga; - uint32_t flags; - MemoryRegion mmio; - MemoryRegion mrs[3]; -} PCIVGAState; - -#define TYPE_PCI_VGA "pci-vga" -#define PCI_VGA(obj) OBJECT_CHECK(PCIVGAState, (obj), TYPE_PCI_VGA) - -static const VMStateDescription vmstate_vga_pci = { - .name = "vga", - .version_id = 2, - .minimum_version_id = 2, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(dev, PCIVGAState), - VMSTATE_STRUCT(vga, PCIVGAState, 0, vmstate_vga_common, VGACommonState), - VMSTATE_END_OF_LIST() - } -}; - -static uint64_t pci_vga_ioport_read(void *ptr, hwaddr addr, - unsigned size) -{ - VGACommonState *s = ptr; - uint64_t ret = 0; - - switch (size) { - case 1: - ret = vga_ioport_read(s, addr + 0x3c0); - break; - case 2: - ret = vga_ioport_read(s, addr + 0x3c0); - ret |= vga_ioport_read(s, addr + 0x3c1) << 8; - break; - } - return ret; -} - -static void pci_vga_ioport_write(void *ptr, hwaddr addr, - uint64_t val, unsigned size) -{ - VGACommonState *s = ptr; - - switch (size) { - case 1: - vga_ioport_write(s, addr + 0x3c0, val); - break; - case 2: - /* - * Update bytes in little endian order. Allows to update - * indexed registers with a single word write because the - * index byte is updated first. - */ - vga_ioport_write(s, addr + 0x3c0, val & 0xff); - vga_ioport_write(s, addr + 0x3c1, (val >> 8) & 0xff); - break; - } -} - -static const MemoryRegionOps pci_vga_ioport_ops = { - .read = pci_vga_ioport_read, - .write = pci_vga_ioport_write, - .valid.min_access_size = 1, - .valid.max_access_size = 4, - .impl.min_access_size = 1, - .impl.max_access_size = 2, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static uint64_t pci_vga_bochs_read(void *ptr, hwaddr addr, - unsigned size) -{ - VGACommonState *s = ptr; - int index = addr >> 1; - - vbe_ioport_write_index(s, 0, index); - return vbe_ioport_read_data(s, 0); -} - -static void pci_vga_bochs_write(void *ptr, hwaddr addr, - uint64_t val, unsigned size) -{ - VGACommonState *s = ptr; - int index = addr >> 1; - - vbe_ioport_write_index(s, 0, index); - vbe_ioport_write_data(s, 0, val); -} - -static const MemoryRegionOps pci_vga_bochs_ops = { - .read = pci_vga_bochs_read, - .write = pci_vga_bochs_write, - .valid.min_access_size = 1, - .valid.max_access_size = 4, - .impl.min_access_size = 2, - .impl.max_access_size = 2, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static uint64_t pci_vga_qext_read(void *ptr, hwaddr addr, unsigned size) -{ - VGACommonState *s = ptr; - - switch (addr) { - case PCI_VGA_QEXT_REG_SIZE: - return PCI_VGA_QEXT_SIZE; - case PCI_VGA_QEXT_REG_BYTEORDER: - return s->big_endian_fb ? - PCI_VGA_QEXT_BIG_ENDIAN : PCI_VGA_QEXT_LITTLE_ENDIAN; - default: - return 0; - } -} - -static void pci_vga_qext_write(void *ptr, hwaddr addr, - uint64_t val, unsigned size) -{ - VGACommonState *s = ptr; - - switch (addr) { - case PCI_VGA_QEXT_REG_BYTEORDER: - if (val == PCI_VGA_QEXT_BIG_ENDIAN) { - s->big_endian_fb = true; - } - if (val == PCI_VGA_QEXT_LITTLE_ENDIAN) { - s->big_endian_fb = false; - } - break; - } -} - -static bool vga_get_big_endian_fb(Object *obj, Error **errp) -{ - PCIVGAState *d = PCI_VGA(PCI_DEVICE(obj)); - - return d->vga.big_endian_fb; -} - -static void vga_set_big_endian_fb(Object *obj, bool value, Error **errp) -{ - PCIVGAState *d = PCI_VGA(PCI_DEVICE(obj)); - - d->vga.big_endian_fb = value; -} - -static const MemoryRegionOps pci_vga_qext_ops = { - .read = pci_vga_qext_read, - .write = pci_vga_qext_write, - .valid.min_access_size = 4, - .valid.max_access_size = 4, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -void pci_std_vga_mmio_region_init(VGACommonState *s, - MemoryRegion *parent, - MemoryRegion *subs, - bool qext) -{ - memory_region_init_io(&subs[0], NULL, &pci_vga_ioport_ops, s, - "vga ioports remapped", PCI_VGA_IOPORT_SIZE); - memory_region_add_subregion(parent, PCI_VGA_IOPORT_OFFSET, - &subs[0]); - - memory_region_init_io(&subs[1], NULL, &pci_vga_bochs_ops, s, - "bochs dispi interface", PCI_VGA_BOCHS_SIZE); - memory_region_add_subregion(parent, PCI_VGA_BOCHS_OFFSET, - &subs[1]); - - if (qext) { - memory_region_init_io(&subs[2], NULL, &pci_vga_qext_ops, s, - "qemu extended regs", PCI_VGA_QEXT_SIZE); - memory_region_add_subregion(parent, PCI_VGA_QEXT_OFFSET, - &subs[2]); - } -} - -static void pci_std_vga_realize(PCIDevice *dev, Error **errp) -{ - PCIVGAState *d = PCI_VGA(dev); - VGACommonState *s = &d->vga; - bool qext = false; - - /* vga + console init */ - vga_common_init(s, OBJECT(dev), true); - vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev), - true); - - s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s); - - /* XXX: VGA_RAM_SIZE must be a power of two */ - pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); - - /* mmio bar for vga register access */ - if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_MMIO)) { - memory_region_init(&d->mmio, NULL, "vga.mmio", 4096); - - if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_QEXT)) { - qext = true; - pci_set_byte(&d->dev.config[PCI_REVISION_ID], 2); - } - pci_std_vga_mmio_region_init(s, &d->mmio, d->mrs, qext); - - pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); - } - - if (!dev->rom_bar) { - /* compatibility with pc-0.13 and older */ - vga_init_vbe(s, OBJECT(dev), pci_address_space(dev)); - } -} - -static void pci_std_vga_init(Object *obj) -{ - /* Expose framebuffer byteorder via QOM */ - object_property_add_bool(obj, "big-endian-framebuffer", - vga_get_big_endian_fb, vga_set_big_endian_fb, NULL); -} - -static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp) -{ - PCIVGAState *d = PCI_VGA(dev); - VGACommonState *s = &d->vga; - bool qext = false; - - /* vga + console init */ - vga_common_init(s, OBJECT(dev), false); - s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s); - - /* mmio bar */ - memory_region_init(&d->mmio, OBJECT(dev), "vga.mmio", 4096); - - if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_QEXT)) { - qext = true; - pci_set_byte(&d->dev.config[PCI_REVISION_ID], 2); - } - pci_std_vga_mmio_region_init(s, &d->mmio, d->mrs, qext); - - pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); - pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); -} - -static void pci_secondary_vga_init(Object *obj) -{ - /* Expose framebuffer byteorder via QOM */ - object_property_add_bool(obj, "big-endian-framebuffer", - vga_get_big_endian_fb, vga_set_big_endian_fb, NULL); -} - -static void pci_secondary_vga_reset(DeviceState *dev) -{ - PCIVGAState *d = PCI_VGA(PCI_DEVICE(dev)); - vga_common_reset(&d->vga); -} - -static Property vga_pci_properties[] = { - DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16), - DEFINE_PROP_BIT("mmio", PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_MMIO, true), - DEFINE_PROP_BIT("qemu-extended-regs", - PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_QEXT, true), - DEFINE_PROP_END_OF_LIST(), -}; - -static Property secondary_pci_properties[] = { - DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16), - DEFINE_PROP_BIT("qemu-extended-regs", - PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_QEXT, true), - DEFINE_PROP_END_OF_LIST(), -}; - -static void vga_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->vendor_id = PCI_VENDOR_ID_QEMU; - k->device_id = PCI_DEVICE_ID_QEMU_VGA; - dc->vmsd = &vmstate_vga_pci; - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); -} - -static const TypeInfo vga_pci_type_info = { - .name = TYPE_PCI_VGA, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIVGAState), - .abstract = true, - .class_init = vga_pci_class_init, -}; - -static void vga_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = pci_std_vga_realize; - k->romfile = "vgabios-stdvga.bin"; - k->class_id = PCI_CLASS_DISPLAY_VGA; - dc->props = vga_pci_properties; - dc->hotpluggable = false; -} - -static void secondary_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = pci_secondary_vga_realize; - k->class_id = PCI_CLASS_DISPLAY_OTHER; - dc->props = secondary_pci_properties; - dc->reset = pci_secondary_vga_reset; -} - -static const TypeInfo vga_info = { - .name = "VGA", - .parent = TYPE_PCI_VGA, - .instance_init = pci_std_vga_init, - .class_init = vga_class_init, -}; - -static const TypeInfo secondary_info = { - .name = "secondary-vga", - .parent = TYPE_PCI_VGA, - .instance_init = pci_secondary_vga_init, - .class_init = secondary_class_init, -}; - -static void vga_register_types(void) -{ - type_register_static(&vga_pci_type_info); - type_register_static(&vga_info); - type_register_static(&secondary_info); -} - -type_init(vga_register_types) diff --git a/qemu/hw/display/vga.c b/qemu/hw/display/vga.c deleted file mode 100644 index 4a55ec6db..000000000 --- a/qemu/hw/display/vga.c +++ /dev/null @@ -1,2289 +0,0 @@ -/* - * QEMU VGA Emulator. - * - * Copyright (c) 2003 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "hw/hw.h" -#include "vga.h" -#include "ui/console.h" -#include "hw/i386/pc.h" -#include "hw/pci/pci.h" -#include "vga_int.h" -#include "ui/pixel_ops.h" -#include "qemu/timer.h" -#include "hw/xen/xen.h" -#include "trace.h" - -//#define DEBUG_VGA -//#define DEBUG_VGA_MEM -//#define DEBUG_VGA_REG - -//#define DEBUG_BOCHS_VBE - -/* 16 state changes per vertical frame @60 Hz */ -#define VGA_TEXT_CURSOR_PERIOD_MS (1000 * 2 * 16 / 60) - -/* - * Video Graphics Array (VGA) - * - * Chipset docs for original IBM VGA: - * http://www.mcamafia.de/pdf/ibm_vgaxga_trm2.pdf - * - * FreeVGA site: - * http://www.osdever.net/FreeVGA/home.htm - * - * Standard VGA features and Bochs VBE extensions are implemented. - */ - -/* force some bits to zero */ -const uint8_t sr_mask[8] = { - 0x03, - 0x3d, - 0x0f, - 0x3f, - 0x0e, - 0x00, - 0x00, - 0xff, -}; - -const uint8_t gr_mask[16] = { - 0x0f, /* 0x00 */ - 0x0f, /* 0x01 */ - 0x0f, /* 0x02 */ - 0x1f, /* 0x03 */ - 0x03, /* 0x04 */ - 0x7b, /* 0x05 */ - 0x0f, /* 0x06 */ - 0x0f, /* 0x07 */ - 0xff, /* 0x08 */ - 0x00, /* 0x09 */ - 0x00, /* 0x0a */ - 0x00, /* 0x0b */ - 0x00, /* 0x0c */ - 0x00, /* 0x0d */ - 0x00, /* 0x0e */ - 0x00, /* 0x0f */ -}; - -#define cbswap_32(__x) \ -((uint32_t)( \ - (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ - (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ - (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ - (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )) - -#ifdef HOST_WORDS_BIGENDIAN -#define PAT(x) cbswap_32(x) -#else -#define PAT(x) (x) -#endif - -#ifdef HOST_WORDS_BIGENDIAN -#define BIG 1 -#else -#define BIG 0 -#endif - -#ifdef HOST_WORDS_BIGENDIAN -#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff) -#else -#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff) -#endif - -static const uint32_t mask16[16] = { - PAT(0x00000000), - PAT(0x000000ff), - PAT(0x0000ff00), - PAT(0x0000ffff), - PAT(0x00ff0000), - PAT(0x00ff00ff), - PAT(0x00ffff00), - PAT(0x00ffffff), - PAT(0xff000000), - PAT(0xff0000ff), - PAT(0xff00ff00), - PAT(0xff00ffff), - PAT(0xffff0000), - PAT(0xffff00ff), - PAT(0xffffff00), - PAT(0xffffffff), -}; - -#undef PAT - -#ifdef HOST_WORDS_BIGENDIAN -#define PAT(x) (x) -#else -#define PAT(x) cbswap_32(x) -#endif - -static uint32_t expand4[256]; -static uint16_t expand2[256]; -static uint8_t expand4to8[16]; - -static void vbe_update_vgaregs(VGACommonState *s); - -static inline bool vbe_enabled(VGACommonState *s) -{ - return s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED; -} - -static void vga_update_memory_access(VGACommonState *s) -{ - hwaddr base, offset, size; - - if (s->legacy_address_space == NULL) { - return; - } - - if (s->has_chain4_alias) { - memory_region_del_subregion(s->legacy_address_space, &s->chain4_alias); - object_unparent(OBJECT(&s->chain4_alias)); - s->has_chain4_alias = false; - s->plane_updated = 0xf; - } - if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) == - VGA_SR02_ALL_PLANES && s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) { - offset = 0; - switch ((s->gr[VGA_GFX_MISC] >> 2) & 3) { - case 0: - base = 0xa0000; - size = 0x20000; - break; - case 1: - base = 0xa0000; - size = 0x10000; - offset = s->bank_offset; - break; - case 2: - base = 0xb0000; - size = 0x8000; - break; - case 3: - default: - base = 0xb8000; - size = 0x8000; - break; - } - assert(offset + size <= s->vram_size); - memory_region_init_alias(&s->chain4_alias, memory_region_owner(&s->vram), - "vga.chain4", &s->vram, offset, size); - memory_region_add_subregion_overlap(s->legacy_address_space, base, - &s->chain4_alias, 2); - s->has_chain4_alias = true; - } -} - -static void vga_dumb_update_retrace_info(VGACommonState *s) -{ - (void) s; -} - -static void vga_precise_update_retrace_info(VGACommonState *s) -{ - int htotal_chars; - int hretr_start_char; - int hretr_skew_chars; - int hretr_end_char; - - int vtotal_lines; - int vretr_start_line; - int vretr_end_line; - - int dots; -#if 0 - int div2, sldiv2; -#endif - int clocking_mode; - int clock_sel; - const int clk_hz[] = {25175000, 28322000, 25175000, 25175000}; - int64_t chars_per_sec; - struct vga_precise_retrace *r = &s->retrace_info.precise; - - htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5; - hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START]; - hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3; - hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f; - - vtotal_lines = (s->cr[VGA_CRTC_V_TOTAL] | - (((s->cr[VGA_CRTC_OVERFLOW] & 1) | - ((s->cr[VGA_CRTC_OVERFLOW] >> 4) & 2)) << 8)) + 2; - vretr_start_line = s->cr[VGA_CRTC_V_SYNC_START] | - ((((s->cr[VGA_CRTC_OVERFLOW] >> 2) & 1) | - ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8); - vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf; - - clocking_mode = (s->sr[VGA_SEQ_CLOCK_MODE] >> 3) & 1; - clock_sel = (s->msr >> 2) & 3; - dots = (s->msr & 1) ? 8 : 9; - - chars_per_sec = clk_hz[clock_sel] / dots; - - htotal_chars <<= clocking_mode; - - r->total_chars = vtotal_lines * htotal_chars; - if (r->freq) { - r->ticks_per_char = NANOSECONDS_PER_SECOND / (r->total_chars * r->freq); - } else { - r->ticks_per_char = NANOSECONDS_PER_SECOND / chars_per_sec; - } - - r->vstart = vretr_start_line; - r->vend = r->vstart + vretr_end_line + 1; - - r->hstart = hretr_start_char + hretr_skew_chars; - r->hend = r->hstart + hretr_end_char + 1; - r->htotal = htotal_chars; - -#if 0 - div2 = (s->cr[VGA_CRTC_MODE] >> 2) & 1; - sldiv2 = (s->cr[VGA_CRTC_MODE] >> 3) & 1; - printf ( - "hz=%f\n" - "htotal = %d\n" - "hretr_start = %d\n" - "hretr_skew = %d\n" - "hretr_end = %d\n" - "vtotal = %d\n" - "vretr_start = %d\n" - "vretr_end = %d\n" - "div2 = %d sldiv2 = %d\n" - "clocking_mode = %d\n" - "clock_sel = %d %d\n" - "dots = %d\n" - "ticks/char = %" PRId64 "\n" - "\n", - (double) NANOSECONDS_PER_SECOND / (r->ticks_per_char * r->total_chars), - htotal_chars, - hretr_start_char, - hretr_skew_chars, - hretr_end_char, - vtotal_lines, - vretr_start_line, - vretr_end_line, - div2, sldiv2, - clocking_mode, - clock_sel, - clk_hz[clock_sel], - dots, - r->ticks_per_char - ); -#endif -} - -static uint8_t vga_precise_retrace(VGACommonState *s) -{ - struct vga_precise_retrace *r = &s->retrace_info.precise; - uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE); - - if (r->total_chars) { - int cur_line, cur_line_char, cur_char; - int64_t cur_tick; - - cur_tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - - cur_char = (cur_tick / r->ticks_per_char) % r->total_chars; - cur_line = cur_char / r->htotal; - - if (cur_line >= r->vstart && cur_line <= r->vend) { - val |= ST01_V_RETRACE | ST01_DISP_ENABLE; - } else { - cur_line_char = cur_char % r->htotal; - if (cur_line_char >= r->hstart && cur_line_char <= r->hend) { - val |= ST01_DISP_ENABLE; - } - } - - return val; - } else { - return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE); - } -} - -static uint8_t vga_dumb_retrace(VGACommonState *s) -{ - return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE); -} - -int vga_ioport_invalid(VGACommonState *s, uint32_t addr) -{ - if (s->msr & VGA_MIS_COLOR) { - /* Color */ - return (addr >= 0x3b0 && addr <= 0x3bf); - } else { - /* Monochrome */ - return (addr >= 0x3d0 && addr <= 0x3df); - } -} - -uint32_t vga_ioport_read(void *opaque, uint32_t addr) -{ - VGACommonState *s = opaque; - int val, index; - - if (vga_ioport_invalid(s, addr)) { - val = 0xff; - } else { - switch(addr) { - case VGA_ATT_W: - if (s->ar_flip_flop == 0) { - val = s->ar_index; - } else { - val = 0; - } - break; - case VGA_ATT_R: - index = s->ar_index & 0x1f; - if (index < VGA_ATT_C) { - val = s->ar[index]; - } else { - val = 0; - } - break; - case VGA_MIS_W: - val = s->st00; - break; - case VGA_SEQ_I: - val = s->sr_index; - break; - case VGA_SEQ_D: - val = s->sr[s->sr_index]; -#ifdef DEBUG_VGA_REG - printf("vga: read SR%x = 0x%02x\n", s->sr_index, val); -#endif - break; - case VGA_PEL_IR: - val = s->dac_state; - break; - case VGA_PEL_IW: - val = s->dac_write_index; - break; - case VGA_PEL_D: - val = s->palette[s->dac_read_index * 3 + s->dac_sub_index]; - if (++s->dac_sub_index == 3) { - s->dac_sub_index = 0; - s->dac_read_index++; - } - break; - case VGA_FTC_R: - val = s->fcr; - break; - case VGA_MIS_R: - val = s->msr; - break; - case VGA_GFX_I: - val = s->gr_index; - break; - case VGA_GFX_D: - val = s->gr[s->gr_index]; -#ifdef DEBUG_VGA_REG - printf("vga: read GR%x = 0x%02x\n", s->gr_index, val); -#endif - break; - case VGA_CRT_IM: - case VGA_CRT_IC: - val = s->cr_index; - break; - case VGA_CRT_DM: - case VGA_CRT_DC: - val = s->cr[s->cr_index]; -#ifdef DEBUG_VGA_REG - printf("vga: read CR%x = 0x%02x\n", s->cr_index, val); -#endif - break; - case VGA_IS1_RM: - case VGA_IS1_RC: - /* just toggle to fool polling */ - val = s->st01 = s->retrace(s); - s->ar_flip_flop = 0; - break; - default: - val = 0x00; - break; - } - } -#if defined(DEBUG_VGA) - printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val); -#endif - return val; -} - -void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) -{ - VGACommonState *s = opaque; - int index; - - /* check port range access depending on color/monochrome mode */ - if (vga_ioport_invalid(s, addr)) { - return; - } -#ifdef DEBUG_VGA - printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val); -#endif - - switch(addr) { - case VGA_ATT_W: - if (s->ar_flip_flop == 0) { - val &= 0x3f; - s->ar_index = val; - } else { - index = s->ar_index & 0x1f; - switch(index) { - case VGA_ATC_PALETTE0 ... VGA_ATC_PALETTEF: - s->ar[index] = val & 0x3f; - break; - case VGA_ATC_MODE: - s->ar[index] = val & ~0x10; - break; - case VGA_ATC_OVERSCAN: - s->ar[index] = val; - break; - case VGA_ATC_PLANE_ENABLE: - s->ar[index] = val & ~0xc0; - break; - case VGA_ATC_PEL: - s->ar[index] = val & ~0xf0; - break; - case VGA_ATC_COLOR_PAGE: - s->ar[index] = val & ~0xf0; - break; - default: - break; - } - } - s->ar_flip_flop ^= 1; - break; - case VGA_MIS_W: - s->msr = val & ~0x10; - s->update_retrace_info(s); - break; - case VGA_SEQ_I: - s->sr_index = val & 7; - break; - case VGA_SEQ_D: -#ifdef DEBUG_VGA_REG - printf("vga: write SR%x = 0x%02x\n", s->sr_index, val); -#endif - s->sr[s->sr_index] = val & sr_mask[s->sr_index]; - vbe_update_vgaregs(s); - if (s->sr_index == VGA_SEQ_CLOCK_MODE) { - s->update_retrace_info(s); - } - vga_update_memory_access(s); - break; - case VGA_PEL_IR: - s->dac_read_index = val; - s->dac_sub_index = 0; - s->dac_state = 3; - break; - case VGA_PEL_IW: - s->dac_write_index = val; - s->dac_sub_index = 0; - s->dac_state = 0; - break; - case VGA_PEL_D: - s->dac_cache[s->dac_sub_index] = val; - if (++s->dac_sub_index == 3) { - memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3); - s->dac_sub_index = 0; - s->dac_write_index++; - } - break; - case VGA_GFX_I: - s->gr_index = val & 0x0f; - break; - case VGA_GFX_D: -#ifdef DEBUG_VGA_REG - printf("vga: write GR%x = 0x%02x\n", s->gr_index, val); -#endif - s->gr[s->gr_index] = val & gr_mask[s->gr_index]; - vbe_update_vgaregs(s); - vga_update_memory_access(s); - break; - case VGA_CRT_IM: - case VGA_CRT_IC: - s->cr_index = val; - break; - case VGA_CRT_DM: - case VGA_CRT_DC: -#ifdef DEBUG_VGA_REG - printf("vga: write CR%x = 0x%02x\n", s->cr_index, val); -#endif - /* handle CR0-7 protection */ - if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) && - s->cr_index <= VGA_CRTC_OVERFLOW) { - /* can always write bit 4 of CR7 */ - if (s->cr_index == VGA_CRTC_OVERFLOW) { - s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) | - (val & 0x10); - vbe_update_vgaregs(s); - } - return; - } - s->cr[s->cr_index] = val; - vbe_update_vgaregs(s); - - switch(s->cr_index) { - case VGA_CRTC_H_TOTAL: - case VGA_CRTC_H_SYNC_START: - case VGA_CRTC_H_SYNC_END: - case VGA_CRTC_V_TOTAL: - case VGA_CRTC_OVERFLOW: - case VGA_CRTC_V_SYNC_END: - case VGA_CRTC_MODE: - s->update_retrace_info(s); - break; - } - break; - case VGA_IS1_RM: - case VGA_IS1_RC: - s->fcr = val & 0x10; - break; - } -} - -/* - * Sanity check vbe register writes. - * - * As we don't have a way to signal errors to the guest in the bochs - * dispi interface we'll go adjust the registers to the closest valid - * value. - */ -static void vbe_fixup_regs(VGACommonState *s) -{ - uint16_t *r = s->vbe_regs; - uint32_t bits, linelength, maxy, offset; - - if (!vbe_enabled(s)) { - /* vbe is turned off -- nothing to do */ - return; - } - - /* check depth */ - switch (r[VBE_DISPI_INDEX_BPP]) { - case 4: - case 8: - case 16: - case 24: - case 32: - bits = r[VBE_DISPI_INDEX_BPP]; - break; - case 15: - bits = 16; - break; - default: - bits = r[VBE_DISPI_INDEX_BPP] = 8; - break; - } - - /* check width */ - r[VBE_DISPI_INDEX_XRES] &= ~7u; - if (r[VBE_DISPI_INDEX_XRES] == 0) { - r[VBE_DISPI_INDEX_XRES] = 8; - } - if (r[VBE_DISPI_INDEX_XRES] > VBE_DISPI_MAX_XRES) { - r[VBE_DISPI_INDEX_XRES] = VBE_DISPI_MAX_XRES; - } - r[VBE_DISPI_INDEX_VIRT_WIDTH] &= ~7u; - if (r[VBE_DISPI_INDEX_VIRT_WIDTH] > VBE_DISPI_MAX_XRES) { - r[VBE_DISPI_INDEX_VIRT_WIDTH] = VBE_DISPI_MAX_XRES; - } - if (r[VBE_DISPI_INDEX_VIRT_WIDTH] < r[VBE_DISPI_INDEX_XRES]) { - r[VBE_DISPI_INDEX_VIRT_WIDTH] = r[VBE_DISPI_INDEX_XRES]; - } - - /* check height */ - linelength = r[VBE_DISPI_INDEX_VIRT_WIDTH] * bits / 8; - maxy = s->vbe_size / linelength; - if (r[VBE_DISPI_INDEX_YRES] == 0) { - r[VBE_DISPI_INDEX_YRES] = 1; - } - if (r[VBE_DISPI_INDEX_YRES] > VBE_DISPI_MAX_YRES) { - r[VBE_DISPI_INDEX_YRES] = VBE_DISPI_MAX_YRES; - } - if (r[VBE_DISPI_INDEX_YRES] > maxy) { - r[VBE_DISPI_INDEX_YRES] = maxy; - } - - /* check offset */ - if (r[VBE_DISPI_INDEX_X_OFFSET] > VBE_DISPI_MAX_XRES) { - r[VBE_DISPI_INDEX_X_OFFSET] = VBE_DISPI_MAX_XRES; - } - if (r[VBE_DISPI_INDEX_Y_OFFSET] > VBE_DISPI_MAX_YRES) { - r[VBE_DISPI_INDEX_Y_OFFSET] = VBE_DISPI_MAX_YRES; - } - offset = r[VBE_DISPI_INDEX_X_OFFSET] * bits / 8; - offset += r[VBE_DISPI_INDEX_Y_OFFSET] * linelength; - if (offset + r[VBE_DISPI_INDEX_YRES] * linelength > s->vbe_size) { - r[VBE_DISPI_INDEX_Y_OFFSET] = 0; - offset = r[VBE_DISPI_INDEX_X_OFFSET] * bits / 8; - if (offset + r[VBE_DISPI_INDEX_YRES] * linelength > s->vbe_size) { - r[VBE_DISPI_INDEX_X_OFFSET] = 0; - offset = 0; - } - } - - /* update vga state */ - r[VBE_DISPI_INDEX_VIRT_HEIGHT] = maxy; - s->vbe_line_offset = linelength; - s->vbe_start_addr = offset / 4; -} - -/* we initialize the VGA graphic mode */ -static void vbe_update_vgaregs(VGACommonState *s) -{ - int h, shift_control; - - if (!vbe_enabled(s)) { - /* vbe is turned off -- nothing to do */ - return; - } - - /* graphic mode + memory map 1 */ - s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 | - VGA_GR06_GRAPHICS_MODE; - s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */ - s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3; - /* width */ - s->cr[VGA_CRTC_H_DISP] = - (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1; - /* height (only meaningful if < 1024) */ - h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1; - s->cr[VGA_CRTC_V_DISP_END] = h; - s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) | - ((h >> 7) & 0x02) | ((h >> 3) & 0x40); - /* line compare to 1023 */ - s->cr[VGA_CRTC_LINE_COMPARE] = 0xff; - s->cr[VGA_CRTC_OVERFLOW] |= 0x10; - s->cr[VGA_CRTC_MAX_SCAN] |= 0x40; - - if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) { - shift_control = 0; - s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */ - } else { - shift_control = 2; - /* set chain 4 mode */ - s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M; - /* activate all planes */ - s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES; - } - s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) | - (shift_control << 5); - s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */ -} - -static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr) -{ - VGACommonState *s = opaque; - uint32_t val; - val = s->vbe_index; - return val; -} - -uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr) -{ - VGACommonState *s = opaque; - uint32_t val; - - if (s->vbe_index < VBE_DISPI_INDEX_NB) { - if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) { - switch(s->vbe_index) { - /* XXX: do not hardcode ? */ - case VBE_DISPI_INDEX_XRES: - val = VBE_DISPI_MAX_XRES; - break; - case VBE_DISPI_INDEX_YRES: - val = VBE_DISPI_MAX_YRES; - break; - case VBE_DISPI_INDEX_BPP: - val = VBE_DISPI_MAX_BPP; - break; - default: - val = s->vbe_regs[s->vbe_index]; - break; - } - } else { - val = s->vbe_regs[s->vbe_index]; - } - } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) { - val = s->vbe_size / (64 * 1024); - } else { - val = 0; - } -#ifdef DEBUG_BOCHS_VBE - printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val); -#endif - return val; -} - -void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val) -{ - VGACommonState *s = opaque; - s->vbe_index = val; -} - -void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) -{ - VGACommonState *s = opaque; - - if (s->vbe_index <= VBE_DISPI_INDEX_NB) { -#ifdef DEBUG_BOCHS_VBE - printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val); -#endif - switch(s->vbe_index) { - case VBE_DISPI_INDEX_ID: - if (val == VBE_DISPI_ID0 || - val == VBE_DISPI_ID1 || - val == VBE_DISPI_ID2 || - val == VBE_DISPI_ID3 || - val == VBE_DISPI_ID4) { - s->vbe_regs[s->vbe_index] = val; - } - break; - case VBE_DISPI_INDEX_XRES: - case VBE_DISPI_INDEX_YRES: - case VBE_DISPI_INDEX_BPP: - case VBE_DISPI_INDEX_VIRT_WIDTH: - case VBE_DISPI_INDEX_X_OFFSET: - case VBE_DISPI_INDEX_Y_OFFSET: - s->vbe_regs[s->vbe_index] = val; - vbe_fixup_regs(s); - vbe_update_vgaregs(s); - break; - case VBE_DISPI_INDEX_BANK: - val &= s->vbe_bank_mask; - s->vbe_regs[s->vbe_index] = val; - s->bank_offset = (val << 16); - vga_update_memory_access(s); - break; - case VBE_DISPI_INDEX_ENABLE: - if ((val & VBE_DISPI_ENABLED) && - !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) { - - s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 0; - s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0; - s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0; - s->vbe_regs[VBE_DISPI_INDEX_ENABLE] |= VBE_DISPI_ENABLED; - vbe_fixup_regs(s); - vbe_update_vgaregs(s); - - /* clear the screen */ - if (!(val & VBE_DISPI_NOCLEARMEM)) { - memset(s->vram_ptr, 0, - s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset); - } - } else { - s->bank_offset = 0; - } - s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0; - s->vbe_regs[s->vbe_index] = val; - vga_update_memory_access(s); - break; - default: - break; - } - } -} - -/* called for accesses between 0xa0000 and 0xc0000 */ -uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr) -{ - int memory_map_mode, plane; - uint32_t ret; - - /* convert to VGA memory offset */ - memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3; - addr &= 0x1ffff; - switch(memory_map_mode) { - case 0: - break; - case 1: - if (addr >= 0x10000) - return 0xff; - addr += s->bank_offset; - break; - case 2: - addr -= 0x10000; - if (addr >= 0x8000) - return 0xff; - break; - default: - case 3: - addr -= 0x18000; - if (addr >= 0x8000) - return 0xff; - break; - } - - if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) { - /* chain 4 mode : simplest access */ - assert(addr < s->vram_size); - ret = s->vram_ptr[addr]; - } else if (s->gr[VGA_GFX_MODE] & 0x10) { - /* odd/even mode (aka text mode mapping) */ - plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); - addr = ((addr & ~1) << 1) | plane; - if (addr >= s->vram_size) { - return 0xff; - } - ret = s->vram_ptr[addr]; - } else { - /* standard VGA latched access */ - if (addr * sizeof(uint32_t) >= s->vram_size) { - return 0xff; - } - s->latch = ((uint32_t *)s->vram_ptr)[addr]; - - if (!(s->gr[VGA_GFX_MODE] & 0x08)) { - /* read mode 0 */ - plane = s->gr[VGA_GFX_PLANE_READ]; - ret = GET_PLANE(s->latch, plane); - } else { - /* read mode 1 */ - ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) & - mask16[s->gr[VGA_GFX_COMPARE_MASK]]; - ret |= ret >> 16; - ret |= ret >> 8; - ret = (~ret) & 0xff; - } - } - return ret; -} - -/* called for accesses between 0xa0000 and 0xc0000 */ -void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) -{ - int memory_map_mode, plane, write_mode, b, func_select, mask; - uint32_t write_mask, bit_mask, set_mask; - -#ifdef DEBUG_VGA_MEM - printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val); -#endif - /* convert to VGA memory offset */ - memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3; - addr &= 0x1ffff; - switch(memory_map_mode) { - case 0: - break; - case 1: - if (addr >= 0x10000) - return; - addr += s->bank_offset; - break; - case 2: - addr -= 0x10000; - if (addr >= 0x8000) - return; - break; - default: - case 3: - addr -= 0x18000; - if (addr >= 0x8000) - return; - break; - } - - if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) { - /* chain 4 mode : simplest access */ - plane = addr & 3; - mask = (1 << plane); - if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) { - assert(addr < s->vram_size); - s->vram_ptr[addr] = val; -#ifdef DEBUG_VGA_MEM - printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr); -#endif - s->plane_updated |= mask; /* only used to detect font change */ - memory_region_set_dirty(&s->vram, addr, 1); - } - } else if (s->gr[VGA_GFX_MODE] & 0x10) { - /* odd/even mode (aka text mode mapping) */ - plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); - mask = (1 << plane); - if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) { - addr = ((addr & ~1) << 1) | plane; - if (addr >= s->vram_size) { - return; - } - s->vram_ptr[addr] = val; -#ifdef DEBUG_VGA_MEM - printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr); -#endif - s->plane_updated |= mask; /* only used to detect font change */ - memory_region_set_dirty(&s->vram, addr, 1); - } - } else { - /* standard VGA latched access */ - write_mode = s->gr[VGA_GFX_MODE] & 3; - switch(write_mode) { - default: - case 0: - /* rotate */ - b = s->gr[VGA_GFX_DATA_ROTATE] & 7; - val = ((val >> b) | (val << (8 - b))) & 0xff; - val |= val << 8; - val |= val << 16; - - /* apply set/reset mask */ - set_mask = mask16[s->gr[VGA_GFX_SR_ENABLE]]; - val = (val & ~set_mask) | - (mask16[s->gr[VGA_GFX_SR_VALUE]] & set_mask); - bit_mask = s->gr[VGA_GFX_BIT_MASK]; - break; - case 1: - val = s->latch; - goto do_write; - case 2: - val = mask16[val & 0x0f]; - bit_mask = s->gr[VGA_GFX_BIT_MASK]; - break; - case 3: - /* rotate */ - b = s->gr[VGA_GFX_DATA_ROTATE] & 7; - val = (val >> b) | (val << (8 - b)); - - bit_mask = s->gr[VGA_GFX_BIT_MASK] & val; - val = mask16[s->gr[VGA_GFX_SR_VALUE]]; - break; - } - - /* apply logical operation */ - func_select = s->gr[VGA_GFX_DATA_ROTATE] >> 3; - switch(func_select) { - case 0: - default: - /* nothing to do */ - break; - case 1: - /* and */ - val &= s->latch; - break; - case 2: - /* or */ - val |= s->latch; - break; - case 3: - /* xor */ - val ^= s->latch; - break; - } - - /* apply bit mask */ - bit_mask |= bit_mask << 8; - bit_mask |= bit_mask << 16; - val = (val & bit_mask) | (s->latch & ~bit_mask); - - do_write: - /* mask data according to sr[2] */ - mask = s->sr[VGA_SEQ_PLANE_WRITE]; - s->plane_updated |= mask; /* only used to detect font change */ - write_mask = mask16[mask]; - if (addr * sizeof(uint32_t) >= s->vram_size) { - return; - } - ((uint32_t *)s->vram_ptr)[addr] = - (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | - (val & write_mask); -#ifdef DEBUG_VGA_MEM - printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n", - addr * 4, write_mask, val); -#endif - memory_region_set_dirty(&s->vram, addr << 2, sizeof(uint32_t)); - } -} - -typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width); - -#include "vga-helpers.h" - -/* return true if the palette was modified */ -static int update_palette16(VGACommonState *s) -{ - int full_update, i; - uint32_t v, col, *palette; - - full_update = 0; - palette = s->last_palette; - for(i = 0; i < 16; i++) { - v = s->ar[i]; - if (s->ar[VGA_ATC_MODE] & 0x80) { - v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xf) << 4) | (v & 0xf); - } else { - v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f); - } - v = v * 3; - col = rgb_to_pixel32(c6_to_8(s->palette[v]), - c6_to_8(s->palette[v + 1]), - c6_to_8(s->palette[v + 2])); - if (col != palette[i]) { - full_update = 1; - palette[i] = col; - } - } - return full_update; -} - -/* return true if the palette was modified */ -static int update_palette256(VGACommonState *s) -{ - int full_update, i; - uint32_t v, col, *palette; - - full_update = 0; - palette = s->last_palette; - v = 0; - for(i = 0; i < 256; i++) { - if (s->dac_8bit) { - col = rgb_to_pixel32(s->palette[v], - s->palette[v + 1], - s->palette[v + 2]); - } else { - col = rgb_to_pixel32(c6_to_8(s->palette[v]), - c6_to_8(s->palette[v + 1]), - c6_to_8(s->palette[v + 2])); - } - if (col != palette[i]) { - full_update = 1; - palette[i] = col; - } - v += 3; - } - return full_update; -} - -static void vga_get_offsets(VGACommonState *s, - uint32_t *pline_offset, - uint32_t *pstart_addr, - uint32_t *pline_compare) -{ - uint32_t start_addr, line_offset, line_compare; - - if (vbe_enabled(s)) { - line_offset = s->vbe_line_offset; - start_addr = s->vbe_start_addr; - line_compare = 65535; - } else { - /* compute line_offset in bytes */ - line_offset = s->cr[VGA_CRTC_OFFSET]; - line_offset <<= 3; - - /* starting address */ - start_addr = s->cr[VGA_CRTC_START_LO] | - (s->cr[VGA_CRTC_START_HI] << 8); - - /* line compare */ - line_compare = s->cr[VGA_CRTC_LINE_COMPARE] | - ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) | - ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3); - } - *pline_offset = line_offset; - *pstart_addr = start_addr; - *pline_compare = line_compare; -} - -/* update start_addr and line_offset. Return TRUE if modified */ -static int update_basic_params(VGACommonState *s) -{ - int full_update; - uint32_t start_addr, line_offset, line_compare; - - full_update = 0; - - s->get_offsets(s, &line_offset, &start_addr, &line_compare); - - if (line_offset != s->line_offset || - start_addr != s->start_addr || - line_compare != s->line_compare) { - s->line_offset = line_offset; - s->start_addr = start_addr; - s->line_compare = line_compare; - full_update = 1; - } - return full_update; -} - - -static const uint8_t cursor_glyph[32 * 4] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -}; - -static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight, - int *pcwidth, int *pcheight) -{ - int width, cwidth, height, cheight; - - /* total width & height */ - cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1; - cwidth = 8; - if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) { - cwidth = 9; - } - if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) { - cwidth = 16; /* NOTE: no 18 pixel wide */ - } - width = (s->cr[VGA_CRTC_H_DISP] + 1); - if (s->cr[VGA_CRTC_V_TOTAL] == 100) { - /* ugly hack for CGA 160x100x16 - explain me the logic */ - height = 100; - } else { - height = s->cr[VGA_CRTC_V_DISP_END] | - ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) | - ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3); - height = (height + 1) / cheight; - } - - *pwidth = width; - *pheight = height; - *pcwidth = cwidth; - *pcheight = cheight; -} - -/* - * Text mode update - * Missing: - * - double scan - * - double width - * - underline - * - flashing - */ -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; - uint8_t *d1, *d, *src, *dest, *cursor_ptr; - const uint8_t *font_ptr, *font_base[2]; - int dup9, line_offset; - uint32_t *palette; - uint32_t *ch_attr_ptr; - int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); - - /* compute font data address (in plane 2) */ - v = s->sr[VGA_SEQ_CHARACTER_MAP]; - offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2; - if (offset != s->font_offsets[0]) { - s->font_offsets[0] = offset; - full_update = 1; - } - font_base[0] = s->vram_ptr + offset; - - offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2; - font_base[1] = s->vram_ptr + offset; - if (offset != s->font_offsets[1]) { - s->font_offsets[1] = offset; - full_update = 1; - } - if (s->plane_updated & (1 << 2) || s->has_chain4_alias) { - /* if the plane 2 was modified since the last display, it - indicates the font may have been modified */ - s->plane_updated = 0; - full_update = 1; - } - full_update |= update_basic_params(s); - - line_offset = s->line_offset; - - vga_get_text_resolution(s, &width, &height, &cw, &cheight); - if ((height * width) <= 1) { - /* better than nothing: exit if transient size is too small */ - return; - } - if ((height * width) > CH_ATTR_SIZE) { - /* better than nothing: exit if transient size is too big */ - return; - } - - if (width != s->last_width || height != s->last_height || - 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->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; - s->last_ch = cheight; - s->last_cw = cw; - full_update = 1; - } - full_update |= update_palette16(s); - palette = s->last_palette; - x_incr = cw * surface_bytes_per_pixel(surface); - - if (full_update) { - s->full_update_text = 1; - } - if (s->full_update_gfx) { - s->full_update_gfx = 0; - full_update |= 1; - } - - cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) | - s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr; - if (cursor_offset != s->cursor_offset || - s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start || - s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) { - /* if the cursor position changed, we update the old and new - chars */ - if (s->cursor_offset < CH_ATTR_SIZE) - s->last_ch_attr[s->cursor_offset] = -1; - if (cursor_offset < CH_ATTR_SIZE) - s->last_ch_attr[cursor_offset] = -1; - s->cursor_offset = cursor_offset; - s->cursor_start = s->cr[VGA_CRTC_CURSOR_START]; - s->cursor_end = s->cr[VGA_CRTC_CURSOR_END]; - } - cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4; - if (now >= s->cursor_blink_time) { - s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2; - s->cursor_visible_phase = !s->cursor_visible_phase; - } - - dest = surface_data(surface); - linesize = surface_stride(surface); - ch_attr_ptr = s->last_ch_attr; - line = 0; - offset = s->start_addr * 4; - for(cy = 0; cy < height; cy++) { - d1 = dest; - src = s->vram_ptr + offset; - cx_min = width; - cx_max = -1; - for(cx = 0; cx < width; cx++) { - ch_attr = *(uint16_t *)src; - if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) { - if (cx < cx_min) - cx_min = cx; - if (cx > cx_max) - cx_max = cx; - *ch_attr_ptr = ch_attr; -#ifdef HOST_WORDS_BIGENDIAN - ch = ch_attr >> 8; - cattr = ch_attr & 0xff; -#else - ch = ch_attr & 0xff; - cattr = ch_attr >> 8; -#endif - font_ptr = font_base[(cattr >> 3) & 1]; - font_ptr += 32 * 4 * ch; - bgcol = palette[cattr >> 4]; - fgcol = palette[cattr & 0x0f]; - if (cw == 16) { - vga_draw_glyph16(d1, linesize, - font_ptr, cheight, fgcol, bgcol); - } else if (cw != 9) { - vga_draw_glyph8(d1, linesize, - font_ptr, cheight, fgcol, bgcol); - } else { - dup9 = 0; - if (ch >= 0xb0 && ch <= 0xdf && - (s->ar[VGA_ATC_MODE] & 0x04)) { - dup9 = 1; - } - vga_draw_glyph9(d1, linesize, - font_ptr, cheight, fgcol, bgcol, dup9); - } - if (src == cursor_ptr && - !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) && - s->cursor_visible_phase) { - int line_start, line_last, h; - /* draw the cursor */ - line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f; - line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f; - /* XXX: check that */ - if (line_last > cheight - 1) - line_last = cheight - 1; - if (line_last >= line_start && line_start < cheight) { - h = line_last - line_start + 1; - d = d1 + linesize * line_start; - if (cw == 16) { - vga_draw_glyph16(d, linesize, - cursor_glyph, h, fgcol, bgcol); - } else if (cw != 9) { - vga_draw_glyph8(d, linesize, - cursor_glyph, h, fgcol, bgcol); - } else { - vga_draw_glyph9(d, linesize, - cursor_glyph, h, fgcol, bgcol, 1); - } - } - } - } - d1 += x_incr; - src += 4; - ch_attr_ptr++; - } - if (cx_max != -1) { - dpy_gfx_update(s->con, cx_min * cw, cy * cheight, - (cx_max - cx_min + 1) * cw, cheight); - } - dest += linesize * cheight; - line1 = line + cheight; - offset += line_offset; - if (line < s->line_compare && line1 >= s->line_compare) { - offset = 0; - } - line = line1; - } -} - -enum { - VGA_DRAW_LINE2, - VGA_DRAW_LINE2D2, - VGA_DRAW_LINE4, - VGA_DRAW_LINE4D2, - VGA_DRAW_LINE8D2, - VGA_DRAW_LINE8, - VGA_DRAW_LINE15_LE, - VGA_DRAW_LINE16_LE, - VGA_DRAW_LINE24_LE, - VGA_DRAW_LINE32_LE, - VGA_DRAW_LINE15_BE, - VGA_DRAW_LINE16_BE, - VGA_DRAW_LINE24_BE, - VGA_DRAW_LINE32_BE, - VGA_DRAW_LINE_NB, -}; - -static vga_draw_line_func * const vga_draw_line_table[VGA_DRAW_LINE_NB] = { - vga_draw_line2, - vga_draw_line2d2, - vga_draw_line4, - vga_draw_line4d2, - vga_draw_line8d2, - vga_draw_line8, - vga_draw_line15_le, - vga_draw_line16_le, - vga_draw_line24_le, - vga_draw_line32_le, - vga_draw_line15_be, - vga_draw_line16_be, - vga_draw_line24_be, - vga_draw_line32_be, -}; - -static int vga_get_bpp(VGACommonState *s) -{ - int ret; - - if (vbe_enabled(s)) { - ret = s->vbe_regs[VBE_DISPI_INDEX_BPP]; - } else { - ret = 0; - } - return ret; -} - -static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight) -{ - int width, height; - - if (vbe_enabled(s)) { - width = s->vbe_regs[VBE_DISPI_INDEX_XRES]; - height = s->vbe_regs[VBE_DISPI_INDEX_YRES]; - } else { - width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8; - height = s->cr[VGA_CRTC_V_DISP_END] | - ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) | - ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3); - height = (height + 1); - } - *pwidth = width; - *pheight = height; -} - -void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2) -{ - int y; - if (y1 >= VGA_MAX_HEIGHT) - return; - if (y2 >= VGA_MAX_HEIGHT) - y2 = VGA_MAX_HEIGHT; - for(y = y1; y < y2; y++) { - s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f); - } -} - -void vga_sync_dirty_bitmap(VGACommonState *s) -{ - memory_region_sync_dirty_bitmap(&s->vram); -} - -void vga_dirty_log_start(VGACommonState *s) -{ - memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA); -} - -void vga_dirty_log_stop(VGACommonState *s) -{ - memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA); -} - -/* - * graphic modes - */ -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; - int disp_width, multi_scan, multi_run; - uint8_t *d; - uint32_t v, addr1, addr; - vga_draw_line_func *vga_draw_line = NULL; - bool share_surface; - pixman_format_code_t format; -#ifdef HOST_WORDS_BIGENDIAN - bool byteswap = !s->big_endian_fb; -#else - bool byteswap = s->big_endian_fb; -#endif - - full_update |= update_basic_params(s); - - if (!full_update) - vga_sync_dirty_bitmap(s); - - s->get_resolution(s, &width, &height); - disp_width = width; - - shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3; - double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7); - if (shift_control != 1) { - multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan) - - 1; - } else { - /* in CGA modes, multi_scan is ignored */ - /* XXX: is it correct ? */ - multi_scan = double_scan; - } - multi_run = multi_scan; - if (shift_control != s->shift_control || - double_scan != s->double_scan) { - full_update = 1; - s->shift_control = shift_control; - s->double_scan = double_scan; - } - - if (shift_control == 0) { - if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) { - disp_width <<= 1; - } - } else if (shift_control == 1) { - if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) { - disp_width <<= 1; - } - } - - depth = s->get_bpp(s); - - /* - * Check whether we can share the surface with the backend - * or whether we need a shadow surface. We share native - * endian surfaces for 15bpp and above and byteswapped - * surfaces for 24bpp and above. - */ - format = qemu_default_pixman_format(depth, !byteswap); - if (format) { - share_surface = dpy_gfx_check_format(s->con, format) - && !s->force_shadow; - } else { - share_surface = false; - } - if (s->line_offset != s->last_line_offset || - disp_width != s->last_width || - height != s->last_height || - s->last_depth != depth || - s->last_byteswap != byteswap || - share_surface != is_buffer_shared(surface)) { - if (share_surface) { - surface = qemu_create_displaysurface_from(disp_width, - height, format, s->line_offset, - s->vram_ptr + (s->start_addr * 4)); - dpy_gfx_replace_surface(s->con, surface); -#ifdef DEBUG_VGA - printf("VGA: Using shared surface for depth=%d swap=%d\n", - depth, byteswap); -#endif - } else { - qemu_console_resize(s->con, disp_width, height); - surface = qemu_console_surface(s->con); -#ifdef DEBUG_VGA - printf("VGA: Using shadow surface for depth=%d swap=%d\n", - depth, byteswap); -#endif - } - s->last_scr_width = disp_width; - s->last_scr_height = height; - s->last_width = disp_width; - s->last_height = height; - s->last_line_offset = s->line_offset; - s->last_depth = depth; - s->last_byteswap = byteswap; - full_update = 1; - } else if (is_buffer_shared(surface) && - (full_update || surface_data(surface) != s->vram_ptr - + (s->start_addr * 4))) { - pixman_format_code_t format = - qemu_default_pixman_format(depth, !byteswap); - surface = qemu_create_displaysurface_from(disp_width, - height, format, s->line_offset, - s->vram_ptr + (s->start_addr * 4)); - dpy_gfx_replace_surface(s->con, surface); - } - - if (shift_control == 0) { - full_update |= update_palette16(s); - if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) { - v = VGA_DRAW_LINE4D2; - } else { - v = VGA_DRAW_LINE4; - } - bits = 4; - } else if (shift_control == 1) { - full_update |= update_palette16(s); - if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) { - v = VGA_DRAW_LINE2D2; - } else { - v = VGA_DRAW_LINE2; - } - bits = 4; - } else { - switch(s->get_bpp(s)) { - default: - case 0: - full_update |= update_palette256(s); - v = VGA_DRAW_LINE8D2; - bits = 4; - break; - case 8: - full_update |= update_palette256(s); - v = VGA_DRAW_LINE8; - bits = 8; - break; - case 15: - v = s->big_endian_fb ? VGA_DRAW_LINE15_BE : VGA_DRAW_LINE15_LE; - bits = 16; - break; - case 16: - v = s->big_endian_fb ? VGA_DRAW_LINE16_BE : VGA_DRAW_LINE16_LE; - bits = 16; - break; - case 24: - v = s->big_endian_fb ? VGA_DRAW_LINE24_BE : VGA_DRAW_LINE24_LE; - bits = 24; - break; - case 32: - v = s->big_endian_fb ? VGA_DRAW_LINE32_BE : VGA_DRAW_LINE32_LE; - bits = 32; - break; - } - } - vga_draw_line = vga_draw_line_table[v]; - - if (!is_buffer_shared(surface) && s->cursor_invalidate) { - s->cursor_invalidate(s); - } - - line_offset = s->line_offset; -#if 0 - printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n", - width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE], - s->line_compare, s->sr[VGA_SEQ_CLOCK_MODE]); -#endif - addr1 = (s->start_addr * 4); - bwidth = (width * bits + 7) / 8; - y_start = -1; - page_min = -1; - page_max = 0; - d = surface_data(surface); - linesize = surface_stride(surface); - y1 = 0; - for(y = 0; y < height; y++) { - addr = addr1; - if (!(s->cr[VGA_CRTC_MODE] & 1)) { - int shift; - /* CGA compatibility handling */ - shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1); - addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift); - } - if (!(s->cr[VGA_CRTC_MODE] & 2)) { - addr = (addr & ~0x8000) | ((y1 & 2) << 14); - } - update = full_update; - page0 = addr; - page1 = addr + bwidth - 1; - update |= memory_region_get_dirty(&s->vram, page0, page1 - page0, - DIRTY_MEMORY_VGA); - /* explicit invalidation for the hardware cursor */ - update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1; - if (update) { - if (y_start < 0) - y_start = y; - if (page0 < page_min) - page_min = page0; - if (page1 > page_max) - page_max = page1; - 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); - } - } else { - if (y_start >= 0) { - /* flush to display */ - dpy_gfx_update(s->con, 0, y_start, - disp_width, y - y_start); - y_start = -1; - } - } - if (!multi_run) { - mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3; - if ((y1 & mask) == mask) - addr1 += line_offset; - y1++; - multi_run = multi_scan; - } else { - multi_run--; - } - /* line compare acts on the displayed lines */ - if (y == s->line_compare) - addr1 = 0; - d += linesize; - } - if (y_start >= 0) { - /* flush to display */ - dpy_gfx_update(s->con, 0, y_start, - disp_width, y - y_start); - } - /* reset modified pages */ - if (page_max >= page_min) { - memory_region_reset_dirty(&s->vram, - page_min, - page_max - page_min, - DIRTY_MEMORY_VGA); - } - memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4); -} - -static void vga_draw_blank(VGACommonState *s, int full_update) -{ - DisplaySurface *surface = qemu_console_surface(s->con); - int i, w; - uint8_t *d; - - if (!full_update) - return; - if (s->last_scr_width <= 0 || s->last_scr_height <= 0) - return; - - 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, 0, w); - d += surface_stride(surface); - } - dpy_gfx_update(s->con, 0, 0, - s->last_scr_width, s->last_scr_height); -} - -#define GMODE_TEXT 0 -#define GMODE_GRAPH 1 -#define GMODE_BLANK 2 - -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 (surface_bits_per_pixel(surface) == 0) { - /* nothing to do */ - } else { - full_update = 0; - if (!(s->ar_index & 0x20)) { - graphic_mode = GMODE_BLANK; - } else { - graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE; - } - if (graphic_mode != s->graphic_mode) { - s->graphic_mode = graphic_mode; - s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); - full_update = 1; - } - switch(graphic_mode) { - case GMODE_TEXT: - vga_draw_text(s, full_update); - break; - case GMODE_GRAPH: - vga_draw_graphic(s, full_update); - break; - case GMODE_BLANK: - default: - vga_draw_blank(s, full_update); - break; - } - } -} - -/* force a full display refresh */ -static void vga_invalidate_display(void *opaque) -{ - VGACommonState *s = opaque; - - s->last_width = -1; - s->last_height = -1; -} - -void vga_common_reset(VGACommonState *s) -{ - s->sr_index = 0; - memset(s->sr, '\0', sizeof(s->sr)); - s->gr_index = 0; - memset(s->gr, '\0', sizeof(s->gr)); - s->ar_index = 0; - memset(s->ar, '\0', sizeof(s->ar)); - s->ar_flip_flop = 0; - s->cr_index = 0; - memset(s->cr, '\0', sizeof(s->cr)); - s->msr = 0; - s->fcr = 0; - s->st00 = 0; - s->st01 = 0; - s->dac_state = 0; - s->dac_sub_index = 0; - s->dac_read_index = 0; - s->dac_write_index = 0; - memset(s->dac_cache, '\0', sizeof(s->dac_cache)); - s->dac_8bit = 0; - memset(s->palette, '\0', sizeof(s->palette)); - s->bank_offset = 0; - s->vbe_index = 0; - memset(s->vbe_regs, '\0', sizeof(s->vbe_regs)); - s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5; - s->vbe_start_addr = 0; - s->vbe_line_offset = 0; - s->vbe_bank_mask = (s->vram_size >> 16) - 1; - memset(s->font_offsets, '\0', sizeof(s->font_offsets)); - s->graphic_mode = -1; /* force full update */ - s->shift_control = 0; - s->double_scan = 0; - s->line_offset = 0; - s->line_compare = 0; - s->start_addr = 0; - s->plane_updated = 0; - s->last_cw = 0; - s->last_ch = 0; - s->last_width = 0; - s->last_height = 0; - s->last_scr_width = 0; - s->last_scr_height = 0; - s->cursor_start = 0; - s->cursor_end = 0; - s->cursor_offset = 0; - s->big_endian_fb = s->default_endian_fb; - memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table)); - memset(s->last_palette, '\0', sizeof(s->last_palette)); - memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr)); - switch (vga_retrace_method) { - case VGA_RETRACE_DUMB: - break; - case VGA_RETRACE_PRECISE: - memset(&s->retrace_info, 0, sizeof (s->retrace_info)); - break; - } - vga_update_memory_access(s); -} - -static void vga_reset(void *opaque) -{ - VGACommonState *s = opaque; - vga_common_reset(s); -} - -#define TEXTMODE_X(x) ((x) % width) -#define TEXTMODE_Y(x) ((x) / width) -#define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \ - ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1)) -/* relay text rendering to the display driver - * instead of doing a full vga_update_display() */ -static void vga_update_text(void *opaque, console_ch_t *chardata) -{ - VGACommonState *s = opaque; - int graphic_mode, i, cursor_offset, cursor_visible; - int cw, cheight, width, height, size, c_min, c_max; - uint32_t *src; - console_ch_t *dst, val; - char msg_buffer[80]; - int full_update = 0; - - qemu_flush_coalesced_mmio_buffer(); - - if (!(s->ar_index & 0x20)) { - graphic_mode = GMODE_BLANK; - } else { - graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE; - } - if (graphic_mode != s->graphic_mode) { - s->graphic_mode = graphic_mode; - full_update = 1; - } - if (s->last_width == -1) { - s->last_width = 0; - full_update = 1; - } - - switch (graphic_mode) { - case GMODE_TEXT: - /* TODO: update palette */ - full_update |= update_basic_params(s); - - /* total width & height */ - cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1; - cw = 8; - if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) { - cw = 9; - } - if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) { - cw = 16; /* NOTE: no 18 pixel wide */ - } - width = (s->cr[VGA_CRTC_H_DISP] + 1); - if (s->cr[VGA_CRTC_V_TOTAL] == 100) { - /* ugly hack for CGA 160x100x16 - explain me the logic */ - height = 100; - } else { - height = s->cr[VGA_CRTC_V_DISP_END] | - ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) | - ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3); - height = (height + 1) / cheight; - } - - size = (height * width); - if (size > CH_ATTR_SIZE) { - if (!full_update) - return; - - snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode", - width, height); - break; - } - - if (width != s->last_width || height != s->last_height || - cw != s->last_cw || cheight != s->last_ch) { - s->last_scr_width = width * cw; - s->last_scr_height = height * cheight; - 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; - s->last_ch = cheight; - s->last_cw = cw; - full_update = 1; - } - - if (full_update) { - s->full_update_gfx = 1; - } - if (s->full_update_text) { - s->full_update_text = 0; - full_update |= 1; - } - - /* Update "hardware" cursor */ - cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) | - s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr; - if (cursor_offset != s->cursor_offset || - s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start || - 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->con, - TEXTMODE_X(cursor_offset), - TEXTMODE_Y(cursor_offset)); - else - 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]; - } - - src = (uint32_t *) s->vram_ptr + s->start_addr; - dst = chardata; - - if (full_update) { - for (i = 0; i < size; src ++, dst ++, i ++) - console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src))); - - dpy_text_update(s->con, 0, 0, width, height); - } else { - c_max = 0; - - for (i = 0; i < size; src ++, dst ++, i ++) { - console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src))); - if (*dst != val) { - *dst = val; - c_max = i; - break; - } - } - c_min = i; - for (; i < size; src ++, dst ++, i ++) { - console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src))); - if (*dst != val) { - *dst = val; - c_max = i; - } - } - - if (c_min <= c_max) { - i = TEXTMODE_Y(c_min); - dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1); - } - } - - return; - case GMODE_GRAPH: - if (!full_update) - return; - - s->get_resolution(s, &width, &height); - snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode", - width, height); - break; - case GMODE_BLANK: - default: - if (!full_update) - return; - - snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode"); - break; - } - - /* Display a message */ - s->last_width = 60; - s->last_height = height = 3; - 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 ++, ' '); - - size = strlen(msg_buffer); - width = (s->last_width - size) / 2; - dst = chardata + s->last_width + width; - for (i = 0; i < size; i ++) - console_write_ch(dst ++, ATTR2CHTYPE(msg_buffer[i], QEMU_COLOR_BLUE, - QEMU_COLOR_BLACK, 1)); - - dpy_text_update(s->con, 0, 0, s->last_width, height); -} - -static uint64_t vga_mem_read(void *opaque, hwaddr addr, - unsigned size) -{ - VGACommonState *s = opaque; - - return vga_mem_readb(s, addr); -} - -static void vga_mem_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - VGACommonState *s = opaque; - - vga_mem_writeb(s, addr, data); -} - -const MemoryRegionOps vga_mem_ops = { - .read = vga_mem_read, - .write = vga_mem_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static int vga_common_post_load(void *opaque, int version_id) -{ - VGACommonState *s = opaque; - - /* force refresh */ - s->graphic_mode = -1; - return 0; -} - -static bool vga_endian_state_needed(void *opaque) -{ - VGACommonState *s = opaque; - - /* - * Only send the endian state if it's different from the - * default one, thus ensuring backward compatibility for - * migration of the common case - */ - return s->default_endian_fb != s->big_endian_fb; -} - -static const VMStateDescription vmstate_vga_endian = { - .name = "vga.endian", - .version_id = 1, - .minimum_version_id = 1, - .needed = vga_endian_state_needed, - .fields = (VMStateField[]) { - VMSTATE_BOOL(big_endian_fb, VGACommonState), - VMSTATE_END_OF_LIST() - } -}; - -const VMStateDescription vmstate_vga_common = { - .name = "vga", - .version_id = 2, - .minimum_version_id = 2, - .post_load = vga_common_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32(latch, VGACommonState), - VMSTATE_UINT8(sr_index, VGACommonState), - VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8), - VMSTATE_UINT8(gr_index, VGACommonState), - VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16), - VMSTATE_UINT8(ar_index, VGACommonState), - VMSTATE_BUFFER(ar, VGACommonState), - VMSTATE_INT32(ar_flip_flop, VGACommonState), - VMSTATE_UINT8(cr_index, VGACommonState), - VMSTATE_BUFFER(cr, VGACommonState), - VMSTATE_UINT8(msr, VGACommonState), - VMSTATE_UINT8(fcr, VGACommonState), - VMSTATE_UINT8(st00, VGACommonState), - VMSTATE_UINT8(st01, VGACommonState), - - VMSTATE_UINT8(dac_state, VGACommonState), - VMSTATE_UINT8(dac_sub_index, VGACommonState), - VMSTATE_UINT8(dac_read_index, VGACommonState), - VMSTATE_UINT8(dac_write_index, VGACommonState), - VMSTATE_BUFFER(dac_cache, VGACommonState), - VMSTATE_BUFFER(palette, VGACommonState), - - VMSTATE_INT32(bank_offset, VGACommonState), - VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState), - VMSTATE_UINT16(vbe_index, VGACommonState), - VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB), - VMSTATE_UINT32(vbe_start_addr, VGACommonState), - VMSTATE_UINT32(vbe_line_offset, VGACommonState), - VMSTATE_UINT32(vbe_bank_mask, VGACommonState), - VMSTATE_END_OF_LIST() - }, - .subsections = (const VMStateDescription*[]) { - &vmstate_vga_endian, - NULL - } -}; - -static const GraphicHwOps vga_ops = { - .invalidate = vga_invalidate_display, - .gfx_update = vga_update_display, - .text_update = vga_update_text, -}; - -static inline uint32_t uint_clamp(uint32_t val, uint32_t vmin, uint32_t vmax) -{ - if (val < vmin) { - return vmin; - } - if (val > vmax) { - return vmax; - } - return val; -} - -void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate) -{ - int i, j, v, b; - - for(i = 0;i < 256; i++) { - v = 0; - for(j = 0; j < 8; j++) { - v |= ((i >> j) & 1) << (j * 4); - } - expand4[i] = v; - - v = 0; - for(j = 0; j < 4; j++) { - v |= ((i >> (2 * j)) & 3) << (j * 4); - } - expand2[i] = v; - } - for(i = 0; i < 16; i++) { - v = 0; - for(j = 0; j < 4; j++) { - b = ((i >> j) & 1); - v |= b << (2 * j); - v |= b << (2 * j + 1); - } - expand4to8[i] = v; - } - - s->vram_size_mb = uint_clamp(s->vram_size_mb, 1, 512); - s->vram_size_mb = pow2ceil(s->vram_size_mb); - s->vram_size = s->vram_size_mb << 20; - - if (!s->vbe_size) { - s->vbe_size = s->vram_size; - } - - s->is_vbe_vmstate = 1; - memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size, - &error_fatal); - vmstate_register_ram(&s->vram, global_vmstate ? NULL : DEVICE(obj)); - xen_register_framebuffer(&s->vram); - s->vram_ptr = memory_region_get_ram_ptr(&s->vram); - s->get_bpp = vga_get_bpp; - s->get_offsets = vga_get_offsets; - s->get_resolution = vga_get_resolution; - s->hw_ops = &vga_ops; - switch (vga_retrace_method) { - case VGA_RETRACE_DUMB: - s->retrace = vga_dumb_retrace; - s->update_retrace_info = vga_dumb_update_retrace_info; - break; - - case VGA_RETRACE_PRECISE: - s->retrace = vga_precise_retrace; - s->update_retrace_info = vga_precise_update_retrace_info; - break; - } - - /* - * Set default fb endian based on target, could probably be turned - * into a device attribute set by the machine/platform to remove - * all target endian dependencies from this file. - */ -#ifdef TARGET_WORDS_BIGENDIAN - s->default_endian_fb = true; -#else - s->default_endian_fb = false; -#endif - vga_dirty_log_start(s); -} - -static const MemoryRegionPortio vga_portio_list[] = { - { 0x04, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */ - { 0x0a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */ - { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */ - { 0x24, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */ - { 0x2a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */ - PORTIO_END_OF_LIST(), -}; - -static const MemoryRegionPortio vbe_portio_list[] = { - { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index }, -# ifdef TARGET_I386 - { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data }, -# endif - { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data }, - PORTIO_END_OF_LIST(), -}; - -/* Used by both ISA and PCI */ -MemoryRegion *vga_init_io(VGACommonState *s, Object *obj, - const MemoryRegionPortio **vga_ports, - const MemoryRegionPortio **vbe_ports) -{ - MemoryRegion *vga_mem; - - *vga_ports = vga_portio_list; - *vbe_ports = vbe_portio_list; - - vga_mem = g_malloc(sizeof(*vga_mem)); - memory_region_init_io(vga_mem, obj, &vga_mem_ops, s, - "vga-lowmem", 0x20000); - memory_region_set_flush_coalesced(vga_mem); - - return vga_mem; -} - -void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space, - MemoryRegion *address_space_io, bool init_vga_ports) -{ - MemoryRegion *vga_io_memory; - const MemoryRegionPortio *vga_ports, *vbe_ports; - - qemu_register_reset(vga_reset, s); - - s->bank_offset = 0; - - s->legacy_address_space = address_space; - - vga_io_memory = vga_init_io(s, obj, &vga_ports, &vbe_ports); - memory_region_add_subregion_overlap(address_space, - 0x000a0000, - vga_io_memory, - 1); - memory_region_set_coalescing(vga_io_memory); - if (init_vga_ports) { - portio_list_init(&s->vga_port_list, obj, vga_ports, s, "vga"); - portio_list_set_flush_coalesced(&s->vga_port_list); - portio_list_add(&s->vga_port_list, address_space_io, 0x3b0); - } - if (vbe_ports) { - portio_list_init(&s->vbe_port_list, obj, vbe_ports, s, "vbe"); - portio_list_add(&s->vbe_port_list, address_space_io, 0x1ce); - } -} - -void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *system_memory) -{ - /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region, - * so use an alias to avoid double-mapping the same region. - */ - memory_region_init_alias(&s->vram_vbe, obj, "vram.vbe", - &s->vram, 0, memory_region_size(&s->vram)); - /* XXX: use optimized standard vga accesses */ - memory_region_add_subregion(system_memory, - VBE_DISPI_LFB_PHYSICAL_ADDRESS, - &s->vram_vbe); - s->vbe_mapped = 1; -} diff --git a/qemu/hw/display/vga.h b/qemu/hw/display/vga.h deleted file mode 100644 index d917046da..000000000 --- a/qemu/hw/display/vga.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * linux/include/video/vga.h -- standard VGA chipset interaction - * - * Copyright 1999 Jeff Garzik - * - * Copyright history from vga16fb.c: - * Copyright 1999 Ben Pfaff and Petr Vandrovec - * Based on VGA info at http://www.osdever.net/FreeVGA/home.htm - * Based on VESA framebuffer (c) 1998 Gerd Knorr - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of this - * archive for more details. - * - */ - -#ifndef __linux_video_vga_h__ -#define __linux_video_vga_h__ - -/* Some of the code below is taken from SVGAlib. The original, - unmodified copyright notice for that code is below. */ -/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ -/* */ -/* This library is free software; you can redistribute it and/or */ -/* modify it without any restrictions. This library is distributed */ -/* in the hope that it will be useful, but without any warranty. */ - -/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ -/* partially copyrighted (C) 1993 by Hartmut Schirmer */ - -/* VGA data register ports */ -#define VGA_CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */ -#define VGA_CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */ -#define VGA_ATT_R 0x3C1 /* Attribute Controller Data Read Register */ -#define VGA_ATT_W 0x3C0 /* Attribute Controller Data Write Register */ -#define VGA_GFX_D 0x3CF /* Graphics Controller Data Register */ -#define VGA_SEQ_D 0x3C5 /* Sequencer Data Register */ -#define VGA_MIS_R 0x3CC /* Misc Output Read Register */ -#define VGA_MIS_W 0x3C2 /* Misc Output Write Register */ -#define VGA_FTC_R 0x3CA /* Feature Control Read Register */ -#define VGA_IS1_RC 0x3DA /* Input Status Register 1 - color emulation */ -#define VGA_IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */ -#define VGA_PEL_D 0x3C9 /* PEL Data Register */ -#define VGA_PEL_MSK 0x3C6 /* PEL mask register */ - -/* EGA-specific registers */ -#define EGA_GFX_E0 0x3CC /* Graphics enable processor 0 */ -#define EGA_GFX_E1 0x3CA /* Graphics enable processor 1 */ - -/* VGA index register ports */ -#define VGA_CRT_IC 0x3D4 /* CRT Controller Index - color emulation */ -#define VGA_CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */ -#define VGA_ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ -#define VGA_GFX_I 0x3CE /* Graphics Controller Index */ -#define VGA_SEQ_I 0x3C4 /* Sequencer Index */ -#define VGA_PEL_IW 0x3C8 /* PEL Write Index */ -#define VGA_PEL_IR 0x3C7 /* PEL Read Index */ - -/* standard VGA indexes max counts */ -#define VGA_CRT_C 0x19 /* Number of CRT Controller Registers */ -#define VGA_ATT_C 0x15 /* Number of Attribute Controller Registers */ -#define VGA_GFX_C 0x09 /* Number of Graphics Controller Registers */ -#define VGA_SEQ_C 0x05 /* Number of Sequencer Registers */ -#define VGA_MIS_C 0x01 /* Number of Misc Output Register */ - -/* VGA misc register bit masks */ -#define VGA_MIS_COLOR 0x01 -#define VGA_MIS_ENB_MEM_ACCESS 0x02 -#define VGA_MIS_DCLK_28322_720 0x04 -#define VGA_MIS_ENB_PLL_LOAD (0x04 | 0x08) -#define VGA_MIS_SEL_HIGH_PAGE 0x20 - -/* VGA CRT controller register indices */ -#define VGA_CRTC_H_TOTAL 0 -#define VGA_CRTC_H_DISP 1 -#define VGA_CRTC_H_BLANK_START 2 -#define VGA_CRTC_H_BLANK_END 3 -#define VGA_CRTC_H_SYNC_START 4 -#define VGA_CRTC_H_SYNC_END 5 -#define VGA_CRTC_V_TOTAL 6 -#define VGA_CRTC_OVERFLOW 7 -#define VGA_CRTC_PRESET_ROW 8 -#define VGA_CRTC_MAX_SCAN 9 -#define VGA_CRTC_CURSOR_START 0x0A -#define VGA_CRTC_CURSOR_END 0x0B -#define VGA_CRTC_START_HI 0x0C -#define VGA_CRTC_START_LO 0x0D -#define VGA_CRTC_CURSOR_HI 0x0E -#define VGA_CRTC_CURSOR_LO 0x0F -#define VGA_CRTC_V_SYNC_START 0x10 -#define VGA_CRTC_V_SYNC_END 0x11 -#define VGA_CRTC_V_DISP_END 0x12 -#define VGA_CRTC_OFFSET 0x13 -#define VGA_CRTC_UNDERLINE 0x14 -#define VGA_CRTC_V_BLANK_START 0x15 -#define VGA_CRTC_V_BLANK_END 0x16 -#define VGA_CRTC_MODE 0x17 -#define VGA_CRTC_LINE_COMPARE 0x18 -#define VGA_CRTC_REGS VGA_CRT_C - -/* VGA CRT controller bit masks */ -#define VGA_CR11_LOCK_CR0_CR7 0x80 /* lock writes to CR0 - CR7 */ -#define VGA_CR17_H_V_SIGNALS_ENABLED 0x80 - -/* VGA attribute controller register indices */ -#define VGA_ATC_PALETTE0 0x00 -#define VGA_ATC_PALETTE1 0x01 -#define VGA_ATC_PALETTE2 0x02 -#define VGA_ATC_PALETTE3 0x03 -#define VGA_ATC_PALETTE4 0x04 -#define VGA_ATC_PALETTE5 0x05 -#define VGA_ATC_PALETTE6 0x06 -#define VGA_ATC_PALETTE7 0x07 -#define VGA_ATC_PALETTE8 0x08 -#define VGA_ATC_PALETTE9 0x09 -#define VGA_ATC_PALETTEA 0x0A -#define VGA_ATC_PALETTEB 0x0B -#define VGA_ATC_PALETTEC 0x0C -#define VGA_ATC_PALETTED 0x0D -#define VGA_ATC_PALETTEE 0x0E -#define VGA_ATC_PALETTEF 0x0F -#define VGA_ATC_MODE 0x10 -#define VGA_ATC_OVERSCAN 0x11 -#define VGA_ATC_PLANE_ENABLE 0x12 -#define VGA_ATC_PEL 0x13 -#define VGA_ATC_COLOR_PAGE 0x14 - -#define VGA_AR_ENABLE_DISPLAY 0x20 - -/* VGA sequencer register indices */ -#define VGA_SEQ_RESET 0x00 -#define VGA_SEQ_CLOCK_MODE 0x01 -#define VGA_SEQ_PLANE_WRITE 0x02 -#define VGA_SEQ_CHARACTER_MAP 0x03 -#define VGA_SEQ_MEMORY_MODE 0x04 - -/* VGA sequencer register bit masks */ -#define VGA_SR01_CHAR_CLK_8DOTS 0x01 /* bit 0: character clocks 8 dots wide are generated */ -#define VGA_SR01_SCREEN_OFF 0x20 /* bit 5: Screen is off */ -#define VGA_SR02_ALL_PLANES 0x0F /* bits 3-0: enable access to all planes */ -#define VGA_SR04_EXT_MEM 0x02 /* bit 1: allows complete mem access to 256K */ -#define VGA_SR04_SEQ_MODE 0x04 /* bit 2: directs system to use a sequential addressing mode */ -#define VGA_SR04_CHN_4M 0x08 /* bit 3: selects modulo 4 addressing for CPU access to display memory */ - -/* VGA graphics controller register indices */ -#define VGA_GFX_SR_VALUE 0x00 -#define VGA_GFX_SR_ENABLE 0x01 -#define VGA_GFX_COMPARE_VALUE 0x02 -#define VGA_GFX_DATA_ROTATE 0x03 -#define VGA_GFX_PLANE_READ 0x04 -#define VGA_GFX_MODE 0x05 -#define VGA_GFX_MISC 0x06 -#define VGA_GFX_COMPARE_MASK 0x07 -#define VGA_GFX_BIT_MASK 0x08 - -/* VGA graphics controller bit masks */ -#define VGA_GR06_GRAPHICS_MODE 0x01 - -#endif /* __linux_video_vga_h__ */ diff --git a/qemu/hw/display/vga_int.h b/qemu/hw/display/vga_int.h deleted file mode 100644 index bdb43a5a3..000000000 --- a/qemu/hw/display/vga_int.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - * QEMU internal VGA defines. - * - * Copyright (c) 2003-2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef HW_VGA_INT_H -#define HW_VGA_INT_H 1 - -#include -#include "exec/memory.h" - -#define ST01_V_RETRACE 0x08 -#define ST01_DISP_ENABLE 0x01 - -#define VBE_DISPI_MAX_XRES 16000 -#define VBE_DISPI_MAX_YRES 12000 -#define VBE_DISPI_MAX_BPP 32 - -#define VBE_DISPI_INDEX_ID 0x0 -#define VBE_DISPI_INDEX_XRES 0x1 -#define VBE_DISPI_INDEX_YRES 0x2 -#define VBE_DISPI_INDEX_BPP 0x3 -#define VBE_DISPI_INDEX_ENABLE 0x4 -#define VBE_DISPI_INDEX_BANK 0x5 -#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 -#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 -#define VBE_DISPI_INDEX_X_OFFSET 0x8 -#define VBE_DISPI_INDEX_Y_OFFSET 0x9 -#define VBE_DISPI_INDEX_NB 0xa /* size of vbe_regs[] */ -#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa /* read-only, not in vbe_regs */ - -#define VBE_DISPI_ID0 0xB0C0 -#define VBE_DISPI_ID1 0xB0C1 -#define VBE_DISPI_ID2 0xB0C2 -#define VBE_DISPI_ID3 0xB0C3 -#define VBE_DISPI_ID4 0xB0C4 -#define VBE_DISPI_ID5 0xB0C5 - -#define VBE_DISPI_DISABLED 0x00 -#define VBE_DISPI_ENABLED 0x01 -#define VBE_DISPI_GETCAPS 0x02 -#define VBE_DISPI_8BIT_DAC 0x20 -#define VBE_DISPI_LFB_ENABLED 0x40 -#define VBE_DISPI_NOCLEARMEM 0x80 - -#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 - -#define CH_ATTR_SIZE (160 * 100) -#define VGA_MAX_HEIGHT 2048 - -struct vga_precise_retrace { - int64_t ticks_per_char; - int64_t total_chars; - int htotal; - int hstart; - int hend; - int vstart; - int vend; - int freq; -}; - -union vga_retrace { - struct vga_precise_retrace precise; -}; - -struct VGACommonState; -typedef uint8_t (* vga_retrace_fn)(struct VGACommonState *s); -typedef void (* vga_update_retrace_info_fn)(struct VGACommonState *s); - -typedef struct VGACommonState { - MemoryRegion *legacy_address_space; - uint8_t *vram_ptr; - MemoryRegion vram; - MemoryRegion vram_vbe; - uint32_t vram_size; - uint32_t vram_size_mb; /* property */ - uint32_t vbe_size; - uint32_t latch; - bool has_chain4_alias; - MemoryRegion chain4_alias; - uint8_t sr_index; - uint8_t sr[256]; - uint8_t gr_index; - uint8_t gr[256]; - uint8_t ar_index; - uint8_t ar[21]; - int ar_flip_flop; - uint8_t cr_index; - uint8_t cr[256]; /* CRT registers */ - uint8_t msr; /* Misc Output Register */ - uint8_t fcr; /* Feature Control Register */ - uint8_t st00; /* status 0 */ - uint8_t st01; /* status 1 */ - uint8_t dac_state; - uint8_t dac_sub_index; - uint8_t dac_read_index; - uint8_t dac_write_index; - uint8_t dac_cache[3]; /* used when writing */ - int dac_8bit; - uint8_t palette[768]; - int32_t bank_offset; - int (*get_bpp)(struct VGACommonState *s); - void (*get_offsets)(struct VGACommonState *s, - uint32_t *pline_offset, - uint32_t *pstart_addr, - uint32_t *pline_compare); - void (*get_resolution)(struct VGACommonState *s, - int *pwidth, - int *pheight); - PortioList vga_port_list; - PortioList vbe_port_list; - /* bochs vbe state */ - uint16_t vbe_index; - uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; - uint32_t vbe_start_addr; - uint32_t vbe_line_offset; - uint32_t vbe_bank_mask; - int vbe_mapped; - /* display refresh support */ - QemuConsole *con; - uint32_t font_offsets[2]; - int graphic_mode; - uint8_t shift_control; - uint8_t double_scan; - uint32_t line_offset; - uint32_t line_compare; - uint32_t start_addr; - uint32_t plane_updated; - uint32_t last_line_offset; - uint8_t last_cw, last_ch; - uint32_t last_width, last_height; /* in chars or pixels */ - uint32_t last_scr_width, last_scr_height; /* in pixels */ - uint32_t last_depth; /* in bits */ - bool last_byteswap; - bool force_shadow; - uint8_t cursor_start, cursor_end; - bool cursor_visible_phase; - int64_t cursor_blink_time; - uint32_t cursor_offset; - const GraphicHwOps *hw_ops; - bool full_update_text; - bool full_update_gfx; - bool big_endian_fb; - bool default_endian_fb; - /* hardware mouse cursor support */ - uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; - uint32_t hw_cursor_x; - uint32_t hw_cursor_y; - void (*cursor_invalidate)(struct VGACommonState *s); - void (*cursor_draw_line)(struct VGACommonState *s, uint8_t *d, int y); - /* tell for each page if it has been updated since the last time */ - uint32_t last_palette[256]; - uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ - /* retrace */ - vga_retrace_fn retrace; - vga_update_retrace_info_fn update_retrace_info; - union vga_retrace retrace_info; - uint8_t is_vbe_vmstate; -} VGACommonState; - -static inline int c6_to_8(int v) -{ - int b; - v &= 0x3f; - b = v & 1; - return (v << 2) | (b << 1) | b; -} - -void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate); -void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space, - MemoryRegion *address_space_io, bool init_vga_ports); -MemoryRegion *vga_init_io(VGACommonState *s, Object *obj, - const MemoryRegionPortio **vga_ports, - const MemoryRegionPortio **vbe_ports); -void vga_common_reset(VGACommonState *s); - -void vga_sync_dirty_bitmap(VGACommonState *s); -void vga_dirty_log_start(VGACommonState *s); -void vga_dirty_log_stop(VGACommonState *s); - -extern const VMStateDescription vmstate_vga_common; -uint32_t vga_ioport_read(void *opaque, uint32_t addr); -void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val); -uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr); -void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val); -void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2); - -int vga_ioport_invalid(VGACommonState *s, uint32_t addr); - -void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *address_space); -uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr); -void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val); -void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val); - -extern const uint8_t sr_mask[8]; -extern const uint8_t gr_mask[16]; - -#define VGABIOS_FILENAME "vgabios.bin" -#define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" - -extern const MemoryRegionOps vga_mem_ops; - -/* vga-pci.c */ -void pci_std_vga_mmio_region_init(VGACommonState *s, - MemoryRegion *parent, - MemoryRegion *subs, - bool qext); - -#endif diff --git a/qemu/hw/display/virtio-gpu-3d.c b/qemu/hw/display/virtio-gpu-3d.c deleted file mode 100644 index fa192946a..000000000 --- a/qemu/hw/display/virtio-gpu-3d.c +++ /dev/null @@ -1,606 +0,0 @@ -/* - * Virtio GPU Device - * - * Copyright Red Hat, Inc. 2013-2014 - * - * Authors: - * Dave Airlie - * Gerd Hoffmann - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "qemu/iov.h" -#include "trace.h" -#include "hw/virtio/virtio.h" -#include "hw/virtio/virtio-gpu.h" - -#ifdef CONFIG_VIRGL - -#include "virglrenderer.h" - -static struct virgl_renderer_callbacks virtio_gpu_3d_cbs; - -static void virgl_cmd_create_resource_2d(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_resource_create_2d c2d; - struct virgl_renderer_resource_create_args args; - - VIRTIO_GPU_FILL_CMD(c2d); - trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format, - c2d.width, c2d.height); - - args.handle = c2d.resource_id; - args.target = 2; - args.format = c2d.format; - args.bind = (1 << 1); - args.width = c2d.width; - args.height = c2d.height; - args.depth = 1; - args.array_size = 1; - args.last_level = 0; - args.nr_samples = 0; - args.flags = VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP; - virgl_renderer_resource_create(&args, NULL, 0); -} - -static void virgl_cmd_create_resource_3d(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_resource_create_3d c3d; - struct virgl_renderer_resource_create_args args; - - VIRTIO_GPU_FILL_CMD(c3d); - trace_virtio_gpu_cmd_res_create_3d(c3d.resource_id, c3d.format, - c3d.width, c3d.height, c3d.depth); - - args.handle = c3d.resource_id; - args.target = c3d.target; - args.format = c3d.format; - args.bind = c3d.bind; - args.width = c3d.width; - args.height = c3d.height; - args.depth = c3d.depth; - args.array_size = c3d.array_size; - args.last_level = c3d.last_level; - args.nr_samples = c3d.nr_samples; - args.flags = c3d.flags; - virgl_renderer_resource_create(&args, NULL, 0); -} - -static void virgl_cmd_resource_unref(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_resource_unref unref; - - VIRTIO_GPU_FILL_CMD(unref); - trace_virtio_gpu_cmd_res_unref(unref.resource_id); - - virgl_renderer_resource_unref(unref.resource_id); -} - -static void virgl_cmd_context_create(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_ctx_create cc; - - VIRTIO_GPU_FILL_CMD(cc); - trace_virtio_gpu_cmd_ctx_create(cc.hdr.ctx_id, - cc.debug_name); - - virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen, - cc.debug_name); -} - -static void virgl_cmd_context_destroy(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_ctx_destroy cd; - - VIRTIO_GPU_FILL_CMD(cd); - trace_virtio_gpu_cmd_ctx_destroy(cd.hdr.ctx_id); - - virgl_renderer_context_destroy(cd.hdr.ctx_id); -} - -static void virtio_gpu_rect_update(VirtIOGPU *g, int idx, int x, int y, - int width, int height) -{ - if (!g->scanout[idx].con) { - return; - } - - dpy_gl_update(g->scanout[idx].con, x, y, width, height); -} - -static void virgl_cmd_resource_flush(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_resource_flush rf; - int i; - - VIRTIO_GPU_FILL_CMD(rf); - trace_virtio_gpu_cmd_res_flush(rf.resource_id, - rf.r.width, rf.r.height, rf.r.x, rf.r.y); - - for (i = 0; i < VIRTIO_GPU_MAX_SCANOUT; i++) { - if (g->scanout[i].resource_id != rf.resource_id) { - continue; - } - virtio_gpu_rect_update(g, i, rf.r.x, rf.r.y, rf.r.width, rf.r.height); - } -} - -static void virgl_cmd_set_scanout(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_set_scanout ss; - struct virgl_renderer_resource_info info; - int ret; - - VIRTIO_GPU_FILL_CMD(ss); - trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id, - ss.r.width, ss.r.height, ss.r.x, ss.r.y); - - if (ss.scanout_id >= VIRTIO_GPU_MAX_SCANOUT) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d", - __func__, ss.scanout_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID; - return; - } - g->enable = 1; - - memset(&info, 0, sizeof(info)); - - if (ss.resource_id && ss.r.width && ss.r.height) { - ret = virgl_renderer_resource_get_info(ss.resource_id, &info); - if (ret == -1) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: illegal resource specified %d\n", - __func__, ss.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - qemu_console_resize(g->scanout[ss.scanout_id].con, - ss.r.width, ss.r.height); - virgl_renderer_force_ctx_0(); - dpy_gl_scanout(g->scanout[ss.scanout_id].con, info.tex_id, - info.flags & 1 /* FIXME: Y_0_TOP */, - ss.r.x, ss.r.y, ss.r.width, ss.r.height); - } else { - if (ss.scanout_id != 0) { - dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, NULL); - } - dpy_gl_scanout(g->scanout[ss.scanout_id].con, 0, false, - 0, 0, 0, 0); - } - g->scanout[ss.scanout_id].resource_id = ss.resource_id; -} - -static void virgl_cmd_submit_3d(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_cmd_submit cs; - void *buf; - size_t s; - - VIRTIO_GPU_FILL_CMD(cs); - trace_virtio_gpu_cmd_ctx_submit(cs.hdr.ctx_id, cs.size); - - buf = g_malloc(cs.size); - s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, - sizeof(cs), buf, cs.size); - if (s != cs.size) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: size mismatch (%zd/%d)", - __func__, s, cs.size); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; - goto out; - } - - if (virtio_gpu_stats_enabled(g->conf)) { - g->stats.req_3d++; - g->stats.bytes_3d += cs.size; - } - - virgl_renderer_submit_cmd(buf, cs.hdr.ctx_id, cs.size / 4); - -out: - g_free(buf); -} - -static void virgl_cmd_transfer_to_host_2d(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_transfer_to_host_2d t2d; - struct virtio_gpu_box box; - - VIRTIO_GPU_FILL_CMD(t2d); - trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id); - - box.x = t2d.r.x; - box.y = t2d.r.y; - box.z = 0; - box.w = t2d.r.width; - box.h = t2d.r.height; - box.d = 1; - - virgl_renderer_transfer_write_iov(t2d.resource_id, - 0, - 0, - 0, - 0, - (struct virgl_box *)&box, - t2d.offset, NULL, 0); -} - -static void virgl_cmd_transfer_to_host_3d(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_transfer_host_3d t3d; - - VIRTIO_GPU_FILL_CMD(t3d); - trace_virtio_gpu_cmd_res_xfer_toh_3d(t3d.resource_id); - - virgl_renderer_transfer_write_iov(t3d.resource_id, - t3d.hdr.ctx_id, - t3d.level, - t3d.stride, - t3d.layer_stride, - (struct virgl_box *)&t3d.box, - t3d.offset, NULL, 0); -} - -static void -virgl_cmd_transfer_from_host_3d(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_transfer_host_3d tf3d; - - VIRTIO_GPU_FILL_CMD(tf3d); - trace_virtio_gpu_cmd_res_xfer_fromh_3d(tf3d.resource_id); - - virgl_renderer_transfer_read_iov(tf3d.resource_id, - tf3d.hdr.ctx_id, - tf3d.level, - tf3d.stride, - tf3d.layer_stride, - (struct virgl_box *)&tf3d.box, - tf3d.offset, NULL, 0); -} - - -static void virgl_resource_attach_backing(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_resource_attach_backing att_rb; - struct iovec *res_iovs; - int ret; - - VIRTIO_GPU_FILL_CMD(att_rb); - trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id); - - ret = virtio_gpu_create_mapping_iov(&att_rb, cmd, &res_iovs); - if (ret != 0) { - cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; - return; - } - - virgl_renderer_resource_attach_iov(att_rb.resource_id, - res_iovs, att_rb.nr_entries); -} - -static void virgl_resource_detach_backing(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_resource_detach_backing detach_rb; - struct iovec *res_iovs = NULL; - int num_iovs = 0; - - VIRTIO_GPU_FILL_CMD(detach_rb); - trace_virtio_gpu_cmd_res_back_detach(detach_rb.resource_id); - - virgl_renderer_resource_detach_iov(detach_rb.resource_id, - &res_iovs, - &num_iovs); - if (res_iovs == NULL || num_iovs == 0) { - return; - } - virtio_gpu_cleanup_mapping_iov(res_iovs, num_iovs); -} - - -static void virgl_cmd_ctx_attach_resource(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_ctx_resource att_res; - - VIRTIO_GPU_FILL_CMD(att_res); - trace_virtio_gpu_cmd_ctx_res_attach(att_res.hdr.ctx_id, - att_res.resource_id); - - virgl_renderer_ctx_attach_resource(att_res.hdr.ctx_id, att_res.resource_id); -} - -static void virgl_cmd_ctx_detach_resource(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_ctx_resource det_res; - - VIRTIO_GPU_FILL_CMD(det_res); - trace_virtio_gpu_cmd_ctx_res_detach(det_res.hdr.ctx_id, - det_res.resource_id); - - virgl_renderer_ctx_detach_resource(det_res.hdr.ctx_id, det_res.resource_id); -} - -static void virgl_cmd_get_capset_info(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_get_capset_info info; - struct virtio_gpu_resp_capset_info resp; - - VIRTIO_GPU_FILL_CMD(info); - - if (info.capset_index == 0) { - resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL; - virgl_renderer_get_cap_set(resp.capset_id, - &resp.capset_max_version, - &resp.capset_max_size); - } else { - resp.capset_max_version = 0; - resp.capset_max_size = 0; - } - resp.hdr.type = VIRTIO_GPU_RESP_OK_CAPSET_INFO; - virtio_gpu_ctrl_response(g, cmd, &resp.hdr, sizeof(resp)); -} - -static void virgl_cmd_get_capset(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_get_capset gc; - struct virtio_gpu_resp_capset *resp; - uint32_t max_ver, max_size; - VIRTIO_GPU_FILL_CMD(gc); - - virgl_renderer_get_cap_set(gc.capset_id, &max_ver, - &max_size); - resp = g_malloc(sizeof(*resp) + max_size); - - resp->hdr.type = VIRTIO_GPU_RESP_OK_CAPSET; - virgl_renderer_fill_caps(gc.capset_id, - gc.capset_version, - (void *)resp->capset_data); - virtio_gpu_ctrl_response(g, cmd, &resp->hdr, sizeof(*resp) + max_size); - g_free(resp); -} - -void virtio_gpu_virgl_process_cmd(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr); - - cmd->waiting = g->renderer_blocked; - if (cmd->waiting) { - return; - } - - virgl_renderer_force_ctx_0(); - switch (cmd->cmd_hdr.type) { - case VIRTIO_GPU_CMD_CTX_CREATE: - virgl_cmd_context_create(g, cmd); - break; - case VIRTIO_GPU_CMD_CTX_DESTROY: - virgl_cmd_context_destroy(g, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D: - virgl_cmd_create_resource_2d(g, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_CREATE_3D: - virgl_cmd_create_resource_3d(g, cmd); - break; - case VIRTIO_GPU_CMD_SUBMIT_3D: - virgl_cmd_submit_3d(g, cmd); - break; - case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D: - virgl_cmd_transfer_to_host_2d(g, cmd); - break; - case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D: - virgl_cmd_transfer_to_host_3d(g, cmd); - break; - case VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D: - virgl_cmd_transfer_from_host_3d(g, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING: - virgl_resource_attach_backing(g, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING: - virgl_resource_detach_backing(g, cmd); - break; - case VIRTIO_GPU_CMD_SET_SCANOUT: - virgl_cmd_set_scanout(g, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_FLUSH: - virgl_cmd_resource_flush(g, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_UNREF: - virgl_cmd_resource_unref(g, cmd); - break; - case VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE: - /* TODO add security */ - virgl_cmd_ctx_attach_resource(g, cmd); - break; - case VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE: - /* TODO add security */ - virgl_cmd_ctx_detach_resource(g, cmd); - break; - case VIRTIO_GPU_CMD_GET_CAPSET_INFO: - virgl_cmd_get_capset_info(g, cmd); - break; - case VIRTIO_GPU_CMD_GET_CAPSET: - virgl_cmd_get_capset(g, cmd); - break; - - case VIRTIO_GPU_CMD_GET_DISPLAY_INFO: - virtio_gpu_get_display_info(g, cmd); - break; - default: - cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; - break; - } - - if (cmd->finished) { - return; - } - if (cmd->error) { - fprintf(stderr, "%s: ctrl 0x%x, error 0x%x\n", __func__, - cmd->cmd_hdr.type, cmd->error); - virtio_gpu_ctrl_response_nodata(g, cmd, cmd->error); - return; - } - if (!(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) { - virtio_gpu_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA); - return; - } - - trace_virtio_gpu_fence_ctrl(cmd->cmd_hdr.fence_id, cmd->cmd_hdr.type); - virgl_renderer_create_fence(cmd->cmd_hdr.fence_id, cmd->cmd_hdr.type); -} - -static void virgl_write_fence(void *opaque, uint32_t fence) -{ - VirtIOGPU *g = opaque; - struct virtio_gpu_ctrl_command *cmd, *tmp; - - QTAILQ_FOREACH_SAFE(cmd, &g->fenceq, next, tmp) { - /* - * the guest can end up emitting fences out of order - * so we should check all fenced cmds not just the first one. - */ - if (cmd->cmd_hdr.fence_id > fence) { - continue; - } - trace_virtio_gpu_fence_resp(cmd->cmd_hdr.fence_id); - virtio_gpu_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA); - QTAILQ_REMOVE(&g->fenceq, cmd, next); - g_free(cmd); - g->inflight--; - if (virtio_gpu_stats_enabled(g->conf)) { - fprintf(stderr, "inflight: %3d (-)\r", g->inflight); - } - } -} - -static virgl_renderer_gl_context -virgl_create_context(void *opaque, int scanout_idx, - struct virgl_renderer_gl_ctx_param *params) -{ - VirtIOGPU *g = opaque; - QEMUGLContext ctx; - QEMUGLParams qparams; - - qparams.major_ver = params->major_ver; - qparams.minor_ver = params->minor_ver; - - ctx = dpy_gl_ctx_create(g->scanout[scanout_idx].con, &qparams); - return (virgl_renderer_gl_context)ctx; -} - -static void virgl_destroy_context(void *opaque, virgl_renderer_gl_context ctx) -{ - VirtIOGPU *g = opaque; - QEMUGLContext qctx = (QEMUGLContext)ctx; - - dpy_gl_ctx_destroy(g->scanout[0].con, qctx); -} - -static int virgl_make_context_current(void *opaque, int scanout_idx, - virgl_renderer_gl_context ctx) -{ - VirtIOGPU *g = opaque; - QEMUGLContext qctx = (QEMUGLContext)ctx; - - return dpy_gl_ctx_make_current(g->scanout[scanout_idx].con, qctx); -} - -static struct virgl_renderer_callbacks virtio_gpu_3d_cbs = { - .version = 1, - .write_fence = virgl_write_fence, - .create_gl_context = virgl_create_context, - .destroy_gl_context = virgl_destroy_context, - .make_current = virgl_make_context_current, -}; - -static void virtio_gpu_print_stats(void *opaque) -{ - VirtIOGPU *g = opaque; - - if (g->stats.requests) { - fprintf(stderr, "stats: vq req %4d, %3d -- 3D %4d (%5d)\n", - g->stats.requests, - g->stats.max_inflight, - g->stats.req_3d, - g->stats.bytes_3d); - g->stats.requests = 0; - g->stats.max_inflight = 0; - g->stats.req_3d = 0; - g->stats.bytes_3d = 0; - } else { - fprintf(stderr, "stats: idle\r"); - } - timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000); -} - -static void virtio_gpu_fence_poll(void *opaque) -{ - VirtIOGPU *g = opaque; - - virgl_renderer_poll(); - virtio_gpu_process_cmdq(g); - if (!QTAILQ_EMPTY(&g->cmdq) || !QTAILQ_EMPTY(&g->fenceq)) { - timer_mod(g->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10); - } -} - -void virtio_gpu_virgl_fence_poll(VirtIOGPU *g) -{ - virtio_gpu_fence_poll(g); -} - -void virtio_gpu_virgl_reset(VirtIOGPU *g) -{ - int i; - - /* virgl_renderer_reset() ??? */ - for (i = 0; i < g->conf.max_outputs; i++) { - if (i != 0) { - dpy_gfx_replace_surface(g->scanout[i].con, NULL); - } - dpy_gl_scanout(g->scanout[i].con, 0, false, 0, 0, 0, 0); - } -} - -int virtio_gpu_virgl_init(VirtIOGPU *g) -{ - int ret; - - ret = virgl_renderer_init(g, 0, &virtio_gpu_3d_cbs); - if (ret != 0) { - return ret; - } - - g->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL, - virtio_gpu_fence_poll, g); - - if (virtio_gpu_stats_enabled(g->conf)) { - g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL, - virtio_gpu_print_stats, g); - timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000); - } - return 0; -} - -#endif /* CONFIG_VIRGL */ diff --git a/qemu/hw/display/virtio-gpu-pci.c b/qemu/hw/display/virtio-gpu-pci.c deleted file mode 100644 index a71b230d3..000000000 --- a/qemu/hw/display/virtio-gpu-pci.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Virtio video device - * - * Copyright Red Hat - * - * Authors: - * Dave Airlie - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ -#include "qemu/osdep.h" -#include "hw/pci/pci.h" -#include "hw/virtio/virtio.h" -#include "hw/virtio/virtio-bus.h" -#include "hw/virtio/virtio-pci.h" -#include "hw/virtio/virtio-gpu.h" - -static Property virtio_gpu_pci_properties[] = { - DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy), - DEFINE_PROP_END_OF_LIST(), -}; - -static void virtio_gpu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) -{ - VirtIOGPUPCI *vgpu = VIRTIO_GPU_PCI(vpci_dev); - VirtIOGPU *g = &vgpu->vdev; - DeviceState *vdev = DEVICE(&vgpu->vdev); - int i; - - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - /* force virtio-1.0 */ - vpci_dev->flags &= ~VIRTIO_PCI_FLAG_DISABLE_MODERN; - vpci_dev->flags |= VIRTIO_PCI_FLAG_DISABLE_LEGACY; - object_property_set_bool(OBJECT(vdev), true, "realized", errp); - - for (i = 0; i < g->conf.max_outputs; i++) { - object_property_set_link(OBJECT(g->scanout[i].con), - OBJECT(vpci_dev), - "device", errp); - } -} - -static void virtio_gpu_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); - dc->props = virtio_gpu_pci_properties; - k->realize = virtio_gpu_pci_realize; - pcidev_k->class_id = PCI_CLASS_DISPLAY_OTHER; -} - -static void virtio_gpu_initfn(Object *obj) -{ - VirtIOGPUPCI *dev = VIRTIO_GPU_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_GPU); -} - -static const TypeInfo virtio_gpu_pci_info = { - .name = TYPE_VIRTIO_GPU_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VirtIOGPUPCI), - .instance_init = virtio_gpu_initfn, - .class_init = virtio_gpu_pci_class_init, -}; - -static void virtio_gpu_pci_register_types(void) -{ - type_register_static(&virtio_gpu_pci_info); -} -type_init(virtio_gpu_pci_register_types) diff --git a/qemu/hw/display/virtio-gpu.c b/qemu/hw/display/virtio-gpu.c deleted file mode 100644 index c181fb364..000000000 --- a/qemu/hw/display/virtio-gpu.c +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * Virtio GPU Device - * - * Copyright Red Hat, Inc. 2013-2014 - * - * Authors: - * Dave Airlie - * Gerd Hoffmann - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "qemu/iov.h" -#include "ui/console.h" -#include "trace.h" -#include "hw/virtio/virtio.h" -#include "hw/virtio/virtio-gpu.h" -#include "hw/virtio/virtio-bus.h" - -static struct virtio_gpu_simple_resource* -virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id); - -#ifdef CONFIG_VIRGL -#include "virglrenderer.h" -#define VIRGL(_g, _virgl, _simple, ...) \ - do { \ - if (_g->use_virgl_renderer) { \ - _virgl(__VA_ARGS__); \ - } else { \ - _simple(__VA_ARGS__); \ - } \ - } while (0) -#else -#define VIRGL(_g, _virgl, _simple, ...) \ - do { \ - _simple(__VA_ARGS__); \ - } while (0) -#endif - -static void update_cursor_data_simple(VirtIOGPU *g, - struct virtio_gpu_scanout *s, - uint32_t resource_id) -{ - struct virtio_gpu_simple_resource *res; - uint32_t pixels; - - res = virtio_gpu_find_resource(g, resource_id); - if (!res) { - return; - } - - if (pixman_image_get_width(res->image) != s->current_cursor->width || - pixman_image_get_height(res->image) != s->current_cursor->height) { - return; - } - - pixels = s->current_cursor->width * s->current_cursor->height; - memcpy(s->current_cursor->data, - pixman_image_get_data(res->image), - pixels * sizeof(uint32_t)); -} - -#ifdef CONFIG_VIRGL - -static void update_cursor_data_virgl(VirtIOGPU *g, - struct virtio_gpu_scanout *s, - uint32_t resource_id) -{ - uint32_t width, height; - uint32_t pixels, *data; - - data = virgl_renderer_get_cursor_data(resource_id, &width, &height); - if (!data) { - return; - } - - if (width != s->current_cursor->width || - height != s->current_cursor->height) { - return; - } - - pixels = s->current_cursor->width * s->current_cursor->height; - memcpy(s->current_cursor->data, data, pixels * sizeof(uint32_t)); - free(data); -} - -#endif - -static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor) -{ - struct virtio_gpu_scanout *s; - bool move = cursor->hdr.type != VIRTIO_GPU_CMD_MOVE_CURSOR; - - if (cursor->pos.scanout_id >= g->conf.max_outputs) { - return; - } - s = &g->scanout[cursor->pos.scanout_id]; - - trace_virtio_gpu_update_cursor(cursor->pos.scanout_id, - cursor->pos.x, - cursor->pos.y, - move ? "move" : "update", - cursor->resource_id); - - if (move) { - if (!s->current_cursor) { - s->current_cursor = cursor_alloc(64, 64); - } - - s->current_cursor->hot_x = cursor->hot_x; - s->current_cursor->hot_y = cursor->hot_y; - - if (cursor->resource_id > 0) { - VIRGL(g, update_cursor_data_virgl, update_cursor_data_simple, - g, s, cursor->resource_id); - } - dpy_cursor_define(s->con, s->current_cursor); - } - dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y, - cursor->resource_id ? 1 : 0); -} - -static void virtio_gpu_get_config(VirtIODevice *vdev, uint8_t *config) -{ - VirtIOGPU *g = VIRTIO_GPU(vdev); - memcpy(config, &g->virtio_config, sizeof(g->virtio_config)); -} - -static void virtio_gpu_set_config(VirtIODevice *vdev, const uint8_t *config) -{ - VirtIOGPU *g = VIRTIO_GPU(vdev); - struct virtio_gpu_config vgconfig; - - memcpy(&vgconfig, config, sizeof(g->virtio_config)); - - if (vgconfig.events_clear) { - g->virtio_config.events_read &= ~vgconfig.events_clear; - } -} - -static uint64_t virtio_gpu_get_features(VirtIODevice *vdev, uint64_t features, - Error **errp) -{ - VirtIOGPU *g = VIRTIO_GPU(vdev); - - if (virtio_gpu_virgl_enabled(g->conf)) { - features |= (1 << VIRTIO_GPU_F_VIRGL); - } - return features; -} - -static void virtio_gpu_set_features(VirtIODevice *vdev, uint64_t features) -{ - static const uint32_t virgl = (1 << VIRTIO_GPU_F_VIRGL); - VirtIOGPU *g = VIRTIO_GPU(vdev); - - g->use_virgl_renderer = ((features & virgl) == virgl); - trace_virtio_gpu_features(g->use_virgl_renderer); -} - -static void virtio_gpu_notify_event(VirtIOGPU *g, uint32_t event_type) -{ - g->virtio_config.events_read |= event_type; - virtio_notify_config(&g->parent_obj); -} - -static struct virtio_gpu_simple_resource * -virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id) -{ - struct virtio_gpu_simple_resource *res; - - QTAILQ_FOREACH(res, &g->reslist, next) { - if (res->resource_id == resource_id) { - return res; - } - } - return NULL; -} - -void virtio_gpu_ctrl_response(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd, - struct virtio_gpu_ctrl_hdr *resp, - size_t resp_len) -{ - size_t s; - - if (cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE) { - resp->flags |= VIRTIO_GPU_FLAG_FENCE; - resp->fence_id = cmd->cmd_hdr.fence_id; - resp->ctx_id = cmd->cmd_hdr.ctx_id; - } - s = iov_from_buf(cmd->elem.in_sg, cmd->elem.in_num, 0, resp, resp_len); - if (s != resp_len) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: response size incorrect %zu vs %zu\n", - __func__, s, resp_len); - } - virtqueue_push(cmd->vq, &cmd->elem, s); - virtio_notify(VIRTIO_DEVICE(g), cmd->vq); - cmd->finished = true; -} - -void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd, - enum virtio_gpu_ctrl_type type) -{ - struct virtio_gpu_ctrl_hdr resp; - - memset(&resp, 0, sizeof(resp)); - resp.type = type; - virtio_gpu_ctrl_response(g, cmd, &resp, sizeof(resp)); -} - -static void -virtio_gpu_fill_display_info(VirtIOGPU *g, - struct virtio_gpu_resp_display_info *dpy_info) -{ - int i; - - for (i = 0; i < g->conf.max_outputs; i++) { - if (g->enabled_output_bitmask & (1 << i)) { - dpy_info->pmodes[i].enabled = 1; - dpy_info->pmodes[i].r.width = g->req_state[i].width; - dpy_info->pmodes[i].r.height = g->req_state[i].height; - } - } -} - -void virtio_gpu_get_display_info(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_resp_display_info display_info; - - trace_virtio_gpu_cmd_get_display_info(); - memset(&display_info, 0, sizeof(display_info)); - display_info.hdr.type = VIRTIO_GPU_RESP_OK_DISPLAY_INFO; - virtio_gpu_fill_display_info(g, &display_info); - virtio_gpu_ctrl_response(g, cmd, &display_info.hdr, - sizeof(display_info)); -} - -static pixman_format_code_t get_pixman_format(uint32_t virtio_gpu_format) -{ - switch (virtio_gpu_format) { -#ifdef HOST_WORDS_BIGENDIAN - case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM: - return PIXMAN_b8g8r8x8; - case VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM: - return PIXMAN_b8g8r8a8; - case VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM: - return PIXMAN_x8r8g8b8; - case VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM: - return PIXMAN_a8r8g8b8; - case VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM: - return PIXMAN_r8g8b8x8; - case VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM: - return PIXMAN_r8g8b8a8; - case VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM: - return PIXMAN_x8b8g8r8; - case VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM: - return PIXMAN_a8b8g8r8; -#else - case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM: - return PIXMAN_x8r8g8b8; - case VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM: - return PIXMAN_a8r8g8b8; - case VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM: - return PIXMAN_b8g8r8x8; - case VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM: - return PIXMAN_b8g8r8a8; - case VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM: - return PIXMAN_x8b8g8r8; - case VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM: - return PIXMAN_a8b8g8r8; - case VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM: - return PIXMAN_r8g8b8x8; - case VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM: - return PIXMAN_r8g8b8a8; -#endif - default: - return 0; - } -} - -static void virtio_gpu_resource_create_2d(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - pixman_format_code_t pformat; - struct virtio_gpu_simple_resource *res; - struct virtio_gpu_resource_create_2d c2d; - - VIRTIO_GPU_FILL_CMD(c2d); - trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format, - c2d.width, c2d.height); - - if (c2d.resource_id == 0) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n", - __func__); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - res = virtio_gpu_find_resource(g, c2d.resource_id); - if (res) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n", - __func__, c2d.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - res = g_new0(struct virtio_gpu_simple_resource, 1); - - res->width = c2d.width; - res->height = c2d.height; - res->format = c2d.format; - res->resource_id = c2d.resource_id; - - pformat = get_pixman_format(c2d.format); - if (!pformat) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: host couldn't handle guest format %d\n", - __func__, c2d.format); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; - return; - } - res->image = pixman_image_create_bits(pformat, - c2d.width, - c2d.height, - NULL, 0); - - if (!res->image) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: resource creation failed %d %d %d\n", - __func__, c2d.resource_id, c2d.width, c2d.height); - g_free(res); - cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY; - return; - } - - QTAILQ_INSERT_HEAD(&g->reslist, res, next); -} - -static void virtio_gpu_resource_destroy(VirtIOGPU *g, - struct virtio_gpu_simple_resource *res) -{ - pixman_image_unref(res->image); - QTAILQ_REMOVE(&g->reslist, res, next); - g_free(res); -} - -static void virtio_gpu_resource_unref(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res; - struct virtio_gpu_resource_unref unref; - - VIRTIO_GPU_FILL_CMD(unref); - trace_virtio_gpu_cmd_res_unref(unref.resource_id); - - res = virtio_gpu_find_resource(g, unref.resource_id); - if (!res) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n", - __func__, unref.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - virtio_gpu_resource_destroy(g, res); -} - -static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res; - int h; - uint32_t src_offset, dst_offset, stride; - int bpp; - pixman_format_code_t format; - struct virtio_gpu_transfer_to_host_2d t2d; - - VIRTIO_GPU_FILL_CMD(t2d); - trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id); - - res = virtio_gpu_find_resource(g, t2d.resource_id); - if (!res || !res->iov) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n", - __func__, t2d.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - if (t2d.r.x > res->width || - t2d.r.y > res->height || - t2d.r.width > res->width || - t2d.r.height > res->height || - t2d.r.x + t2d.r.width > res->width || - t2d.r.y + t2d.r.height > res->height) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: transfer bounds outside resource" - " bounds for resource %d: %d %d %d %d vs %d %d\n", - __func__, t2d.resource_id, t2d.r.x, t2d.r.y, - t2d.r.width, t2d.r.height, res->width, res->height); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; - return; - } - - format = pixman_image_get_format(res->image); - bpp = (PIXMAN_FORMAT_BPP(format) + 7) / 8; - stride = pixman_image_get_stride(res->image); - - if (t2d.offset || t2d.r.x || t2d.r.y || - t2d.r.width != pixman_image_get_width(res->image)) { - void *img_data = pixman_image_get_data(res->image); - for (h = 0; h < t2d.r.height; h++) { - src_offset = t2d.offset + stride * h; - dst_offset = (t2d.r.y + h) * stride + (t2d.r.x * bpp); - - iov_to_buf(res->iov, res->iov_cnt, src_offset, - (uint8_t *)img_data - + dst_offset, t2d.r.width * bpp); - } - } else { - iov_to_buf(res->iov, res->iov_cnt, 0, - pixman_image_get_data(res->image), - pixman_image_get_stride(res->image) - * pixman_image_get_height(res->image)); - } -} - -static void virtio_gpu_resource_flush(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res; - struct virtio_gpu_resource_flush rf; - pixman_region16_t flush_region; - int i; - - VIRTIO_GPU_FILL_CMD(rf); - trace_virtio_gpu_cmd_res_flush(rf.resource_id, - rf.r.width, rf.r.height, rf.r.x, rf.r.y); - - res = virtio_gpu_find_resource(g, rf.resource_id); - if (!res) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n", - __func__, rf.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - if (rf.r.x > res->width || - rf.r.y > res->height || - rf.r.width > res->width || - rf.r.height > res->height || - rf.r.x + rf.r.width > res->width || - rf.r.y + rf.r.height > res->height) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: flush bounds outside resource" - " bounds for resource %d: %d %d %d %d vs %d %d\n", - __func__, rf.resource_id, rf.r.x, rf.r.y, - rf.r.width, rf.r.height, res->width, res->height); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; - return; - } - - pixman_region_init_rect(&flush_region, - rf.r.x, rf.r.y, rf.r.width, rf.r.height); - for (i = 0; i < VIRTIO_GPU_MAX_SCANOUT; i++) { - struct virtio_gpu_scanout *scanout; - pixman_region16_t region, finalregion; - pixman_box16_t *extents; - - if (!(res->scanout_bitmask & (1 << i))) { - continue; - } - scanout = &g->scanout[i]; - - pixman_region_init(&finalregion); - pixman_region_init_rect(®ion, scanout->x, scanout->y, - scanout->width, scanout->height); - - pixman_region_intersect(&finalregion, &flush_region, ®ion); - pixman_region_translate(&finalregion, -scanout->x, -scanout->y); - extents = pixman_region_extents(&finalregion); - /* work out the area we need to update for each console */ - dpy_gfx_update(g->scanout[i].con, - extents->x1, extents->y1, - extents->x2 - extents->x1, - extents->y2 - extents->y1); - - pixman_region_fini(®ion); - pixman_region_fini(&finalregion); - } - pixman_region_fini(&flush_region); -} - -static void virtio_gpu_set_scanout(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res; - struct virtio_gpu_scanout *scanout; - pixman_format_code_t format; - uint32_t offset; - int bpp; - struct virtio_gpu_set_scanout ss; - - VIRTIO_GPU_FILL_CMD(ss); - trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id, - ss.r.width, ss.r.height, ss.r.x, ss.r.y); - - g->enable = 1; - if (ss.resource_id == 0) { - scanout = &g->scanout[ss.scanout_id]; - if (scanout->resource_id) { - res = virtio_gpu_find_resource(g, scanout->resource_id); - if (res) { - res->scanout_bitmask &= ~(1 << ss.scanout_id); - } - } - if (ss.scanout_id == 0 || - ss.scanout_id >= g->conf.max_outputs) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: illegal scanout id specified %d", - __func__, ss.scanout_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID; - return; - } - dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, NULL); - scanout->ds = NULL; - scanout->width = 0; - scanout->height = 0; - return; - } - - /* create a surface for this scanout */ - if (ss.scanout_id >= VIRTIO_GPU_MAX_SCANOUT || - ss.scanout_id >= g->conf.max_outputs) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d", - __func__, ss.scanout_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID; - return; - } - - res = virtio_gpu_find_resource(g, ss.resource_id); - if (!res) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n", - __func__, ss.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - if (ss.r.x > res->width || - ss.r.y > res->height || - ss.r.width > res->width || - ss.r.height > res->height || - ss.r.x + ss.r.width > res->width || - ss.r.y + ss.r.height > res->height) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for" - " resource %d, (%d,%d)+%d,%d vs %d %d\n", - __func__, ss.scanout_id, ss.resource_id, ss.r.x, ss.r.y, - ss.r.width, ss.r.height, res->width, res->height); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; - return; - } - - scanout = &g->scanout[ss.scanout_id]; - - format = pixman_image_get_format(res->image); - bpp = (PIXMAN_FORMAT_BPP(format) + 7) / 8; - offset = (ss.r.x * bpp) + ss.r.y * pixman_image_get_stride(res->image); - if (!scanout->ds || surface_data(scanout->ds) - != ((uint8_t *)pixman_image_get_data(res->image) + offset) || - scanout->width != ss.r.width || - scanout->height != ss.r.height) { - /* realloc the surface ptr */ - scanout->ds = qemu_create_displaysurface_pixman(res->image); - if (!scanout->ds) { - cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; - return; - } - dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, scanout->ds); - } - - res->scanout_bitmask |= (1 << ss.scanout_id); - scanout->resource_id = ss.resource_id; - scanout->x = ss.r.x; - scanout->y = ss.r.y; - scanout->width = ss.r.width; - scanout->height = ss.r.height; -} - -int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, - struct virtio_gpu_ctrl_command *cmd, - struct iovec **iov) -{ - struct virtio_gpu_mem_entry *ents; - size_t esize, s; - int i; - - if (ab->nr_entries > 16384) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: nr_entries is too big (%d > 16384)\n", - __func__, ab->nr_entries); - return -1; - } - - esize = sizeof(*ents) * ab->nr_entries; - ents = g_malloc(esize); - s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, - sizeof(*ab), ents, esize); - if (s != esize) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: command data size incorrect %zu vs %zu\n", - __func__, s, esize); - g_free(ents); - return -1; - } - - *iov = g_malloc0(sizeof(struct iovec) * ab->nr_entries); - for (i = 0; i < ab->nr_entries; i++) { - hwaddr len = ents[i].length; - (*iov)[i].iov_len = ents[i].length; - (*iov)[i].iov_base = cpu_physical_memory_map(ents[i].addr, &len, 1); - if (!(*iov)[i].iov_base || len != ents[i].length) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for" - " resource %d element %d\n", - __func__, ab->resource_id, i); - virtio_gpu_cleanup_mapping_iov(*iov, i); - g_free(ents); - *iov = NULL; - return -1; - } - } - g_free(ents); - return 0; -} - -void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count) -{ - int i; - - for (i = 0; i < count; i++) { - cpu_physical_memory_unmap(iov[i].iov_base, iov[i].iov_len, 1, - iov[i].iov_len); - } - g_free(iov); -} - -static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res) -{ - virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt); - res->iov = NULL; - res->iov_cnt = 0; -} - -static void -virtio_gpu_resource_attach_backing(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res; - struct virtio_gpu_resource_attach_backing ab; - int ret; - - VIRTIO_GPU_FILL_CMD(ab); - trace_virtio_gpu_cmd_res_back_attach(ab.resource_id); - - res = virtio_gpu_find_resource(g, ab.resource_id); - if (!res) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n", - __func__, ab.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->iov); - if (ret != 0) { - cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; - return; - } - - res->iov_cnt = ab.nr_entries; -} - -static void -virtio_gpu_resource_detach_backing(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res; - struct virtio_gpu_resource_detach_backing detach; - - VIRTIO_GPU_FILL_CMD(detach); - trace_virtio_gpu_cmd_res_back_detach(detach.resource_id); - - res = virtio_gpu_find_resource(g, detach.resource_id); - if (!res || !res->iov) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n", - __func__, detach.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - virtio_gpu_cleanup_mapping(res); -} - -static void virtio_gpu_simple_process_cmd(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) -{ - VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr); - - switch (cmd->cmd_hdr.type) { - case VIRTIO_GPU_CMD_GET_DISPLAY_INFO: - virtio_gpu_get_display_info(g, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D: - virtio_gpu_resource_create_2d(g, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_UNREF: - virtio_gpu_resource_unref(g, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_FLUSH: - virtio_gpu_resource_flush(g, cmd); - break; - case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D: - virtio_gpu_transfer_to_host_2d(g, cmd); - break; - case VIRTIO_GPU_CMD_SET_SCANOUT: - virtio_gpu_set_scanout(g, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING: - virtio_gpu_resource_attach_backing(g, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING: - virtio_gpu_resource_detach_backing(g, cmd); - break; - default: - cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; - break; - } - if (!cmd->finished) { - virtio_gpu_ctrl_response_nodata(g, cmd, cmd->error ? cmd->error : - VIRTIO_GPU_RESP_OK_NODATA); - } -} - -static void virtio_gpu_handle_ctrl_cb(VirtIODevice *vdev, VirtQueue *vq) -{ - VirtIOGPU *g = VIRTIO_GPU(vdev); - qemu_bh_schedule(g->ctrl_bh); -} - -static void virtio_gpu_handle_cursor_cb(VirtIODevice *vdev, VirtQueue *vq) -{ - VirtIOGPU *g = VIRTIO_GPU(vdev); - qemu_bh_schedule(g->cursor_bh); -} - -void virtio_gpu_process_cmdq(VirtIOGPU *g) -{ - struct virtio_gpu_ctrl_command *cmd; - - while (!QTAILQ_EMPTY(&g->cmdq)) { - cmd = QTAILQ_FIRST(&g->cmdq); - - /* process command */ - VIRGL(g, virtio_gpu_virgl_process_cmd, virtio_gpu_simple_process_cmd, - g, cmd); - if (cmd->waiting) { - break; - } - QTAILQ_REMOVE(&g->cmdq, cmd, next); - if (virtio_gpu_stats_enabled(g->conf)) { - g->stats.requests++; - } - - if (!cmd->finished) { - QTAILQ_INSERT_TAIL(&g->fenceq, cmd, next); - g->inflight++; - if (virtio_gpu_stats_enabled(g->conf)) { - if (g->stats.max_inflight < g->inflight) { - g->stats.max_inflight = g->inflight; - } - fprintf(stderr, "inflight: %3d (+)\r", g->inflight); - } - } else { - g_free(cmd); - } - } -} - -static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) -{ - VirtIOGPU *g = VIRTIO_GPU(vdev); - struct virtio_gpu_ctrl_command *cmd; - - if (!virtio_queue_ready(vq)) { - return; - } - -#ifdef CONFIG_VIRGL - if (!g->renderer_inited && g->use_virgl_renderer) { - virtio_gpu_virgl_init(g); - g->renderer_inited = true; - } -#endif - - cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command)); - while (cmd) { - cmd->vq = vq; - cmd->error = 0; - cmd->finished = false; - cmd->waiting = false; - QTAILQ_INSERT_TAIL(&g->cmdq, cmd, next); - cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command)); - } - - virtio_gpu_process_cmdq(g); - -#ifdef CONFIG_VIRGL - if (g->use_virgl_renderer) { - virtio_gpu_virgl_fence_poll(g); - } -#endif -} - -static void virtio_gpu_ctrl_bh(void *opaque) -{ - VirtIOGPU *g = opaque; - virtio_gpu_handle_ctrl(&g->parent_obj, g->ctrl_vq); -} - -static void virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq) -{ - VirtIOGPU *g = VIRTIO_GPU(vdev); - VirtQueueElement *elem; - size_t s; - struct virtio_gpu_update_cursor cursor_info; - - if (!virtio_queue_ready(vq)) { - return; - } - for (;;) { - elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); - if (!elem) { - break; - } - - s = iov_to_buf(elem->out_sg, elem->out_num, 0, - &cursor_info, sizeof(cursor_info)); - if (s != sizeof(cursor_info)) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: cursor size incorrect %zu vs %zu\n", - __func__, s, sizeof(cursor_info)); - } else { - update_cursor(g, &cursor_info); - } - virtqueue_push(vq, elem, 0); - virtio_notify(vdev, vq); - g_free(elem); - } -} - -static void virtio_gpu_cursor_bh(void *opaque) -{ - VirtIOGPU *g = opaque; - virtio_gpu_handle_cursor(&g->parent_obj, g->cursor_vq); -} - -static void virtio_gpu_invalidate_display(void *opaque) -{ -} - -static void virtio_gpu_update_display(void *opaque) -{ -} - -static void virtio_gpu_text_update(void *opaque, console_ch_t *chardata) -{ -} - -static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) -{ - VirtIOGPU *g = opaque; - - if (idx > g->conf.max_outputs) { - return -1; - } - - g->req_state[idx].x = info->xoff; - g->req_state[idx].y = info->yoff; - g->req_state[idx].width = info->width; - g->req_state[idx].height = info->height; - - if (info->width && info->height) { - g->enabled_output_bitmask |= (1 << idx); - } else { - g->enabled_output_bitmask &= ~(1 << idx); - } - - /* send event to guest */ - virtio_gpu_notify_event(g, VIRTIO_GPU_EVENT_DISPLAY); - return 0; -} - -static void virtio_gpu_gl_block(void *opaque, bool block) -{ - VirtIOGPU *g = opaque; - - g->renderer_blocked = block; - if (!block) { - virtio_gpu_process_cmdq(g); - } -} - -const GraphicHwOps virtio_gpu_ops = { - .invalidate = virtio_gpu_invalidate_display, - .gfx_update = virtio_gpu_update_display, - .text_update = virtio_gpu_text_update, - .ui_info = virtio_gpu_ui_info, - .gl_block = virtio_gpu_gl_block, -}; - -static const VMStateDescription vmstate_virtio_gpu_unmigratable = { - .name = "virtio-gpu", - .unmigratable = 1, -}; - -static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) -{ - VirtIODevice *vdev = VIRTIO_DEVICE(qdev); - VirtIOGPU *g = VIRTIO_GPU(qdev); - bool have_virgl; - int i; - - g->config_size = sizeof(struct virtio_gpu_config); - g->virtio_config.num_scanouts = g->conf.max_outputs; - virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU, - g->config_size); - - g->req_state[0].width = 1024; - g->req_state[0].height = 768; - - g->use_virgl_renderer = false; -#if !defined(CONFIG_VIRGL) || defined(HOST_WORDS_BIGENDIAN) - have_virgl = false; -#else - have_virgl = display_opengl; -#endif - if (!have_virgl) { - g->conf.flags &= ~(1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED); - } - - if (virtio_gpu_virgl_enabled(g->conf)) { - /* use larger control queue in 3d mode */ - g->ctrl_vq = virtio_add_queue(vdev, 256, virtio_gpu_handle_ctrl_cb); - g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb); - g->virtio_config.num_capsets = 1; - } else { - g->ctrl_vq = virtio_add_queue(vdev, 64, virtio_gpu_handle_ctrl_cb); - g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb); - } - - g->ctrl_bh = qemu_bh_new(virtio_gpu_ctrl_bh, g); - g->cursor_bh = qemu_bh_new(virtio_gpu_cursor_bh, g); - QTAILQ_INIT(&g->reslist); - QTAILQ_INIT(&g->cmdq); - QTAILQ_INIT(&g->fenceq); - - g->enabled_output_bitmask = 1; - g->qdev = qdev; - - for (i = 0; i < g->conf.max_outputs; i++) { - g->scanout[i].con = - graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g); - if (i > 0) { - dpy_gfx_replace_surface(g->scanout[i].con, NULL); - } - } - - vmstate_register(qdev, -1, &vmstate_virtio_gpu_unmigratable, g); -} - -static void virtio_gpu_instance_init(Object *obj) -{ -} - -static void virtio_gpu_reset(VirtIODevice *vdev) -{ - VirtIOGPU *g = VIRTIO_GPU(vdev); - struct virtio_gpu_simple_resource *res, *tmp; - int i; - - g->enable = 0; - - QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) { - virtio_gpu_resource_destroy(g, res); - } - for (i = 0; i < g->conf.max_outputs; i++) { -#if 0 - g->req_state[i].x = 0; - g->req_state[i].y = 0; - if (i == 0) { - g->req_state[0].width = 1024; - g->req_state[0].height = 768; - } else { - g->req_state[i].width = 0; - g->req_state[i].height = 0; - } -#endif - g->scanout[i].resource_id = 0; - g->scanout[i].width = 0; - g->scanout[i].height = 0; - g->scanout[i].x = 0; - g->scanout[i].y = 0; - g->scanout[i].ds = NULL; - } - g->enabled_output_bitmask = 1; - -#ifdef CONFIG_VIRGL - if (g->use_virgl_renderer) { - virtio_gpu_virgl_reset(g); - g->use_virgl_renderer = 0; - } -#endif -} - -static Property virtio_gpu_properties[] = { - DEFINE_PROP_UINT32("max_outputs", VirtIOGPU, conf.max_outputs, 1), -#ifdef CONFIG_VIRGL - DEFINE_PROP_BIT("virgl", VirtIOGPU, conf.flags, - VIRTIO_GPU_FLAG_VIRGL_ENABLED, true), - DEFINE_PROP_BIT("stats", VirtIOGPU, conf.flags, - VIRTIO_GPU_FLAG_STATS_ENABLED, false), -#endif - DEFINE_PROP_END_OF_LIST(), -}; - -static void virtio_gpu_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); - - vdc->realize = virtio_gpu_device_realize; - vdc->get_config = virtio_gpu_get_config; - vdc->set_config = virtio_gpu_set_config; - vdc->get_features = virtio_gpu_get_features; - vdc->set_features = virtio_gpu_set_features; - - vdc->reset = virtio_gpu_reset; - - dc->props = virtio_gpu_properties; -} - -static const TypeInfo virtio_gpu_info = { - .name = TYPE_VIRTIO_GPU, - .parent = TYPE_VIRTIO_DEVICE, - .instance_size = sizeof(VirtIOGPU), - .instance_init = virtio_gpu_instance_init, - .class_init = virtio_gpu_class_init, -}; - -static void virtio_register_types(void) -{ - type_register_static(&virtio_gpu_info); -} - -type_init(virtio_register_types) - -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctrl_hdr) != 24); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_update_cursor) != 56); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_unref) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_2d) != 40); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_set_scanout) != 48); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_flush) != 48); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_to_host_2d) != 56); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_mem_entry) != 16); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_attach_backing) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_detach_backing) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_display_info) != 408); - -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_host_3d) != 72); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_3d) != 72); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_create) != 96); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_destroy) != 24); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_resource) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_cmd_submit) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset_info) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset_info) != 40); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset) != 24); diff --git a/qemu/hw/display/virtio-vga.c b/qemu/hw/display/virtio-vga.c deleted file mode 100644 index e58b165ae..000000000 --- a/qemu/hw/display/virtio-vga.c +++ /dev/null @@ -1,193 +0,0 @@ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/pci/pci.h" -#include "ui/console.h" -#include "vga_int.h" -#include "hw/virtio/virtio-pci.h" - -/* - * virtio-vga: This extends VirtioPCIProxy. - */ -#define TYPE_VIRTIO_VGA "virtio-vga" -#define VIRTIO_VGA(obj) \ - OBJECT_CHECK(VirtIOVGA, (obj), TYPE_VIRTIO_VGA) - -typedef struct VirtIOVGA { - VirtIOPCIProxy parent_obj; - VirtIOGPU vdev; - VGACommonState vga; - MemoryRegion vga_mrs[3]; -} VirtIOVGA; - -static void virtio_vga_invalidate_display(void *opaque) -{ - VirtIOVGA *vvga = opaque; - - if (vvga->vdev.enable) { - virtio_gpu_ops.invalidate(&vvga->vdev); - } else { - vvga->vga.hw_ops->invalidate(&vvga->vga); - } -} - -static void virtio_vga_update_display(void *opaque) -{ - VirtIOVGA *vvga = opaque; - - if (vvga->vdev.enable) { - virtio_gpu_ops.gfx_update(&vvga->vdev); - } else { - vvga->vga.hw_ops->gfx_update(&vvga->vga); - } -} - -static void virtio_vga_text_update(void *opaque, console_ch_t *chardata) -{ - VirtIOVGA *vvga = opaque; - - if (vvga->vdev.enable) { - if (virtio_gpu_ops.text_update) { - virtio_gpu_ops.text_update(&vvga->vdev, chardata); - } - } else { - if (vvga->vga.hw_ops->text_update) { - vvga->vga.hw_ops->text_update(&vvga->vga, chardata); - } - } -} - -static int virtio_vga_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) -{ - VirtIOVGA *vvga = opaque; - - if (virtio_gpu_ops.ui_info) { - return virtio_gpu_ops.ui_info(&vvga->vdev, idx, info); - } - return -1; -} - -static void virtio_vga_gl_block(void *opaque, bool block) -{ - VirtIOVGA *vvga = opaque; - - if (virtio_gpu_ops.gl_block) { - virtio_gpu_ops.gl_block(&vvga->vdev, block); - } -} - -static const GraphicHwOps virtio_vga_ops = { - .invalidate = virtio_vga_invalidate_display, - .gfx_update = virtio_vga_update_display, - .text_update = virtio_vga_text_update, - .ui_info = virtio_vga_ui_info, - .gl_block = virtio_vga_gl_block, -}; - -/* VGA device wrapper around PCI device around virtio GPU */ -static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp) -{ - VirtIOVGA *vvga = VIRTIO_VGA(vpci_dev); - VirtIOGPU *g = &vvga->vdev; - VGACommonState *vga = &vvga->vga; - uint32_t offset; - int i; - - /* init vga compat bits */ - vga->vram_size_mb = 8; - vga_common_init(vga, OBJECT(vpci_dev), false); - vga_init(vga, OBJECT(vpci_dev), pci_address_space(&vpci_dev->pci_dev), - pci_address_space_io(&vpci_dev->pci_dev), true); - pci_register_bar(&vpci_dev->pci_dev, 0, - PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram); - - /* - * Configure virtio bar and regions - * - * We use bar #2 for the mmio regions, to be compatible with stdvga. - * virtio regions are moved to the end of bar #2, to make room for - * the stdvga mmio registers at the start of bar #2. - */ - vpci_dev->modern_mem_bar = 2; - vpci_dev->msix_bar = 4; - offset = memory_region_size(&vpci_dev->modern_bar); - offset -= vpci_dev->notify.size; - vpci_dev->notify.offset = offset; - offset -= vpci_dev->device.size; - vpci_dev->device.offset = offset; - offset -= vpci_dev->isr.size; - vpci_dev->isr.offset = offset; - offset -= vpci_dev->common.size; - vpci_dev->common.offset = offset; - - /* init virtio bits */ - qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus)); - /* force virtio-1.0 */ - vpci_dev->flags &= ~VIRTIO_PCI_FLAG_DISABLE_MODERN; - vpci_dev->flags |= VIRTIO_PCI_FLAG_DISABLE_LEGACY; - object_property_set_bool(OBJECT(g), true, "realized", errp); - - /* add stdvga mmio regions */ - pci_std_vga_mmio_region_init(vga, &vpci_dev->modern_bar, - vvga->vga_mrs, true); - - vga->con = g->scanout[0].con; - graphic_console_set_hwops(vga->con, &virtio_vga_ops, vvga); - - for (i = 0; i < g->conf.max_outputs; i++) { - object_property_set_link(OBJECT(g->scanout[i].con), - OBJECT(vpci_dev), - "device", errp); - } -} - -static void virtio_vga_reset(DeviceState *dev) -{ - VirtIOVGA *vvga = VIRTIO_VGA(dev); - vvga->vdev.enable = 0; - - vga_dirty_log_start(&vvga->vga); -} - -static Property virtio_vga_properties[] = { - DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy), - DEFINE_PROP_END_OF_LIST(), -}; - -static void virtio_vga_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); - dc->props = virtio_vga_properties; - dc->reset = virtio_vga_reset; - dc->hotpluggable = false; - - k->realize = virtio_vga_realize; - pcidev_k->romfile = "vgabios-virtio.bin"; - pcidev_k->class_id = PCI_CLASS_DISPLAY_VGA; -} - -static void virtio_vga_inst_initfn(Object *obj) -{ - VirtIOVGA *dev = VIRTIO_VGA(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_GPU); -} - -static TypeInfo virtio_vga_info = { - .name = TYPE_VIRTIO_VGA, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(struct VirtIOVGA), - .instance_init = virtio_vga_inst_initfn, - .class_init = virtio_vga_class_init, -}; - -static void virtio_vga_register_types(void) -{ - type_register_static(&virtio_vga_info); -} - -type_init(virtio_vga_register_types) diff --git a/qemu/hw/display/vmware_vga.c b/qemu/hw/display/vmware_vga.c deleted file mode 100644 index 0c63fa851..000000000 --- a/qemu/hw/display/vmware_vga.c +++ /dev/null @@ -1,1370 +0,0 @@ -/* - * QEMU VMware-SVGA "chipset". - * - * Copyright (c) 2007 Andrzej Zaborowski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "hw/hw.h" -#include "hw/loader.h" -#include "trace.h" -#include "ui/console.h" -#include "ui/vnc.h" -#include "hw/pci/pci.h" - -#undef VERBOSE -#define HW_RECT_ACCEL -#define HW_FILL_ACCEL -#define HW_MOUSE_ACCEL - -#include "vga_int.h" - -/* See http://vmware-svga.sf.net/ for some documentation on VMWare SVGA */ - -struct vmsvga_state_s { - VGACommonState vga; - - int invalidated; - int enable; - int config; - struct { - int id; - int x; - int y; - int on; - } cursor; - - int index; - int scratch_size; - uint32_t *scratch; - int new_width; - int new_height; - int new_depth; - uint32_t guest; - uint32_t svgaid; - int syncing; - - MemoryRegion fifo_ram; - uint8_t *fifo_ptr; - unsigned int fifo_size; - - union { - uint32_t *fifo; - struct QEMU_PACKED { - uint32_t min; - uint32_t max; - uint32_t next_cmd; - uint32_t stop; - /* Add registers here when adding capabilities. */ - uint32_t fifo[0]; - } *cmd; - }; - -#define REDRAW_FIFO_LEN 512 - struct vmsvga_rect_s { - int x, y, w, h; - } redraw_fifo[REDRAW_FIFO_LEN]; - int redraw_fifo_first, redraw_fifo_last; -}; - -#define TYPE_VMWARE_SVGA "vmware-svga" - -#define VMWARE_SVGA(obj) \ - OBJECT_CHECK(struct pci_vmsvga_state_s, (obj), TYPE_VMWARE_SVGA) - -struct pci_vmsvga_state_s { - /*< private >*/ - PCIDevice parent_obj; - /*< public >*/ - - struct vmsvga_state_s chip; - MemoryRegion io_bar; -}; - -#define SVGA_MAGIC 0x900000UL -#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver)) -#define SVGA_ID_0 SVGA_MAKE_ID(0) -#define SVGA_ID_1 SVGA_MAKE_ID(1) -#define SVGA_ID_2 SVGA_MAKE_ID(2) - -#define SVGA_LEGACY_BASE_PORT 0x4560 -#define SVGA_INDEX_PORT 0x0 -#define SVGA_VALUE_PORT 0x1 -#define SVGA_BIOS_PORT 0x2 - -#define SVGA_VERSION_2 - -#ifdef SVGA_VERSION_2 -# define SVGA_ID SVGA_ID_2 -# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT -# define SVGA_IO_MUL 1 -# define SVGA_FIFO_SIZE 0x10000 -# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA2 -#else -# define SVGA_ID SVGA_ID_1 -# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT -# define SVGA_IO_MUL 4 -# define SVGA_FIFO_SIZE 0x10000 -# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA -#endif - -enum { - /* ID 0, 1 and 2 registers */ - SVGA_REG_ID = 0, - SVGA_REG_ENABLE = 1, - SVGA_REG_WIDTH = 2, - SVGA_REG_HEIGHT = 3, - SVGA_REG_MAX_WIDTH = 4, - SVGA_REG_MAX_HEIGHT = 5, - SVGA_REG_DEPTH = 6, - SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */ - SVGA_REG_PSEUDOCOLOR = 8, - SVGA_REG_RED_MASK = 9, - SVGA_REG_GREEN_MASK = 10, - SVGA_REG_BLUE_MASK = 11, - SVGA_REG_BYTES_PER_LINE = 12, - SVGA_REG_FB_START = 13, - SVGA_REG_FB_OFFSET = 14, - SVGA_REG_VRAM_SIZE = 15, - SVGA_REG_FB_SIZE = 16, - - /* ID 1 and 2 registers */ - SVGA_REG_CAPABILITIES = 17, - SVGA_REG_MEM_START = 18, /* Memory for command FIFO */ - SVGA_REG_MEM_SIZE = 19, - SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ - SVGA_REG_SYNC = 21, /* Write to force synchronization */ - SVGA_REG_BUSY = 22, /* Read to check if sync is done */ - SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */ - SVGA_REG_CURSOR_ID = 24, /* ID of cursor */ - SVGA_REG_CURSOR_X = 25, /* Set cursor X position */ - SVGA_REG_CURSOR_Y = 26, /* Set cursor Y position */ - SVGA_REG_CURSOR_ON = 27, /* Turn cursor on/off */ - SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* Current bpp in the host */ - SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */ - 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_PALETTE_BASE = 1024, /* Base of SVGA color map */ - SVGA_PALETTE_END = SVGA_PALETTE_BASE + 767, - SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + 768, -}; - -#define SVGA_CAP_NONE 0 -#define SVGA_CAP_RECT_FILL (1 << 0) -#define SVGA_CAP_RECT_COPY (1 << 1) -#define SVGA_CAP_RECT_PAT_FILL (1 << 2) -#define SVGA_CAP_LEGACY_OFFSCREEN (1 << 3) -#define SVGA_CAP_RASTER_OP (1 << 4) -#define SVGA_CAP_CURSOR (1 << 5) -#define SVGA_CAP_CURSOR_BYPASS (1 << 6) -#define SVGA_CAP_CURSOR_BYPASS_2 (1 << 7) -#define SVGA_CAP_8BIT_EMULATION (1 << 8) -#define SVGA_CAP_ALPHA_CURSOR (1 << 9) -#define SVGA_CAP_GLYPH (1 << 10) -#define SVGA_CAP_GLYPH_CLIPPING (1 << 11) -#define SVGA_CAP_OFFSCREEN_1 (1 << 12) -#define SVGA_CAP_ALPHA_BLEND (1 << 13) -#define SVGA_CAP_3D (1 << 14) -#define SVGA_CAP_EXTENDED_FIFO (1 << 15) -#define SVGA_CAP_MULTIMON (1 << 16) -#define SVGA_CAP_PITCHLOCK (1 << 17) - -/* - * FIFO offsets (seen as an array of 32-bit words) - */ -enum { - /* - * The original defined FIFO offsets - */ - SVGA_FIFO_MIN = 0, - SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */ - SVGA_FIFO_NEXT_CMD, - SVGA_FIFO_STOP, - - /* - * Additional offsets added as of SVGA_CAP_EXTENDED_FIFO - */ - SVGA_FIFO_CAPABILITIES = 4, - SVGA_FIFO_FLAGS, - SVGA_FIFO_FENCE, - SVGA_FIFO_3D_HWVERSION, - SVGA_FIFO_PITCHLOCK, -}; - -#define SVGA_FIFO_CAP_NONE 0 -#define SVGA_FIFO_CAP_FENCE (1 << 0) -#define SVGA_FIFO_CAP_ACCELFRONT (1 << 1) -#define SVGA_FIFO_CAP_PITCHLOCK (1 << 2) - -#define SVGA_FIFO_FLAG_NONE 0 -#define SVGA_FIFO_FLAG_ACCELFRONT (1 << 0) - -/* These values can probably be changed arbitrarily. */ -#define SVGA_SCRATCH_SIZE 0x8000 -#define SVGA_MAX_WIDTH ROUND_UP(2360, VNC_DIRTY_PIXELS_PER_BIT) -#define SVGA_MAX_HEIGHT 1770 - -#ifdef VERBOSE -# define GUEST_OS_BASE 0x5001 -static const char *vmsvga_guest_id[] = { - [0x00] = "Dos", - [0x01] = "Windows 3.1", - [0x02] = "Windows 95", - [0x03] = "Windows 98", - [0x04] = "Windows ME", - [0x05] = "Windows NT", - [0x06] = "Windows 2000", - [0x07] = "Linux", - [0x08] = "OS/2", - [0x09] = "an unknown OS", - [0x0a] = "BSD", - [0x0b] = "Whistler", - [0x0c] = "an unknown OS", - [0x0d] = "an unknown OS", - [0x0e] = "an unknown OS", - [0x0f] = "an unknown OS", - [0x10] = "an unknown OS", - [0x11] = "an unknown OS", - [0x12] = "an unknown OS", - [0x13] = "an unknown OS", - [0x14] = "an unknown OS", - [0x15] = "Windows 2003", -}; -#endif - -enum { - SVGA_CMD_INVALID_CMD = 0, - SVGA_CMD_UPDATE = 1, - SVGA_CMD_RECT_FILL = 2, - SVGA_CMD_RECT_COPY = 3, - SVGA_CMD_DEFINE_BITMAP = 4, - SVGA_CMD_DEFINE_BITMAP_SCANLINE = 5, - SVGA_CMD_DEFINE_PIXMAP = 6, - SVGA_CMD_DEFINE_PIXMAP_SCANLINE = 7, - SVGA_CMD_RECT_BITMAP_FILL = 8, - SVGA_CMD_RECT_PIXMAP_FILL = 9, - SVGA_CMD_RECT_BITMAP_COPY = 10, - SVGA_CMD_RECT_PIXMAP_COPY = 11, - SVGA_CMD_FREE_OBJECT = 12, - SVGA_CMD_RECT_ROP_FILL = 13, - SVGA_CMD_RECT_ROP_COPY = 14, - SVGA_CMD_RECT_ROP_BITMAP_FILL = 15, - SVGA_CMD_RECT_ROP_PIXMAP_FILL = 16, - SVGA_CMD_RECT_ROP_BITMAP_COPY = 17, - SVGA_CMD_RECT_ROP_PIXMAP_COPY = 18, - SVGA_CMD_DEFINE_CURSOR = 19, - SVGA_CMD_DISPLAY_CURSOR = 20, - SVGA_CMD_MOVE_CURSOR = 21, - SVGA_CMD_DEFINE_ALPHA_CURSOR = 22, - SVGA_CMD_DRAW_GLYPH = 23, - SVGA_CMD_DRAW_GLYPH_CLIPPED = 24, - SVGA_CMD_UPDATE_VERBOSE = 25, - SVGA_CMD_SURFACE_FILL = 26, - SVGA_CMD_SURFACE_COPY = 27, - SVGA_CMD_SURFACE_ALPHA_BLEND = 28, - SVGA_CMD_FRONT_ROP_FILL = 29, - SVGA_CMD_FENCE = 30, -}; - -/* Legal values for the SVGA_REG_CURSOR_ON register in cursor bypass mode */ -enum { - SVGA_CURSOR_ON_HIDE = 0, - SVGA_CURSOR_ON_SHOW = 1, - SVGA_CURSOR_ON_REMOVE_FROM_FB = 2, - SVGA_CURSOR_ON_RESTORE_TO_FB = 3, -}; - -static inline bool vmsvga_verify_rect(DisplaySurface *surface, - const char *name, - int x, int y, int w, int h) -{ - if (x < 0) { - fprintf(stderr, "%s: x was < 0 (%d)\n", name, x); - return false; - } - if (x > SVGA_MAX_WIDTH) { - fprintf(stderr, "%s: x was > %d (%d)\n", name, SVGA_MAX_WIDTH, x); - return false; - } - if (w < 0) { - fprintf(stderr, "%s: w was < 0 (%d)\n", name, w); - return false; - } - if (w > SVGA_MAX_WIDTH) { - fprintf(stderr, "%s: w was > %d (%d)\n", name, SVGA_MAX_WIDTH, w); - return false; - } - if (x + w > surface_width(surface)) { - fprintf(stderr, "%s: width was > %d (x: %d, w: %d)\n", - name, surface_width(surface), x, w); - return false; - } - - if (y < 0) { - fprintf(stderr, "%s: y was < 0 (%d)\n", name, y); - return false; - } - if (y > SVGA_MAX_HEIGHT) { - fprintf(stderr, "%s: y was > %d (%d)\n", name, SVGA_MAX_HEIGHT, y); - return false; - } - if (h < 0) { - fprintf(stderr, "%s: h was < 0 (%d)\n", name, h); - return false; - } - if (h > SVGA_MAX_HEIGHT) { - fprintf(stderr, "%s: h was > %d (%d)\n", name, SVGA_MAX_HEIGHT, h); - return false; - } - if (y + h > surface_height(surface)) { - fprintf(stderr, "%s: update height > %d (y: %d, h: %d)\n", - name, surface_height(surface), y, h); - return false; - } - - return true; -} - -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; - int start; - uint8_t *src; - uint8_t *dst; - - if (!vmsvga_verify_rect(surface, __func__, x, y, w, h)) { - /* go for a fullscreen update as fallback */ - x = 0; - y = 0; - w = surface_width(surface); - h = surface_height(surface); - } - - 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 = surface_data(surface) + start; - - for (line = h; line > 0; line--, src += bypl, dst += bypl) { - memcpy(dst, src, width); - } - dpy_gfx_update(s->vga.con, x, y, w, h); -} - -static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s, - int x, int y, int w, int h) -{ - struct vmsvga_rect_s *rect = &s->redraw_fifo[s->redraw_fifo_last++]; - - s->redraw_fifo_last &= REDRAW_FIFO_LEN - 1; - rect->x = x; - rect->y = y; - rect->w = w; - rect->h = h; -} - -static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s) -{ - struct vmsvga_rect_s *rect; - - if (s->invalidated) { - s->redraw_fifo_first = s->redraw_fifo_last; - return; - } - /* Overlapping region updates can be optimised out here - if someone - * knows a smart algorithm to do that, please share. */ - while (s->redraw_fifo_first != s->redraw_fifo_last) { - rect = &s->redraw_fifo[s->redraw_fifo_first++]; - s->redraw_fifo_first &= REDRAW_FIFO_LEN - 1; - vmsvga_update_rect(s, rect->x, rect->y, rect->w, rect->h); - } -} - -#ifdef HW_RECT_ACCEL -static inline int 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 = surface_stride(surface); - int bypp = surface_bytes_per_pixel(surface); - int width = bypp * w; - int line = h; - uint8_t *ptr[2]; - - if (!vmsvga_verify_rect(surface, "vmsvga_copy_rect/src", x0, y0, w, h)) { - return -1; - } - if (!vmsvga_verify_rect(surface, "vmsvga_copy_rect/dst", x1, y1, w, h)) { - return -1; - } - - if (y1 > y0) { - ptr[0] = vram + bypp * x0 + bypl * (y0 + h - 1); - ptr[1] = vram + bypp * x1 + bypl * (y1 + h - 1); - for (; line > 0; line --, ptr[0] -= bypl, ptr[1] -= bypl) { - memmove(ptr[1], ptr[0], width); - } - } else { - ptr[0] = vram + bypp * x0 + bypl * y0; - ptr[1] = vram + bypp * x1 + bypl * y1; - for (; line > 0; line --, ptr[0] += bypl, ptr[1] += bypl) { - memmove(ptr[1], ptr[0], width); - } - } - - vmsvga_update_rect_delayed(s, x1, y1, w, h); - return 0; -} -#endif - -#ifdef HW_FILL_ACCEL -static inline int vmsvga_fill_rect(struct vmsvga_state_s *s, - uint32_t c, int x, int y, int w, int h) -{ - 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; - uint8_t *dst; - uint8_t *src; - uint8_t col[4]; - - if (!vmsvga_verify_rect(surface, __func__, x, y, w, h)) { - return -1; - } - - col[0] = c; - col[1] = c >> 8; - col[2] = c >> 16; - col[3] = c >> 24; - - 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 == surface_bytes_per_pixel(surface)) { - src = col; - } - } - dst = fst; - for (; line > 0; line--) { - dst += bypl; - memcpy(dst, fst, width); - } - } - - vmsvga_update_rect_delayed(s, x, y, w, h); - return 0; -} -#endif - -struct vmsvga_cursor_definition_s { - uint32_t width; - uint32_t height; - int id; - uint32_t bpp; - int hot_x; - int hot_y; - uint32_t mask[1024]; - uint32_t image[4096]; -}; - -#define SVGA_BITMAP_SIZE(w, h) ((((w) + 31) >> 5) * (h)) -#define SVGA_PIXMAP_SIZE(w, h, bpp) (((((w) * (bpp)) + 31) >> 5) * (h)) - -#ifdef HW_MOUSE_ACCEL -static inline void vmsvga_cursor_define(struct vmsvga_state_s *s, - struct vmsvga_cursor_definition_s *c) -{ - QEMUCursor *qc; - int i, pixels; - - qc = cursor_alloc(c->width, c->height); - qc->hot_x = c->hot_x; - qc->hot_y = c->hot_y; - switch (c->bpp) { - case 1: - cursor_set_mono(qc, 0xffffff, 0x000000, (void *)c->image, - 1, (void *)c->mask); -#ifdef DEBUG - cursor_print_ascii_art(qc, "vmware/mono"); -#endif - break; - case 32: - /* fill alpha channel from mask, set color to zero */ - cursor_set_mono(qc, 0x000000, 0x000000, (void *)c->mask, - 1, (void *)c->mask); - /* add in rgb values */ - pixels = c->width * c->height; - for (i = 0; i < pixels; i++) { - qc->data[i] |= c->image[i] & 0xffffff; - } -#ifdef DEBUG - cursor_print_ascii_art(qc, "vmware/32bit"); -#endif - break; - default: - fprintf(stderr, "%s: unhandled bpp %d, using fallback cursor\n", - __func__, c->bpp); - cursor_put(qc); - qc = cursor_builtin_left_ptr(); - } - - dpy_cursor_define(s->vga.con, qc); - cursor_put(qc); -} -#endif - -#define CMD(f) le32_to_cpu(s->cmd->f) - -static inline int vmsvga_fifo_length(struct vmsvga_state_s *s) -{ - int num; - - if (!s->config || !s->enable) { - return 0; - } - num = CMD(next_cmd) - CMD(stop); - if (num < 0) { - num += CMD(max) - CMD(min); - } - return num >> 2; -} - -static inline uint32_t vmsvga_fifo_read_raw(struct vmsvga_state_s *s) -{ - uint32_t cmd = s->fifo[CMD(stop) >> 2]; - - s->cmd->stop = cpu_to_le32(CMD(stop) + 4); - if (CMD(stop) >= CMD(max)) { - s->cmd->stop = s->cmd->min; - } - return cmd; -} - -static inline uint32_t vmsvga_fifo_read(struct vmsvga_state_s *s) -{ - return le32_to_cpu(vmsvga_fifo_read_raw(s)); -} - -static void vmsvga_fifo_run(struct vmsvga_state_s *s) -{ - uint32_t cmd, colour; - int args, len; - int x, y, dx, dy, width, height; - struct vmsvga_cursor_definition_s cursor; - uint32_t cmd_start; - - len = vmsvga_fifo_length(s); - while (len > 0) { - /* May need to go back to the start of the command if incomplete */ - cmd_start = s->cmd->stop; - - switch (cmd = vmsvga_fifo_read(s)) { - case SVGA_CMD_UPDATE: - case SVGA_CMD_UPDATE_VERBOSE: - len -= 5; - if (len < 0) { - goto rewind; - } - - x = vmsvga_fifo_read(s); - y = vmsvga_fifo_read(s); - width = vmsvga_fifo_read(s); - height = vmsvga_fifo_read(s); - vmsvga_update_rect_delayed(s, x, y, width, height); - break; - - case SVGA_CMD_RECT_FILL: - len -= 6; - if (len < 0) { - goto rewind; - } - - colour = vmsvga_fifo_read(s); - x = vmsvga_fifo_read(s); - y = vmsvga_fifo_read(s); - width = vmsvga_fifo_read(s); - height = vmsvga_fifo_read(s); -#ifdef HW_FILL_ACCEL - if (vmsvga_fill_rect(s, colour, x, y, width, height) == 0) { - break; - } -#endif - args = 0; - goto badcmd; - - case SVGA_CMD_RECT_COPY: - len -= 7; - if (len < 0) { - goto rewind; - } - - x = vmsvga_fifo_read(s); - y = vmsvga_fifo_read(s); - dx = vmsvga_fifo_read(s); - dy = vmsvga_fifo_read(s); - width = vmsvga_fifo_read(s); - height = vmsvga_fifo_read(s); -#ifdef HW_RECT_ACCEL - if (vmsvga_copy_rect(s, x, y, dx, dy, width, height) == 0) { - break; - } -#endif - args = 0; - goto badcmd; - - case SVGA_CMD_DEFINE_CURSOR: - len -= 8; - if (len < 0) { - goto rewind; - } - - cursor.id = vmsvga_fifo_read(s); - cursor.hot_x = vmsvga_fifo_read(s); - cursor.hot_y = vmsvga_fifo_read(s); - cursor.width = x = vmsvga_fifo_read(s); - cursor.height = y = vmsvga_fifo_read(s); - vmsvga_fifo_read(s); - cursor.bpp = vmsvga_fifo_read(s); - - args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp); - if (cursor.width > 256 || - cursor.height > 256 || - cursor.bpp > 32 || - SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask || - SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) { - goto badcmd; - } - - len -= args; - if (len < 0) { - goto rewind; - } - - for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args++) { - cursor.mask[args] = vmsvga_fifo_read_raw(s); - } - for (args = 0; args < SVGA_PIXMAP_SIZE(x, y, cursor.bpp); args++) { - cursor.image[args] = vmsvga_fifo_read_raw(s); - } -#ifdef HW_MOUSE_ACCEL - vmsvga_cursor_define(s, &cursor); - break; -#else - args = 0; - goto badcmd; -#endif - - /* - * Other commands that we at least know the number of arguments - * for so we can avoid FIFO desync if driver uses them illegally. - */ - case SVGA_CMD_DEFINE_ALPHA_CURSOR: - len -= 6; - if (len < 0) { - goto rewind; - } - vmsvga_fifo_read(s); - vmsvga_fifo_read(s); - vmsvga_fifo_read(s); - x = vmsvga_fifo_read(s); - y = vmsvga_fifo_read(s); - args = x * y; - goto badcmd; - case SVGA_CMD_RECT_ROP_FILL: - args = 6; - goto badcmd; - case SVGA_CMD_RECT_ROP_COPY: - args = 7; - goto badcmd; - case SVGA_CMD_DRAW_GLYPH_CLIPPED: - len -= 4; - if (len < 0) { - goto rewind; - } - vmsvga_fifo_read(s); - vmsvga_fifo_read(s); - args = 7 + (vmsvga_fifo_read(s) >> 2); - goto badcmd; - case SVGA_CMD_SURFACE_ALPHA_BLEND: - args = 12; - goto badcmd; - - /* - * Other commands that are not listed as depending on any - * CAPABILITIES bits, but are not described in the README either. - */ - case SVGA_CMD_SURFACE_FILL: - case SVGA_CMD_SURFACE_COPY: - case SVGA_CMD_FRONT_ROP_FILL: - case SVGA_CMD_FENCE: - case SVGA_CMD_INVALID_CMD: - break; /* Nop */ - - default: - args = 0; - badcmd: - len -= args; - if (len < 0) { - goto rewind; - } - while (args--) { - vmsvga_fifo_read(s); - } - printf("%s: Unknown command 0x%02x in SVGA command FIFO\n", - __func__, cmd); - break; - - rewind: - s->cmd->stop = cmd_start; - break; - } - } - - s->syncing = 0; -} - -static uint32_t vmsvga_index_read(void *opaque, uint32_t address) -{ - struct vmsvga_state_s *s = opaque; - - return s->index; -} - -static void vmsvga_index_write(void *opaque, uint32_t address, uint32_t index) -{ - struct vmsvga_state_s *s = opaque; - - s->index = index; -} - -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); - PixelFormat pf; - uint32_t ret; - - switch (s->index) { - case SVGA_REG_ID: - ret = s->svgaid; - break; - - case SVGA_REG_ENABLE: - ret = s->enable; - break; - - case SVGA_REG_WIDTH: - ret = s->new_width ? s->new_width : surface_width(surface); - break; - - case SVGA_REG_HEIGHT: - ret = s->new_height ? s->new_height : surface_height(surface); - break; - - case SVGA_REG_MAX_WIDTH: - ret = SVGA_MAX_WIDTH; - break; - - case SVGA_REG_MAX_HEIGHT: - ret = SVGA_MAX_HEIGHT; - break; - - case SVGA_REG_DEPTH: - ret = (s->new_depth == 32) ? 24 : s->new_depth; - break; - - case SVGA_REG_BITS_PER_PIXEL: - case SVGA_REG_HOST_BITS_PER_PIXEL: - ret = s->new_depth; - break; - - case SVGA_REG_PSEUDOCOLOR: - ret = 0x0; - break; - - case SVGA_REG_RED_MASK: - pf = qemu_default_pixelformat(s->new_depth); - ret = pf.rmask; - break; - - case SVGA_REG_GREEN_MASK: - pf = qemu_default_pixelformat(s->new_depth); - ret = pf.gmask; - break; - - case SVGA_REG_BLUE_MASK: - pf = qemu_default_pixelformat(s->new_depth); - ret = pf.bmask; - break; - - case SVGA_REG_BYTES_PER_LINE: - if (s->new_width) { - ret = (s->new_depth * s->new_width) / 8; - } else { - ret = surface_stride(surface); - } - break; - - case SVGA_REG_FB_START: { - struct pci_vmsvga_state_s *pci_vmsvga - = container_of(s, struct pci_vmsvga_state_s, chip); - ret = pci_get_bar_addr(PCI_DEVICE(pci_vmsvga), 1); - break; - } - - case SVGA_REG_FB_OFFSET: - ret = 0x0; - break; - - case SVGA_REG_VRAM_SIZE: - ret = s->vga.vram_size; /* No physical VRAM besides the framebuffer */ - break; - - case SVGA_REG_FB_SIZE: - ret = s->vga.vram_size; - break; - - case SVGA_REG_CAPABILITIES: - caps = SVGA_CAP_NONE; -#ifdef HW_RECT_ACCEL - caps |= SVGA_CAP_RECT_COPY; -#endif -#ifdef HW_FILL_ACCEL - caps |= SVGA_CAP_RECT_FILL; -#endif -#ifdef HW_MOUSE_ACCEL - if (dpy_cursor_define_supported(s->vga.con)) { - caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 | - SVGA_CAP_CURSOR_BYPASS; - } -#endif - ret = caps; - break; - - case SVGA_REG_MEM_START: { - struct pci_vmsvga_state_s *pci_vmsvga - = container_of(s, struct pci_vmsvga_state_s, chip); - ret = pci_get_bar_addr(PCI_DEVICE(pci_vmsvga), 2); - break; - } - - case SVGA_REG_MEM_SIZE: - ret = s->fifo_size; - break; - - case SVGA_REG_CONFIG_DONE: - ret = s->config; - break; - - case SVGA_REG_SYNC: - case SVGA_REG_BUSY: - ret = s->syncing; - break; - - case SVGA_REG_GUEST_ID: - ret = s->guest; - break; - - case SVGA_REG_CURSOR_ID: - ret = s->cursor.id; - break; - - case SVGA_REG_CURSOR_X: - ret = s->cursor.x; - break; - - case SVGA_REG_CURSOR_Y: - ret = s->cursor.y; - break; - - case SVGA_REG_CURSOR_ON: - ret = s->cursor.on; - break; - - case SVGA_REG_SCRATCH_SIZE: - ret = s->scratch_size; - break; - - case SVGA_REG_MEM_REGS: - case SVGA_REG_NUM_DISPLAYS: - case SVGA_REG_PITCHLOCK: - case SVGA_PALETTE_BASE ... SVGA_PALETTE_END: - ret = 0; - break; - - default: - if (s->index >= SVGA_SCRATCH_BASE && - s->index < SVGA_SCRATCH_BASE + s->scratch_size) { - ret = s->scratch[s->index - SVGA_SCRATCH_BASE]; - break; - } - printf("%s: Bad register %02x\n", __func__, s->index); - ret = 0; - break; - } - - if (s->index >= SVGA_SCRATCH_BASE) { - trace_vmware_scratch_read(s->index, ret); - } else if (s->index >= SVGA_PALETTE_BASE) { - trace_vmware_palette_read(s->index, ret); - } else { - trace_vmware_value_read(s->index, ret); - } - return ret; -} - -static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) -{ - struct vmsvga_state_s *s = opaque; - - if (s->index >= SVGA_SCRATCH_BASE) { - trace_vmware_scratch_write(s->index, value); - } else if (s->index >= SVGA_PALETTE_BASE) { - trace_vmware_palette_write(s->index, value); - } else { - trace_vmware_value_write(s->index, value); - } - switch (s->index) { - case SVGA_REG_ID: - if (value == SVGA_ID_2 || value == SVGA_ID_1 || value == SVGA_ID_0) { - s->svgaid = value; - } - break; - - case SVGA_REG_ENABLE: - s->enable = !!value; - s->invalidated = 1; - s->vga.hw_ops->invalidate(&s->vga); - if (s->enable && s->config) { - vga_dirty_log_stop(&s->vga); - } else { - vga_dirty_log_start(&s->vga); - } - break; - - case SVGA_REG_WIDTH: - if (value <= SVGA_MAX_WIDTH) { - s->new_width = value; - s->invalidated = 1; - } else { - printf("%s: Bad width: %i\n", __func__, value); - } - break; - - case SVGA_REG_HEIGHT: - if (value <= SVGA_MAX_HEIGHT) { - s->new_height = value; - s->invalidated = 1; - } else { - printf("%s: Bad height: %i\n", __func__, value); - } - break; - - case SVGA_REG_BITS_PER_PIXEL: - if (value != 32) { - printf("%s: Bad bits per pixel: %i bits\n", __func__, value); - s->config = 0; - s->invalidated = 1; - } - break; - - case SVGA_REG_CONFIG_DONE: - if (value) { - s->fifo = (uint32_t *) s->fifo_ptr; - /* Check range and alignment. */ - if ((CMD(min) | CMD(max) | CMD(next_cmd) | CMD(stop)) & 3) { - break; - } - if (CMD(min) < (uint8_t *) s->cmd->fifo - (uint8_t *) s->fifo) { - break; - } - if (CMD(max) > SVGA_FIFO_SIZE) { - break; - } - if (CMD(max) < CMD(min) + 10 * 1024) { - break; - } - vga_dirty_log_stop(&s->vga); - } - s->config = !!value; - break; - - case SVGA_REG_SYNC: - s->syncing = 1; - vmsvga_fifo_run(s); /* Or should we just wait for update_display? */ - break; - - case SVGA_REG_GUEST_ID: - s->guest = value; -#ifdef VERBOSE - if (value >= GUEST_OS_BASE && value < GUEST_OS_BASE + - ARRAY_SIZE(vmsvga_guest_id)) { - printf("%s: guest runs %s.\n", __func__, - vmsvga_guest_id[value - GUEST_OS_BASE]); - } -#endif - break; - - case SVGA_REG_CURSOR_ID: - s->cursor.id = value; - break; - - case SVGA_REG_CURSOR_X: - s->cursor.x = value; - break; - - case SVGA_REG_CURSOR_Y: - s->cursor.y = value; - break; - - case SVGA_REG_CURSOR_ON: - s->cursor.on |= (value == SVGA_CURSOR_ON_SHOW); - s->cursor.on &= (value != SVGA_CURSOR_ON_HIDE); -#ifdef HW_MOUSE_ACCEL - if (value <= SVGA_CURSOR_ON_SHOW) { - dpy_mouse_set(s->vga.con, s->cursor.x, s->cursor.y, s->cursor.on); - } -#endif - break; - - case SVGA_REG_DEPTH: - case SVGA_REG_MEM_REGS: - case SVGA_REG_NUM_DISPLAYS: - case SVGA_REG_PITCHLOCK: - case SVGA_PALETTE_BASE ... SVGA_PALETTE_END: - break; - - default: - if (s->index >= SVGA_SCRATCH_BASE && - s->index < SVGA_SCRATCH_BASE + s->scratch_size) { - s->scratch[s->index - SVGA_SCRATCH_BASE] = value; - break; - } - printf("%s: Bad register %02x\n", __func__, s->index); - } -} - -static uint32_t vmsvga_bios_read(void *opaque, uint32_t address) -{ - printf("%s: what are we supposed to return?\n", __func__); - return 0xcafe; -} - -static void vmsvga_bios_write(void *opaque, uint32_t address, uint32_t data) -{ - printf("%s: what are we supposed to do with (%08x)?\n", __func__, data); -} - -static inline void vmsvga_check_size(struct vmsvga_state_s *s) -{ - DisplaySurface *surface = qemu_console_surface(s->vga.con); - - if (s->new_width != surface_width(surface) || - s->new_height != surface_height(surface) || - s->new_depth != surface_bits_per_pixel(surface)) { - int stride = (s->new_depth * s->new_width) / 8; - pixman_format_code_t format = - qemu_default_pixman_format(s->new_depth, true); - trace_vmware_setmode(s->new_width, s->new_height, s->new_depth); - surface = qemu_create_displaysurface_from(s->new_width, s->new_height, - format, stride, - s->vga.vram_ptr); - dpy_gfx_replace_surface(s->vga.con, surface); - s->invalidated = 1; - } -} - -static void vmsvga_update_display(void *opaque) -{ - struct vmsvga_state_s *s = opaque; - DisplaySurface *surface; - bool dirty = false; - - if (!s->enable) { - s->vga.hw_ops->gfx_update(&s->vga); - return; - } - - vmsvga_check_size(s); - surface = qemu_console_surface(s->vga.con); - - vmsvga_fifo_run(s); - vmsvga_update_rect_flush(s); - - /* - * Is it more efficient to look at vram VGA-dirty bits or wait - * for the driver to issue SVGA_CMD_UPDATE? - */ - if (memory_region_is_logging(&s->vga.vram, DIRTY_MEMORY_VGA)) { - vga_sync_dirty_bitmap(&s->vga); - dirty = memory_region_get_dirty(&s->vga.vram, 0, - surface_stride(surface) * surface_height(surface), - DIRTY_MEMORY_VGA); - } - if (s->invalidated || dirty) { - s->invalidated = 0; - dpy_gfx_update(s->vga.con, 0, 0, - surface_width(surface), surface_height(surface)); - } - if (dirty) { - memory_region_reset_dirty(&s->vga.vram, 0, - surface_stride(surface) * surface_height(surface), - DIRTY_MEMORY_VGA); - } -} - -static void vmsvga_reset(DeviceState *dev) -{ - struct pci_vmsvga_state_s *pci = VMWARE_SVGA(dev); - struct vmsvga_state_s *s = &pci->chip; - - s->index = 0; - s->enable = 0; - s->config = 0; - s->svgaid = SVGA_ID; - s->cursor.on = 0; - s->redraw_fifo_first = 0; - s->redraw_fifo_last = 0; - s->syncing = 0; - - vga_dirty_log_start(&s->vga); -} - -static void vmsvga_invalidate_display(void *opaque) -{ - struct vmsvga_state_s *s = opaque; - if (!s->enable) { - s->vga.hw_ops->invalidate(&s->vga); - return; - } - - s->invalidated = 1; -} - -static void vmsvga_text_update(void *opaque, console_ch_t *chardata) -{ - struct vmsvga_state_s *s = opaque; - - if (s->vga.hw_ops->text_update) { - s->vga.hw_ops->text_update(&s->vga, chardata); - } -} - -static int vmsvga_post_load(void *opaque, int version_id) -{ - struct vmsvga_state_s *s = opaque; - - s->invalidated = 1; - if (s->config) { - s->fifo = (uint32_t *) s->fifo_ptr; - } - return 0; -} - -static const VMStateDescription vmstate_vmware_vga_internal = { - .name = "vmware_vga_internal", - .version_id = 0, - .minimum_version_id = 0, - .post_load = vmsvga_post_load, - .fields = (VMStateField[]) { - VMSTATE_INT32_EQUAL(new_depth, struct vmsvga_state_s), - VMSTATE_INT32(enable, struct vmsvga_state_s), - VMSTATE_INT32(config, struct vmsvga_state_s), - VMSTATE_INT32(cursor.id, struct vmsvga_state_s), - VMSTATE_INT32(cursor.x, struct vmsvga_state_s), - VMSTATE_INT32(cursor.y, struct vmsvga_state_s), - VMSTATE_INT32(cursor.on, struct vmsvga_state_s), - VMSTATE_INT32(index, struct vmsvga_state_s), - VMSTATE_VARRAY_INT32(scratch, struct vmsvga_state_s, - scratch_size, 0, vmstate_info_uint32, uint32_t), - VMSTATE_INT32(new_width, struct vmsvga_state_s), - VMSTATE_INT32(new_height, struct vmsvga_state_s), - VMSTATE_UINT32(guest, struct vmsvga_state_s), - VMSTATE_UINT32(svgaid, struct vmsvga_state_s), - VMSTATE_INT32(syncing, struct vmsvga_state_s), - VMSTATE_UNUSED(4), /* was fb_size */ - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_vmware_vga = { - .name = "vmware_vga", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(parent_obj, struct pci_vmsvga_state_s), - VMSTATE_STRUCT(chip, struct pci_vmsvga_state_s, 0, - vmstate_vmware_vga_internal, struct vmsvga_state_s), - VMSTATE_END_OF_LIST() - } -}; - -static const GraphicHwOps vmsvga_ops = { - .invalidate = vmsvga_invalidate_display, - .gfx_update = vmsvga_update_display, - .text_update = vmsvga_text_update, -}; - -static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s, - MemoryRegion *address_space, MemoryRegion *io) -{ - s->scratch_size = SVGA_SCRATCH_SIZE; - s->scratch = g_malloc(s->scratch_size * 4); - - s->vga.con = graphic_console_init(dev, 0, &vmsvga_ops, s); - - s->fifo_size = SVGA_FIFO_SIZE; - memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size, - &error_fatal); - vmstate_register_ram_global(&s->fifo_ram); - s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram); - - vga_common_init(&s->vga, OBJECT(dev), true); - vga_init(&s->vga, OBJECT(dev), address_space, io, true); - vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga); - s->new_depth = 32; -} - -static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, unsigned size) -{ - struct vmsvga_state_s *s = opaque; - - switch (addr) { - 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); - default: return -1u; - } -} - -static void vmsvga_io_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - struct vmsvga_state_s *s = opaque; - - switch (addr) { - case SVGA_IO_MUL * SVGA_INDEX_PORT: - vmsvga_index_write(s, addr, data); - break; - case SVGA_IO_MUL * SVGA_VALUE_PORT: - vmsvga_value_write(s, addr, data); - break; - case SVGA_IO_MUL * SVGA_BIOS_PORT: - vmsvga_bios_write(s, addr, data); - break; - } -} - -static const MemoryRegionOps vmsvga_io_ops = { - .read = vmsvga_io_read, - .write = vmsvga_io_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - .unaligned = true, - }, - .impl = { - .unaligned = true, - }, -}; - -static void pci_vmsvga_realize(PCIDevice *dev, Error **errp) -{ - struct pci_vmsvga_state_s *s = VMWARE_SVGA(dev); - - dev->config[PCI_CACHE_LINE_SIZE] = 0x08; - dev->config[PCI_LATENCY_TIMER] = 0x40; - dev->config[PCI_INTERRUPT_LINE] = 0xff; /* End */ - - memory_region_init_io(&s->io_bar, NULL, &vmsvga_io_ops, &s->chip, - "vmsvga-io", 0x10); - memory_region_set_flush_coalesced(&s->io_bar); - pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar); - - vmsvga_init(DEVICE(dev), &s->chip, - pci_address_space(dev), pci_address_space_io(dev)); - - pci_register_bar(dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, - &s->chip.vga.vram); - pci_register_bar(dev, 2, PCI_BASE_ADDRESS_MEM_PREFETCH, - &s->chip.fifo_ram); - - if (!dev->rom_bar) { - /* compatibility with pc-0.13 and older */ - vga_init_vbe(&s->chip.vga, OBJECT(dev), pci_address_space(dev)); - } -} - -static Property vga_vmware_properties[] = { - DEFINE_PROP_UINT32("vgamem_mb", struct pci_vmsvga_state_s, - chip.vga.vram_size_mb, 16), - DEFINE_PROP_END_OF_LIST(), -}; - -static void vmsvga_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = pci_vmsvga_realize; - k->romfile = "vgabios-vmware.bin"; - k->vendor_id = PCI_VENDOR_ID_VMWARE; - k->device_id = SVGA_PCI_DEVICE_ID; - k->class_id = PCI_CLASS_DISPLAY_VGA; - k->subsystem_vendor_id = PCI_VENDOR_ID_VMWARE; - k->subsystem_id = SVGA_PCI_DEVICE_ID; - dc->reset = vmsvga_reset; - dc->vmsd = &vmstate_vmware_vga; - dc->props = vga_vmware_properties; - dc->hotpluggable = false; - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); -} - -static const TypeInfo vmsvga_info = { - .name = TYPE_VMWARE_SVGA, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(struct pci_vmsvga_state_s), - .class_init = vmsvga_class_init, -}; - -static void vmsvga_register_types(void) -{ - type_register_static(&vmsvga_info); -} - -type_init(vmsvga_register_types) diff --git a/qemu/hw/display/xenfb.c b/qemu/hw/display/xenfb.c deleted file mode 100644 index 9866dfda5..000000000 --- a/qemu/hw/display/xenfb.c +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * xen paravirt framebuffer backend - * - * Copyright IBM, Corp. 2005-2006 - * Copyright Red Hat, Inc. 2006-2008 - * - * Authors: - * Anthony Liguori , - * Markus Armbruster , - * Daniel P. Berrange , - * Pat Campbell , - * Gerd Hoffmann - * - * 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; under version 2 of the License. - * - * 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 . - */ - -#include "qemu/osdep.h" -#include - -#include "hw/hw.h" -#include "ui/console.h" -#include "sysemu/char.h" -#include "hw/xen/xen_backend.h" - -#include -#include -#include -#include - -#include "trace.h" - -#ifndef BTN_LEFT -#define BTN_LEFT 0x110 /* from */ -#endif - -/* -------------------------------------------------------------------- */ - -struct common { - struct XenDevice xendev; /* must be first */ - void *page; - QemuConsole *con; -}; - -struct XenInput { - struct common c; - int abs_pointer_wanted; /* Whether guest supports absolute pointer */ - int button_state; /* Last seen pointer button state */ - int extended; - QEMUPutMouseEntry *qmouse; -}; - -#define UP_QUEUE 8 - -struct XenFB { - struct common c; - size_t fb_len; - int row_stride; - int depth; - int width; - int height; - int offset; - void *pixels; - int fbpages; - int feature_update; - int bug_trigger; - int have_console; - int do_resize; - - struct { - int x,y,w,h; - } up_rects[UP_QUEUE]; - int up_count; - int up_fullscreen; -}; - -/* -------------------------------------------------------------------- */ - -static int common_bind(struct common *c) -{ - uint64_t val; - xen_pfn_t mfn; - - if (xenstore_read_fe_uint64(&c->xendev, "page-ref", &val) == -1) - return -1; - mfn = (xen_pfn_t)val; - assert(val == mfn); - - if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1) - return -1; - - c->page = xenforeignmemory_map(xen_fmem, c->xendev.dom, - PROT_READ | PROT_WRITE, 1, &mfn, NULL); - if (c->page == NULL) - return -1; - - xen_be_bind_evtchn(&c->xendev); - xen_be_printf(&c->xendev, 1, "ring mfn %"PRI_xen_pfn", remote-port %d, local-port %d\n", - mfn, c->xendev.remote_port, c->xendev.local_port); - - return 0; -} - -static void common_unbind(struct common *c) -{ - xen_be_unbind_evtchn(&c->xendev); - if (c->page) { - xenforeignmemory_unmap(xen_fmem, c->page, 1); - c->page = NULL; - } -} - -/* -------------------------------------------------------------------- */ - -#if 0 -/* - * These two tables are not needed any more, but left in here - * intentionally as documentation, to show how scancode2linux[] - * was generated. - * - * Tables to map from scancode to Linux input layer keycode. - * Scancodes are hardware-specific. These maps assumes a - * standard AT or PS/2 keyboard which is what QEMU feeds us. - */ -const unsigned char atkbd_set2_keycode[512] = { - - 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117, - 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0, - 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183, - 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185, - 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0, - 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85, - 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0, - 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125, - 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127, - 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142, - 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0, - 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112, - 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0, - -}; - -const unsigned char atkbd_unxlate_table[128] = { - - 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13, - 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27, - 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42, - 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3, - 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105, - 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63, - 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111, - 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110 - -}; -#endif - -/* - * for (i = 0; i < 128; i++) { - * scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]]; - * scancode2linux[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80]; - * } - */ -static const unsigned char scancode2linux[512] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 99, 0, 86, 87, 88,117, 0, 0, 95,183,184,185, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 93, 0, 0, 89, 0, 0, 85, 91, 90, 92, 0, 94, 0,124,121, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 165, 0, 0, 0, 0, 0, 0, 0, 0,163, 0, 0, 96, 97, 0, 0, - 113,140,164, 0,166, 0, 0, 0, 0, 0,255, 0, 0, 0,114, 0, - 115, 0,150, 0, 0, 98,255, 99,100, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,119,119,102,103,104, 0,105,112,106,118,107, - 108,109,110,111, 0, 0, 0, 0, 0, 0, 0,125,126,127,116,142, - 0, 0, 0,143, 0,217,156,173,128,159,158,157,155,226, 0,112, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -/* Send an event to the keyboard frontend driver */ -static int xenfb_kbd_event(struct XenInput *xenfb, - union xenkbd_in_event *event) -{ - struct xenkbd_page *page = xenfb->c.page; - uint32_t prod; - - if (xenfb->c.xendev.be_state != XenbusStateConnected) - return 0; - if (!page) - return 0; - - prod = page->in_prod; - if (prod - page->in_cons == XENKBD_IN_RING_LEN) { - errno = EAGAIN; - return -1; - } - - xen_mb(); /* ensure ring space available */ - XENKBD_IN_RING_REF(page, prod) = *event; - xen_wmb(); /* ensure ring contents visible */ - page->in_prod = prod + 1; - return xen_be_send_notify(&xenfb->c.xendev); -} - -/* Send a keyboard (or mouse button) event */ -static int xenfb_send_key(struct XenInput *xenfb, bool down, int keycode) -{ - union xenkbd_in_event event; - - memset(&event, 0, XENKBD_IN_EVENT_SIZE); - event.type = XENKBD_TYPE_KEY; - event.key.pressed = down ? 1 : 0; - event.key.keycode = keycode; - - return xenfb_kbd_event(xenfb, &event); -} - -/* Send a relative mouse movement event */ -static int xenfb_send_motion(struct XenInput *xenfb, - int rel_x, int rel_y, int rel_z) -{ - union xenkbd_in_event event; - - memset(&event, 0, XENKBD_IN_EVENT_SIZE); - event.type = XENKBD_TYPE_MOTION; - event.motion.rel_x = rel_x; - event.motion.rel_y = rel_y; - event.motion.rel_z = rel_z; - - return xenfb_kbd_event(xenfb, &event); -} - -/* Send an absolute mouse movement event */ -static int xenfb_send_position(struct XenInput *xenfb, - int abs_x, int abs_y, int z) -{ - union xenkbd_in_event event; - - memset(&event, 0, XENKBD_IN_EVENT_SIZE); - event.type = XENKBD_TYPE_POS; - event.pos.abs_x = abs_x; - event.pos.abs_y = abs_y; - event.pos.rel_z = z; - - return xenfb_kbd_event(xenfb, &event); -} - -/* - * Send a key event from the client to the guest OS - * QEMU gives us a raw scancode from an AT / PS/2 style keyboard. - * We have to turn this into a Linux Input layer keycode. - * - * Extra complexity from the fact that with extended scancodes - * (like those produced by arrow keys) this method gets called - * twice, but we only want to send a single event. So we have to - * track the '0xe0' scancode state & collapse the extended keys - * as needed. - * - * Wish we could just send scancodes straight to the guest which - * already has code for dealing with this... - */ -static void xenfb_key_event(void *opaque, int scancode) -{ - struct XenInput *xenfb = opaque; - int down = 1; - - if (scancode == 0xe0) { - xenfb->extended = 1; - return; - } else if (scancode & 0x80) { - scancode &= 0x7f; - down = 0; - } - if (xenfb->extended) { - scancode |= 0x80; - xenfb->extended = 0; - } - xenfb_send_key(xenfb, down, scancode2linux[scancode]); -} - -/* - * Send a mouse event from the client to the guest OS - * - * The QEMU mouse can be in either relative, or absolute mode. - * Movement is sent separately from button state, which has to - * be encoded as virtual key events. We also don't actually get - * given any button up/down events, so have to track changes in - * the button state. - */ -static void xenfb_mouse_event(void *opaque, - int dx, int dy, int dz, int button_state) -{ - struct XenInput *xenfb = opaque; - DisplaySurface *surface = qemu_console_surface(xenfb->c.con); - int dw = surface_width(surface); - int dh = surface_height(surface); - int i; - - trace_xenfb_mouse_event(opaque, dx, dy, dz, button_state, - xenfb->abs_pointer_wanted); - if (xenfb->abs_pointer_wanted) - xenfb_send_position(xenfb, - dx * (dw - 1) / 0x7fff, - dy * (dh - 1) / 0x7fff, - dz); - else - xenfb_send_motion(xenfb, dx, dy, dz); - - for (i = 0 ; i < 8 ; i++) { - int lastDown = xenfb->button_state & (1 << i); - int down = button_state & (1 << i); - if (down == lastDown) - continue; - - if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0) - return; - } - xenfb->button_state = button_state; -} - -static int input_init(struct XenDevice *xendev) -{ - xenstore_write_be_int(xendev, "feature-abs-pointer", 1); - return 0; -} - -static int input_initialise(struct XenDevice *xendev) -{ - struct XenInput *in = container_of(xendev, struct XenInput, c.xendev); - int rc; - - if (!in->c.con) { - xen_be_printf(xendev, 1, "ds not set (yet)\n"); - return -1; - } - - rc = common_bind(&in->c); - if (rc != 0) - return rc; - - qemu_add_kbd_event_handler(xenfb_key_event, in); - return 0; -} - -static void input_connected(struct XenDevice *xendev) -{ - struct XenInput *in = container_of(xendev, struct XenInput, c.xendev); - - if (xenstore_read_fe_int(xendev, "request-abs-pointer", - &in->abs_pointer_wanted) == -1) { - in->abs_pointer_wanted = 0; - } - - if (in->qmouse) { - qemu_remove_mouse_event_handler(in->qmouse); - } - trace_xenfb_input_connected(xendev, in->abs_pointer_wanted); - in->qmouse = qemu_add_mouse_event_handler(xenfb_mouse_event, in, - in->abs_pointer_wanted, - "Xen PVFB Mouse"); -} - -static void input_disconnect(struct XenDevice *xendev) -{ - struct XenInput *in = container_of(xendev, struct XenInput, c.xendev); - - if (in->qmouse) { - qemu_remove_mouse_event_handler(in->qmouse); - in->qmouse = NULL; - } - qemu_add_kbd_event_handler(NULL, NULL); - common_unbind(&in->c); -} - -static void input_event(struct XenDevice *xendev) -{ - struct XenInput *xenfb = container_of(xendev, struct XenInput, c.xendev); - struct xenkbd_page *page = xenfb->c.page; - - /* We don't understand any keyboard events, so just ignore them. */ - if (page->out_prod == page->out_cons) - return; - page->out_cons = page->out_prod; - xen_be_send_notify(&xenfb->c.xendev); -} - -/* -------------------------------------------------------------------- */ - -static void xenfb_copy_mfns(int mode, int count, xen_pfn_t *dst, void *src) -{ - uint32_t *src32 = src; - uint64_t *src64 = src; - int i; - - for (i = 0; i < count; i++) - dst[i] = (mode == 32) ? src32[i] : src64[i]; -} - -static int xenfb_map_fb(struct XenFB *xenfb) -{ - struct xenfb_page *page = xenfb->c.page; - char *protocol = xenfb->c.xendev.protocol; - int n_fbdirs; - xen_pfn_t *pgmfns = NULL; - xen_pfn_t *fbmfns = NULL; - void *map, *pd; - int mode, ret = -1; - - /* default to native */ - pd = page->pd; - mode = sizeof(unsigned long) * 8; - - if (!protocol) { - /* - * Undefined protocol, some guesswork needed. - * - * Old frontends which don't set the protocol use - * one page directory only, thus pd[1] must be zero. - * pd[1] of the 32bit struct layout and the lower - * 32 bits of pd[0] of the 64bit struct layout have - * the same location, so we can check that ... - */ - uint32_t *ptr32 = NULL; - uint32_t *ptr64 = NULL; -#if defined(__i386__) - ptr32 = (void*)page->pd; - ptr64 = ((void*)page->pd) + 4; -#elif defined(__x86_64__) - ptr32 = ((void*)page->pd) - 4; - ptr64 = (void*)page->pd; -#endif - if (ptr32) { - if (ptr32[1] == 0) { - mode = 32; - pd = ptr32; - } else { - mode = 64; - pd = ptr64; - } - } -#if defined(__x86_64__) - } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) { - /* 64bit dom0, 32bit domU */ - mode = 32; - pd = ((void*)page->pd) - 4; -#elif defined(__i386__) - } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_64) == 0) { - /* 32bit dom0, 64bit domU */ - mode = 64; - pd = ((void*)page->pd) + 4; -#endif - } - - if (xenfb->pixels) { - munmap(xenfb->pixels, xenfb->fbpages * XC_PAGE_SIZE); - xenfb->pixels = NULL; - } - - xenfb->fbpages = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE; - n_fbdirs = xenfb->fbpages * mode / 8; - n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE; - - pgmfns = g_malloc0(sizeof(xen_pfn_t) * n_fbdirs); - fbmfns = g_malloc0(sizeof(xen_pfn_t) * xenfb->fbpages); - - xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd); - map = xenforeignmemory_map(xen_fmem, xenfb->c.xendev.dom, - PROT_READ, n_fbdirs, pgmfns, NULL); - if (map == NULL) - goto out; - xenfb_copy_mfns(mode, xenfb->fbpages, fbmfns, map); - xenforeignmemory_unmap(xen_fmem, map, n_fbdirs); - - xenfb->pixels = xenforeignmemory_map(xen_fmem, xenfb->c.xendev.dom, - PROT_READ, xenfb->fbpages, fbmfns, NULL); - if (xenfb->pixels == NULL) - goto out; - - ret = 0; /* all is fine */ - -out: - g_free(pgmfns); - g_free(fbmfns); - return ret; -} - -static int xenfb_configure_fb(struct XenFB *xenfb, size_t fb_len_lim, - int width, int height, int depth, - size_t fb_len, int offset, int row_stride) -{ - size_t mfn_sz = sizeof(*((struct xenfb_page *)0)->pd); - size_t pd_len = sizeof(((struct xenfb_page *)0)->pd) / mfn_sz; - size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz; - size_t fb_len_max = fb_pages * XC_PAGE_SIZE; - int max_width, max_height; - - if (fb_len_lim > fb_len_max) { - xen_be_printf(&xenfb->c.xendev, 0, "fb size limit %zu exceeds %zu, corrected\n", - fb_len_lim, fb_len_max); - fb_len_lim = fb_len_max; - } - if (fb_len_lim && fb_len > fb_len_lim) { - xen_be_printf(&xenfb->c.xendev, 0, "frontend fb size %zu limited to %zu\n", - fb_len, fb_len_lim); - fb_len = fb_len_lim; - } - if (depth != 8 && depth != 16 && depth != 24 && depth != 32) { - xen_be_printf(&xenfb->c.xendev, 0, "can't handle frontend fb depth %d\n", - depth); - return -1; - } - if (row_stride <= 0 || row_stride > fb_len) { - xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend stride %d\n", row_stride); - return -1; - } - max_width = row_stride / (depth / 8); - if (width < 0 || width > max_width) { - xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend width %d limited to %d\n", - width, max_width); - width = max_width; - } - if (offset < 0 || offset >= fb_len) { - xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend offset %d (max %zu)\n", - offset, fb_len - 1); - return -1; - } - max_height = (fb_len - offset) / row_stride; - if (height < 0 || height > max_height) { - xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend height %d limited to %d\n", - height, max_height); - height = max_height; - } - xenfb->fb_len = fb_len; - xenfb->row_stride = row_stride; - xenfb->depth = depth; - xenfb->width = width; - xenfb->height = height; - xenfb->offset = offset; - xenfb->up_fullscreen = 1; - xenfb->do_resize = 1; - xen_be_printf(&xenfb->c.xendev, 1, "framebuffer %dx%dx%d offset %d stride %d\n", - width, height, depth, offset, row_stride); - return 0; -} - -/* A convenient function for munging pixels between different depths */ -#define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB) \ - for (line = y ; line < (y+h) ; line++) { \ - SRC_T *src = (SRC_T *)(xenfb->pixels \ - + xenfb->offset \ - + (line * xenfb->row_stride) \ - + (x * xenfb->depth / 8)); \ - DST_T *dst = (DST_T *)(data \ - + (line * linesize) \ - + (x * bpp / 8)); \ - int col; \ - const int RSS = 32 - (RSB + GSB + BSB); \ - const int GSS = 32 - (GSB + BSB); \ - const int BSS = 32 - (BSB); \ - const uint32_t RSM = (~0U) << (32 - RSB); \ - const uint32_t GSM = (~0U) << (32 - GSB); \ - const uint32_t BSM = (~0U) << (32 - BSB); \ - const int RDS = 32 - (RDB + GDB + BDB); \ - const int GDS = 32 - (GDB + BDB); \ - const int BDS = 32 - (BDB); \ - const uint32_t RDM = (~0U) << (32 - RDB); \ - const uint32_t GDM = (~0U) << (32 - GDB); \ - const uint32_t BDM = (~0U) << (32 - BDB); \ - for (col = x ; col < (x+w) ; col++) { \ - uint32_t spix = *src; \ - *dst = (((spix << RSS) & RSM & RDM) >> RDS) | \ - (((spix << GSS) & GSM & GDM) >> GDS) | \ - (((spix << BSS) & BSM & BDM) >> BDS); \ - src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8); \ - dst = (DST_T *) ((unsigned long) dst + bpp / 8); \ - } \ - } - - -/* - * This copies data from the guest framebuffer region, into QEMU's - * displaysurface. qemu uses 16 or 32 bpp. In case the pv framebuffer - * uses something else we must convert and copy, otherwise we can - * supply the buffer directly and no thing here. - */ -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 = surface_bits_per_pixel(surface); - int linesize = surface_stride(surface); - uint8_t *data = surface_data(surface); - - if (!is_buffer_shared(surface)) { - switch (xenfb->depth) { - case 8: - if (bpp == 16) { - BLT(uint8_t, uint16_t, 3, 3, 2, 5, 6, 5); - } else if (bpp == 32) { - BLT(uint8_t, uint32_t, 3, 3, 2, 8, 8, 8); - } else { - oops = 1; - } - break; - case 24: - if (bpp == 16) { - BLT(uint32_t, uint16_t, 8, 8, 8, 5, 6, 5); - } else if (bpp == 32) { - BLT(uint32_t, uint32_t, 8, 8, 8, 8, 8, 8); - } else { - oops = 1; - } - break; - default: - oops = 1; - } - } - if (oops) /* should not happen */ - xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n", - __FUNCTION__, xenfb->depth, bpp); - - dpy_gfx_update(xenfb->c.con, x, y, w, h); -} - -#ifdef XENFB_TYPE_REFRESH_PERIOD -static int xenfb_queue_full(struct XenFB *xenfb) -{ - struct xenfb_page *page = xenfb->c.page; - uint32_t cons, prod; - - if (!page) - return 1; - - prod = page->in_prod; - cons = page->in_cons; - return prod - cons == XENFB_IN_RING_LEN; -} - -static void xenfb_send_event(struct XenFB *xenfb, union xenfb_in_event *event) -{ - uint32_t prod; - struct xenfb_page *page = xenfb->c.page; - - prod = page->in_prod; - /* caller ensures !xenfb_queue_full() */ - xen_mb(); /* ensure ring space available */ - XENFB_IN_RING_REF(page, prod) = *event; - xen_wmb(); /* ensure ring contents visible */ - page->in_prod = prod + 1; - - xen_be_send_notify(&xenfb->c.xendev); -} - -static void xenfb_send_refresh_period(struct XenFB *xenfb, int period) -{ - union xenfb_in_event event; - - memset(&event, 0, sizeof(event)); - event.type = XENFB_TYPE_REFRESH_PERIOD; - event.refresh_period.period = period; - xenfb_send_event(xenfb, &event); -} -#endif - -/* - * Periodic update of display. - * Also transmit the refresh interval to the frontend. - * - * Never ever do any qemu display operations - * (resize, screen update) outside this function. - * Our screen might be inactive. When asked for - * an update we know it is active. - */ -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) { - /* we don't get update notifications, thus use the - * sledge hammer approach ... */ - xenfb->up_fullscreen = 1; - } - - /* resize if needed */ - if (xenfb->do_resize) { - pixman_format_code_t format; - - xenfb->do_resize = 0; - switch (xenfb->depth) { - case 16: - case 32: - /* console.c supported depth -> buffer can be used directly */ - format = qemu_default_pixman_format(xenfb->depth, true); - surface = qemu_create_displaysurface_from - (xenfb->width, xenfb->height, format, - xenfb->row_stride, xenfb->pixels + xenfb->offset); - break; - default: - /* we must convert stuff */ - 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(surface) ? " (shared)" : ""); - xenfb->up_fullscreen = 1; - } - - /* run queued updates */ - if (xenfb->up_fullscreen) { - xen_be_printf(&xenfb->c.xendev, 3, "update: fullscreen\n"); - xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height); - } else if (xenfb->up_count) { - xen_be_printf(&xenfb->c.xendev, 3, "update: %d rects\n", xenfb->up_count); - for (i = 0; i < xenfb->up_count; i++) - xenfb_guest_copy(xenfb, - xenfb->up_rects[i].x, - xenfb->up_rects[i].y, - xenfb->up_rects[i].w, - xenfb->up_rects[i].h); - } else { - xen_be_printf(&xenfb->c.xendev, 3, "update: nothing\n"); - } - xenfb->up_count = 0; - xenfb->up_fullscreen = 0; -} - -static void xenfb_update_interval(void *opaque, uint64_t interval) -{ - struct XenFB *xenfb = opaque; - - if (xenfb->feature_update) { -#ifdef XENFB_TYPE_REFRESH_PERIOD - if (xenfb_queue_full(xenfb)) { - return; - } - xenfb_send_refresh_period(xenfb, interval); -#endif - } -} - -/* QEMU display state changed, so refresh the framebuffer copy */ -static void xenfb_invalidate(void *opaque) -{ - struct XenFB *xenfb = opaque; - xenfb->up_fullscreen = 1; -} - -static void xenfb_handle_events(struct XenFB *xenfb) -{ - uint32_t prod, cons, out_cons; - struct xenfb_page *page = xenfb->c.page; - - prod = page->out_prod; - out_cons = page->out_cons; - if (prod - out_cons > XENFB_OUT_RING_LEN) { - return; - } - xen_rmb(); /* ensure we see ring contents up to prod */ - for (cons = out_cons; cons != prod; cons++) { - union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons); - uint8_t type = event->type; - int x, y, w, h; - - switch (type) { - case XENFB_TYPE_UPDATE: - if (xenfb->up_count == UP_QUEUE) - xenfb->up_fullscreen = 1; - if (xenfb->up_fullscreen) - break; - x = MAX(event->update.x, 0); - y = MAX(event->update.y, 0); - w = MIN(event->update.width, xenfb->width - x); - h = MIN(event->update.height, xenfb->height - y); - if (w < 0 || h < 0) { - xen_be_printf(&xenfb->c.xendev, 1, "bogus update ignored\n"); - break; - } - if (x != event->update.x || - y != event->update.y || - w != event->update.width || - h != event->update.height) { - xen_be_printf(&xenfb->c.xendev, 1, "bogus update clipped\n"); - } - if (w == xenfb->width && h > xenfb->height / 2) { - /* scroll detector: updated more than 50% of the lines, - * don't bother keeping track of the rectangles then */ - xenfb->up_fullscreen = 1; - } else { - xenfb->up_rects[xenfb->up_count].x = x; - xenfb->up_rects[xenfb->up_count].y = y; - xenfb->up_rects[xenfb->up_count].w = w; - xenfb->up_rects[xenfb->up_count].h = h; - xenfb->up_count++; - } - break; -#ifdef XENFB_TYPE_RESIZE - case XENFB_TYPE_RESIZE: - if (xenfb_configure_fb(xenfb, xenfb->fb_len, - event->resize.width, - event->resize.height, - event->resize.depth, - xenfb->fb_len, - event->resize.offset, - event->resize.stride) < 0) - break; - xenfb_invalidate(xenfb); - break; -#endif - } - } - xen_mb(); /* ensure we're done with ring contents */ - page->out_cons = cons; -} - -static int fb_init(struct XenDevice *xendev) -{ -#ifdef XENFB_TYPE_RESIZE - xenstore_write_be_int(xendev, "feature-resize", 1); -#endif - return 0; -} - -static int fb_initialise(struct XenDevice *xendev) -{ - struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev); - struct xenfb_page *fb_page; - int videoram; - int rc; - - if (xenstore_read_fe_int(xendev, "videoram", &videoram) == -1) - videoram = 0; - - rc = common_bind(&fb->c); - if (rc != 0) - return rc; - - fb_page = fb->c.page; - rc = xenfb_configure_fb(fb, videoram * 1024 * 1024U, - fb_page->width, fb_page->height, fb_page->depth, - fb_page->mem_length, 0, fb_page->line_length); - if (rc != 0) - return rc; - - rc = xenfb_map_fb(fb); - if (rc != 0) - return rc; - -#if 0 /* handled in xen_init_display() for now */ - if (!fb->have_console) { - fb->c.ds = graphic_console_init(xenfb_update, - xenfb_invalidate, - NULL, - NULL, - fb); - fb->have_console = 1; - } -#endif - - if (xenstore_read_fe_int(xendev, "feature-update", &fb->feature_update) == -1) - fb->feature_update = 0; - if (fb->feature_update) - xenstore_write_be_int(xendev, "request-update", 1); - - xen_be_printf(xendev, 1, "feature-update=%d, videoram=%d\n", - fb->feature_update, videoram); - return 0; -} - -static void fb_disconnect(struct XenDevice *xendev) -{ - struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev); - - /* - * FIXME: qemu can't un-init gfx display (yet?). - * Replacing the framebuffer with anonymous shared memory - * instead. This releases the guest pages and keeps qemu happy. - */ - xenforeignmemory_unmap(xen_fmem, fb->pixels, fb->fbpages); - fb->pixels = mmap(fb->pixels, fb->fbpages * XC_PAGE_SIZE, - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, - -1, 0); - if (fb->pixels == MAP_FAILED) { - xen_be_printf(xendev, 0, - "Couldn't replace the framebuffer with anonymous memory errno=%d\n", - errno); - } - common_unbind(&fb->c); - fb->feature_update = 0; - fb->bug_trigger = 0; -} - -static void fb_frontend_changed(struct XenDevice *xendev, const char *node) -{ - struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev); - - /* - * Set state to Connected *again* once the frontend switched - * to connected. We must trigger the watch a second time to - * workaround a frontend bug. - */ - if (fb->bug_trigger == 0 && strcmp(node, "state") == 0 && - xendev->fe_state == XenbusStateConnected && - xendev->be_state == XenbusStateConnected) { - xen_be_printf(xendev, 2, "re-trigger connected (frontend bug)\n"); - xen_be_set_state(xendev, XenbusStateConnected); - fb->bug_trigger = 1; /* only once */ - } -} - -static void fb_event(struct XenDevice *xendev) -{ - struct XenFB *xenfb = container_of(xendev, struct XenFB, c.xendev); - - xenfb_handle_events(xenfb); - xen_be_send_notify(&xenfb->c.xendev); -} - -/* -------------------------------------------------------------------- */ - -struct XenDevOps xen_kbdmouse_ops = { - .size = sizeof(struct XenInput), - .init = input_init, - .initialise = input_initialise, - .connected = input_connected, - .disconnect = input_disconnect, - .event = input_event, -}; - -struct XenDevOps xen_framebuffer_ops = { - .size = sizeof(struct XenFB), - .init = fb_init, - .initialise = fb_initialise, - .disconnect = fb_disconnect, - .event = fb_event, - .frontend_changed = fb_frontend_changed, -}; - -static const GraphicHwOps xenfb_ops = { - .invalidate = xenfb_invalidate, - .gfx_update = xenfb_update, - .update_interval = xenfb_update_interval, -}; - -/* - * FIXME/TODO: Kill this. - * Temporary needed while DisplayState reorganization is in flight. - */ -void xen_init_display(int domid) -{ - struct XenDevice *xfb, *xin; - struct XenFB *fb; - struct XenInput *in; - int i = 0; - -wait_more: - i++; - main_loop_wait(true); - xfb = xen_be_find_xendev("vfb", domid, 0); - xin = xen_be_find_xendev("vkbd", domid, 0); - if (!xfb || !xin) { - if (i < 256) { - usleep(10000); - goto wait_more; - } - xen_be_printf(NULL, 1, "displaystate setup failed\n"); - return; - } - - /* vfb */ - fb = container_of(xfb, struct XenFB, c.xendev); - fb->c.con = graphic_console_init(NULL, 0, &xenfb_ops, fb); - fb->have_console = 1; - - /* vkbd */ - in = container_of(xin, struct XenInput, c.xendev); - in->c.con = fb->c.con; - - /* retry ->init() */ - xen_be_check_state(xin); - xen_be_check_state(xfb); -} -- cgit 1.2.3-korg