Commit d34cab9f49bc3ad83a2a968fc2d2719179db2c15

Authored by ths
1 parent a4080ece

VMware SVGA II emulation, by Andrzej Zaborowski.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2579 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -403,7 +403,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
403 403 VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
404 404 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
405 405 VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o acpi.o piix_pci.o
406   -VL_OBJS+= usb-uhci.o smbus_eeprom.o vmmouse.o
  406 +VL_OBJS+= usb-uhci.o smbus_eeprom.o vmmouse.o vmware_vga.o
407 407 CPPFLAGS += -DHAS_AUDIO
408 408 endif
409 409 ifeq ($(TARGET_BASE_ARCH), ppc)
... ...
hw/cirrus_vga.c
... ... @@ -3193,6 +3193,9 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
3193 3193 vga_common_init((VGAState *)s,
3194 3194 ds, vga_ram_base, vga_ram_offset, vga_ram_size);
3195 3195 cirrus_init_common(s, device_id, 1);
  3196 +
  3197 + graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
  3198 +
3196 3199 s->pci_dev = (PCIDevice *)d;
3197 3200  
3198 3201 /* setup memory space */
... ...
... ... @@ -664,6 +664,12 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
664 664 isa_cirrus_vga_init(ds, phys_ram_base + vga_ram_addr,
665 665 vga_ram_addr, vga_ram_size);
666 666 }
  667 + } else if (vmsvga_enabled) {
  668 + if (pci_enabled)
  669 + pci_vmsvga_init(pci_bus, ds, phys_ram_base + ram_size,
  670 + ram_size, vga_ram_size);
  671 + else
  672 + fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
667 673 } else {
668 674 if (pci_enabled) {
669 675 pci_vga_init(pci_bus, ds, phys_ram_base + vga_ram_addr,
... ...
hw/vga.c
... ... @@ -1788,12 +1788,13 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
1788 1788 s->get_bpp = vga_get_bpp;
1789 1789 s->get_offsets = vga_get_offsets;
1790 1790 s->get_resolution = vga_get_resolution;
1791   - graphic_console_init(s->ds, vga_update_display, vga_invalidate_display,
1792   - vga_screen_dump, s);
  1791 + s->update = vga_update_display;
  1792 + s->invalidate = vga_invalidate_display;
  1793 + s->screen_dump = vga_screen_dump;
1793 1794 }
1794 1795  
1795 1796 /* used by both ISA and PCI */
1796   -static void vga_init(VGAState *s)
  1797 +void vga_init(VGAState *s)
1797 1798 {
1798 1799 int vga_io_memory;
1799 1800  
... ... @@ -1856,6 +1857,8 @@ int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
1856 1857 vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1857 1858 vga_init(s);
1858 1859  
  1860 + graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
  1861 +
1859 1862 #ifdef CONFIG_BOCHS_VBE
1860 1863 /* XXX: use optimized standard vga accesses */
1861 1864 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
... ... @@ -1881,6 +1884,9 @@ int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
1881 1884  
1882 1885 vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1883 1886 vga_init(s);
  1887 +
  1888 + graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
  1889 +
1884 1890 s->pci_dev = &d->dev;
1885 1891  
1886 1892 pci_conf = d->dev.config;
... ...
hw/vga_int.h
... ... @@ -134,6 +134,9 @@
134 134 uint32_t cursor_offset; \
135 135 unsigned int (*rgb_to_pixel)(unsigned int r, \
136 136 unsigned int g, unsigned b); \
  137 + vga_hw_update_ptr update; \
  138 + vga_hw_invalidate_ptr invalidate; \
  139 + vga_hw_screen_dump_ptr screen_dump; \
137 140 /* hardware mouse cursor support */ \
138 141 uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; \
139 142 void (*cursor_invalidate)(struct VGAState *s); \
... ... @@ -157,6 +160,7 @@ static inline int c6_to_8(int v)
157 160  
158 161 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
159 162 unsigned long vga_ram_offset, int vga_ram_size);
  163 +void vga_init(VGAState *s);
160 164 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr);
161 165 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val);
162 166 void vga_invalidate_scanlines(VGAState *s, int y1, int y2);
... ...
hw/vmware_vga.c 0 โ†’ 100644
  1 +/*
  2 + * QEMU VMware-SVGA "chipset".
  3 + *
  4 + * Copyright (c) 2007 Andrzej Zaborowski <balrog@zabor.org>
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +
  26 +#define VERBOSE
  27 +#define EMBED_STDVGA
  28 +#undef DIRECT_VRAM
  29 +#define HW_RECT_ACCEL
  30 +#define HW_FILL_ACCEL
  31 +#define HW_MOUSE_ACCEL
  32 +
  33 +#ifdef EMBED_STDVGA
  34 +# include "vga_int.h"
  35 +#endif
  36 +
  37 +struct vmsvga_state_s {
  38 +#ifdef EMBED_STDVGA
  39 + VGA_STATE_COMMON
  40 +#endif
  41 +
  42 + int width;
  43 + int height;
  44 + int invalidated;
  45 + int depth;
  46 + int bypp;
  47 + int enable;
  48 + int config;
  49 + struct {
  50 + int id;
  51 + int x;
  52 + int y;
  53 + int on;
  54 + } cursor;
  55 +
  56 +#ifndef EMBED_STDVGA
  57 + DisplayState *ds;
  58 + int vram_size;
  59 +#endif
  60 + uint8_t *vram;
  61 +
  62 + int index;
  63 + int scratch_size;
  64 + uint32_t *scratch;
  65 + int new_width;
  66 + int new_height;
  67 + uint32_t guest;
  68 + uint32_t svgaid;
  69 + uint32_t wred;
  70 + uint32_t wgreen;
  71 + uint32_t wblue;
  72 + int syncing;
  73 + int fb_size;
  74 +
  75 + union {
  76 + uint32_t *fifo;
  77 + struct __attribute__((__packed__)) {
  78 + uint32_t min;
  79 + uint32_t max;
  80 + uint32_t next_cmd;
  81 + uint32_t stop;
  82 + /* Add registers here when adding capabilities. */
  83 + uint32_t fifo[0];
  84 + } *cmd;
  85 + };
  86 +
  87 +#define REDRAW_FIFO_LEN 512
  88 + struct vmsvga_rect_s {
  89 + int x, y, w, h;
  90 + } redraw_fifo[REDRAW_FIFO_LEN];
  91 + int redraw_fifo_first, redraw_fifo_last;
  92 +};
  93 +
  94 +struct pci_vmsvga_state_s {
  95 + PCIDevice card;
  96 + struct vmsvga_state_s chip;
  97 +};
  98 +
  99 +#define SVGA_MAGIC 0x900000UL
  100 +#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver))
  101 +#define SVGA_ID_0 SVGA_MAKE_ID(0)
  102 +#define SVGA_ID_1 SVGA_MAKE_ID(1)
  103 +#define SVGA_ID_2 SVGA_MAKE_ID(2)
  104 +
  105 +#define SVGA_LEGACY_BASE_PORT 0x4560
  106 +#define SVGA_INDEX_PORT 0x0
  107 +#define SVGA_VALUE_PORT 0x1
  108 +#define SVGA_BIOS_PORT 0x2
  109 +
  110 +#define SVGA_VERSION_2
  111 +
  112 +#ifdef SVGA_VERSION_2
  113 +# define SVGA_ID SVGA_ID_2
  114 +# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
  115 +# define SVGA_IO_MUL 1
  116 +# define SVGA_FIFO_SIZE 0x10000
  117 +# define SVGA_MEM_BASE 0xec000000
  118 +# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA2
  119 +#else
  120 +# define SVGA_ID SVGA_ID_1
  121 +# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
  122 +# define SVGA_IO_MUL 4
  123 +# define SVGA_FIFO_SIZE 0x10000
  124 +# define SVGA_MEM_BASE 0xec000000
  125 +# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA
  126 +#endif
  127 +
  128 +enum {
  129 + /* ID 0, 1 and 2 registers */
  130 + SVGA_REG_ID = 0,
  131 + SVGA_REG_ENABLE = 1,
  132 + SVGA_REG_WIDTH = 2,
  133 + SVGA_REG_HEIGHT = 3,
  134 + SVGA_REG_MAX_WIDTH = 4,
  135 + SVGA_REG_MAX_HEIGHT = 5,
  136 + SVGA_REG_DEPTH = 6,
  137 + SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */
  138 + SVGA_REG_PSEUDOCOLOR = 8,
  139 + SVGA_REG_RED_MASK = 9,
  140 + SVGA_REG_GREEN_MASK = 10,
  141 + SVGA_REG_BLUE_MASK = 11,
  142 + SVGA_REG_BYTES_PER_LINE = 12,
  143 + SVGA_REG_FB_START = 13,
  144 + SVGA_REG_FB_OFFSET = 14,
  145 + SVGA_REG_VRAM_SIZE = 15,
  146 + SVGA_REG_FB_SIZE = 16,
  147 +
  148 + /* ID 1 and 2 registers */
  149 + SVGA_REG_CAPABILITIES = 17,
  150 + SVGA_REG_MEM_START = 18, /* Memory for command FIFO */
  151 + SVGA_REG_MEM_SIZE = 19,
  152 + SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */
  153 + SVGA_REG_SYNC = 21, /* Write to force synchronization */
  154 + SVGA_REG_BUSY = 22, /* Read to check if sync is done */
  155 + SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */
  156 + SVGA_REG_CURSOR_ID = 24, /* ID of cursor */
  157 + SVGA_REG_CURSOR_X = 25, /* Set cursor X position */
  158 + SVGA_REG_CURSOR_Y = 26, /* Set cursor Y position */
  159 + SVGA_REG_CURSOR_ON = 27, /* Turn cursor on/off */
  160 + SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* Current bpp in the host */
  161 + SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */
  162 + SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */
  163 + SVGA_REG_NUM_DISPLAYS = 31, /* Number of guest displays */
  164 + SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */
  165 +
  166 + SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */
  167 + SVGA_PALETTE_END = SVGA_PALETTE_BASE + 767,
  168 + SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + 768,
  169 +};
  170 +
  171 +#define SVGA_CAP_NONE 0
  172 +#define SVGA_CAP_RECT_FILL (1 << 0)
  173 +#define SVGA_CAP_RECT_COPY (1 << 1)
  174 +#define SVGA_CAP_RECT_PAT_FILL (1 << 2)
  175 +#define SVGA_CAP_LEGACY_OFFSCREEN (1 << 3)
  176 +#define SVGA_CAP_RASTER_OP (1 << 4)
  177 +#define SVGA_CAP_CURSOR (1 << 5)
  178 +#define SVGA_CAP_CURSOR_BYPASS (1 << 6)
  179 +#define SVGA_CAP_CURSOR_BYPASS_2 (1 << 7)
  180 +#define SVGA_CAP_8BIT_EMULATION (1 << 8)
  181 +#define SVGA_CAP_ALPHA_CURSOR (1 << 9)
  182 +#define SVGA_CAP_GLYPH (1 << 10)
  183 +#define SVGA_CAP_GLYPH_CLIPPING (1 << 11)
  184 +#define SVGA_CAP_OFFSCREEN_1 (1 << 12)
  185 +#define SVGA_CAP_ALPHA_BLEND (1 << 13)
  186 +#define SVGA_CAP_3D (1 << 14)
  187 +#define SVGA_CAP_EXTENDED_FIFO (1 << 15)
  188 +#define SVGA_CAP_MULTIMON (1 << 16)
  189 +#define SVGA_CAP_PITCHLOCK (1 << 17)
  190 +
  191 +/*
  192 + * FIFO offsets (seen as an array of 32-bit words)
  193 + */
  194 +enum {
  195 + /*
  196 + * The original defined FIFO offsets
  197 + */
  198 + SVGA_FIFO_MIN = 0,
  199 + SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */
  200 + SVGA_FIFO_NEXT_CMD,
  201 + SVGA_FIFO_STOP,
  202 +
  203 + /*
  204 + * Additional offsets added as of SVGA_CAP_EXTENDED_FIFO
  205 + */
  206 + SVGA_FIFO_CAPABILITIES = 4,
  207 + SVGA_FIFO_FLAGS,
  208 + SVGA_FIFO_FENCE,
  209 + SVGA_FIFO_3D_HWVERSION,
  210 + SVGA_FIFO_PITCHLOCK,
  211 +};
  212 +
  213 +#define SVGA_FIFO_CAP_NONE 0
  214 +#define SVGA_FIFO_CAP_FENCE (1 << 0)
  215 +#define SVGA_FIFO_CAP_ACCELFRONT (1 << 1)
  216 +#define SVGA_FIFO_CAP_PITCHLOCK (1 << 2)
  217 +
  218 +#define SVGA_FIFO_FLAG_NONE 0
  219 +#define SVGA_FIFO_FLAG_ACCELFRONT (1 << 0)
  220 +
  221 +/* These values can probably be changed arbitrarily. */
  222 +#define SVGA_SCRATCH_SIZE 0x8000
  223 +#define SVGA_MAX_WIDTH 2360
  224 +#define SVGA_MAX_HEIGHT 1770
  225 +
  226 +#ifdef VERBOSE
  227 +# define GUEST_OS_BASE 0x5001
  228 +static const char *vmsvga_guest_id[] = {
  229 + [0x0] = "Dos",
  230 + [0x1] = "Windows 3.1",
  231 + [0x2] = "Windows 95",
  232 + [0x3] = "Windows 98",
  233 + [0x4] = "Windows ME",
  234 + [0x5] = "Windows NT",
  235 + [0x6] = "Windows 2000",
  236 + [0x7] = "Linux",
  237 + [0x8] = "OS/2",
  238 + [0x9] = "Unknown",
  239 + [0xa] = "BSD",
  240 + [0xb] = "Whistler",
  241 +};
  242 +#endif
  243 +
  244 +enum {
  245 + SVGA_CMD_INVALID_CMD = 0,
  246 + SVGA_CMD_UPDATE = 1,
  247 + SVGA_CMD_RECT_FILL = 2,
  248 + SVGA_CMD_RECT_COPY = 3,
  249 + SVGA_CMD_DEFINE_BITMAP = 4,
  250 + SVGA_CMD_DEFINE_BITMAP_SCANLINE = 5,
  251 + SVGA_CMD_DEFINE_PIXMAP = 6,
  252 + SVGA_CMD_DEFINE_PIXMAP_SCANLINE = 7,
  253 + SVGA_CMD_RECT_BITMAP_FILL = 8,
  254 + SVGA_CMD_RECT_PIXMAP_FILL = 9,
  255 + SVGA_CMD_RECT_BITMAP_COPY = 10,
  256 + SVGA_CMD_RECT_PIXMAP_COPY = 11,
  257 + SVGA_CMD_FREE_OBJECT = 12,
  258 + SVGA_CMD_RECT_ROP_FILL = 13,
  259 + SVGA_CMD_RECT_ROP_COPY = 14,
  260 + SVGA_CMD_RECT_ROP_BITMAP_FILL = 15,
  261 + SVGA_CMD_RECT_ROP_PIXMAP_FILL = 16,
  262 + SVGA_CMD_RECT_ROP_BITMAP_COPY = 17,
  263 + SVGA_CMD_RECT_ROP_PIXMAP_COPY = 18,
  264 + SVGA_CMD_DEFINE_CURSOR = 19,
  265 + SVGA_CMD_DISPLAY_CURSOR = 20,
  266 + SVGA_CMD_MOVE_CURSOR = 21,
  267 + SVGA_CMD_DEFINE_ALPHA_CURSOR = 22,
  268 + SVGA_CMD_DRAW_GLYPH = 23,
  269 + SVGA_CMD_DRAW_GLYPH_CLIPPED = 24,
  270 + SVGA_CMD_UPDATE_VERBOSE = 25,
  271 + SVGA_CMD_SURFACE_FILL = 26,
  272 + SVGA_CMD_SURFACE_COPY = 27,
  273 + SVGA_CMD_SURFACE_ALPHA_BLEND = 28,
  274 + SVGA_CMD_FRONT_ROP_FILL = 29,
  275 + SVGA_CMD_FENCE = 30,
  276 +};
  277 +
  278 +/* Legal values for the SVGA_REG_CURSOR_ON register in cursor bypass mode */
  279 +enum {
  280 + SVGA_CURSOR_ON_HIDE = 0,
  281 + SVGA_CURSOR_ON_SHOW = 1,
  282 + SVGA_CURSOR_ON_REMOVE_FROM_FB = 2,
  283 + SVGA_CURSOR_ON_RESTORE_TO_FB = 3,
  284 +};
  285 +
  286 +static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
  287 + int x, int y, int w, int h)
  288 +{
  289 +#ifndef DIRECT_VRAM
  290 + int line = h;
  291 + int bypl = s->bypp * s->width;
  292 + int width = s->bypp * w;
  293 + int start = s->bypp * x + bypl * y;
  294 + uint8_t *src = s->vram + start;
  295 + uint8_t *dst = s->ds->data + start;
  296 +
  297 + for (; line > 0; line --, src += bypl, dst += bypl)
  298 + memcpy(dst, src, width);
  299 +#endif
  300 +
  301 + dpy_update(s->ds, x, y, w, h);
  302 +}
  303 +
  304 +static inline void vmsvga_update_screen(struct vmsvga_state_s *s)
  305 +{
  306 +#ifndef DIRECT_VRAM
  307 + memcpy(s->ds->data, s->vram, s->bypp * s->width * s->height);
  308 +#endif
  309 +
  310 + dpy_update(s->ds, 0, 0, s->width, s->height);
  311 +}
  312 +
  313 +#ifdef DIRECT_VRAM
  314 +# define vmsvga_update_rect_delayed vmsvga_update_rect
  315 +#else
  316 +static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
  317 + int x, int y, int w, int h)
  318 +{
  319 + struct vmsvga_rect_s *rect = &s->redraw_fifo[s->redraw_fifo_last ++];
  320 + s->redraw_fifo_last &= REDRAW_FIFO_LEN - 1;
  321 + rect->x = x;
  322 + rect->y = y;
  323 + rect->w = w;
  324 + rect->h = h;
  325 +}
  326 +#endif
  327 +
  328 +static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s)
  329 +{
  330 + struct vmsvga_rect_s *rect;
  331 + if (s->invalidated) {
  332 + s->redraw_fifo_first = s->redraw_fifo_last;
  333 + return;
  334 + }
  335 + /* Overlapping region updates can be optimised out here - if someone
  336 + * knows a smart algorithm to do that, please share. */
  337 + while (s->redraw_fifo_first != s->redraw_fifo_last) {
  338 + rect = &s->redraw_fifo[s->redraw_fifo_first ++];
  339 + s->redraw_fifo_first &= REDRAW_FIFO_LEN - 1;
  340 + vmsvga_update_rect(s, rect->x, rect->y, rect->w, rect->h);
  341 + }
  342 +}
  343 +
  344 +#ifdef HW_RECT_ACCEL
  345 +static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
  346 + int x0, int y0, int x1, int y1, int w, int h)
  347 +{
  348 +# ifdef DIRECT_VRAM
  349 + uint8_t *vram = s->ds->data;
  350 +# else
  351 + uint8_t *vram = s->vram;
  352 +# endif
  353 + int bypl = s->bypp * s->width;
  354 + int width = s->bypp * w;
  355 + int line = h;
  356 + uint8_t *ptr[2];
  357 +
  358 +# ifdef DIRECT_VRAM
  359 + if (s->ds->dpy_copy)
  360 + s->ds->dpy_copy(s->ds, x0, y0, x1, y1, w, h);
  361 + else
  362 +# endif
  363 + {
  364 + if (y1 > y0) {
  365 + ptr[0] = vram + s->bypp * x0 + bypl * (y0 + h - 1);
  366 + ptr[1] = vram + s->bypp * x1 + bypl * (y1 + h - 1);
  367 + for (; line > 0; line --, ptr[0] -= bypl, ptr[1] -= bypl)
  368 + memmove(ptr[1], ptr[0], width);
  369 + } else {
  370 + ptr[0] = vram + s->bypp * x0 + bypl * y0;
  371 + ptr[1] = vram + s->bypp * x1 + bypl * y1;
  372 + for (; line > 0; line --, ptr[0] += bypl, ptr[1] += bypl)
  373 + memmove(ptr[1], ptr[0], width);
  374 + }
  375 + }
  376 +
  377 + vmsvga_update_rect_delayed(s, x1, y1, w, h);
  378 +}
  379 +#endif
  380 +
  381 +#ifdef HW_FILL_ACCEL
  382 +static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
  383 + uint32_t c, int x, int y, int w, int h)
  384 +{
  385 +# ifdef DIRECT_VRAM
  386 + uint8_t *vram = s->ds->data;
  387 +# else
  388 + uint8_t *vram = s->vram;
  389 +# endif
  390 + int bypp = s->bypp;
  391 + int bypl = bypp * s->width;
  392 + int width = bypp * w;
  393 + int line = h;
  394 + int column;
  395 + uint8_t *fst = vram + bypp * x + bypl * y;
  396 + uint8_t *dst;
  397 + uint8_t *src;
  398 + uint8_t col[4];
  399 +
  400 +# ifdef DIRECT_VRAM
  401 + if (s->ds->dpy_fill)
  402 + s->ds->dpy_fill(s->ds, x, y, w, h, c);
  403 + else
  404 +# endif
  405 + {
  406 + col[0] = c;
  407 + col[1] = c >> 8;
  408 + col[2] = c >> 16;
  409 + col[3] = c >> 24;
  410 +
  411 + if (line --) {
  412 + dst = fst;
  413 + src = col;
  414 + for (column = width; column > 0; column --) {
  415 + *(dst ++) = *(src ++);
  416 + if (src - col == bypp)
  417 + src = col;
  418 + }
  419 + dst = fst;
  420 + for (; line > 0; line --) {
  421 + dst += bypl;
  422 + memcpy(dst, fst, width);
  423 + }
  424 + }
  425 + }
  426 +
  427 + vmsvga_update_rect_delayed(s, x, y, w, h);
  428 +}
  429 +#endif
  430 +
  431 +struct vmsvga_cursor_definition_s {
  432 + int width;
  433 + int height;
  434 + int id;
  435 + int bpp;
  436 + int hot_x;
  437 + int hot_y;
  438 + uint32_t mask[1024];
  439 + uint32_t image[1024];
  440 +};
  441 +
  442 +#define SVGA_BITMAP_SIZE(w, h) ((((w) + 31) >> 5) * (h))
  443 +#define SVGA_PIXMAP_SIZE(w, h, bpp) (((((w) * (bpp)) + 31) >> 5) * (h))
  444 +
  445 +#ifdef HW_MOUSE_ACCEL
  446 +static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
  447 + struct vmsvga_cursor_definition_s *c)
  448 +{
  449 + int i;
  450 + for (i = SVGA_BITMAP_SIZE(c->width, c->height) - 1; i >= 0; i --)
  451 + c->mask[i] = ~c->mask[i];
  452 +
  453 + if (s->ds->cursor_define)
  454 + s->ds->cursor_define(c->width, c->height, c->bpp, c->hot_x, c->hot_y,
  455 + (uint8_t *) c->image, (uint8_t *) c->mask);
  456 +}
  457 +#endif
  458 +
  459 +static inline int vmsvga_fifo_empty(struct vmsvga_state_s *s)
  460 +{
  461 + if (!s->config || !s->enable)
  462 + return 0;
  463 + return (s->cmd->next_cmd == s->cmd->stop);
  464 +}
  465 +
  466 +static inline uint32_t vmsvga_fifo_read(struct vmsvga_state_s *s)
  467 +{
  468 + uint32_t cmd = s->fifo[s->cmd->stop >> 2];
  469 + s->cmd->stop += 4;
  470 + if (s->cmd->stop >= s->cmd->max)
  471 + s->cmd->stop = s->cmd->min;
  472 + return cmd;
  473 +}
  474 +
  475 +static void vmsvga_fifo_run(struct vmsvga_state_s *s)
  476 +{
  477 + uint32_t cmd, colour;
  478 + int args = 0;
  479 + int x, y, dx, dy, width, height;
  480 + struct vmsvga_cursor_definition_s cursor;
  481 + while (!vmsvga_fifo_empty(s))
  482 + switch (cmd = vmsvga_fifo_read(s)) {
  483 + case SVGA_CMD_UPDATE:
  484 + case SVGA_CMD_UPDATE_VERBOSE:
  485 + x = vmsvga_fifo_read(s);
  486 + y = vmsvga_fifo_read(s);
  487 + width = vmsvga_fifo_read(s);
  488 + height = vmsvga_fifo_read(s);
  489 + vmsvga_update_rect_delayed(s, x, y, width, height);
  490 + break;
  491 +
  492 + case SVGA_CMD_RECT_FILL:
  493 + colour = vmsvga_fifo_read(s);
  494 + x = vmsvga_fifo_read(s);
  495 + y = vmsvga_fifo_read(s);
  496 + width = vmsvga_fifo_read(s);
  497 + height = vmsvga_fifo_read(s);
  498 +#ifdef HW_FILL_ACCEL
  499 + vmsvga_fill_rect(s, colour, x, y, width, height);
  500 + break;
  501 +#else
  502 + goto badcmd;
  503 +#endif
  504 +
  505 + case SVGA_CMD_RECT_COPY:
  506 + x = vmsvga_fifo_read(s);
  507 + y = vmsvga_fifo_read(s);
  508 + dx = vmsvga_fifo_read(s);
  509 + dy = vmsvga_fifo_read(s);
  510 + width = vmsvga_fifo_read(s);
  511 + height = vmsvga_fifo_read(s);
  512 +#ifdef HW_RECT_ACCEL
  513 + vmsvga_copy_rect(s, x, y, dx, dy, width, height);
  514 + break;
  515 +#else
  516 + goto badcmd;
  517 +#endif
  518 +
  519 + case SVGA_CMD_DEFINE_CURSOR:
  520 + cursor.id = vmsvga_fifo_read(s);
  521 + cursor.hot_x = vmsvga_fifo_read(s);
  522 + cursor.hot_y = vmsvga_fifo_read(s);
  523 + cursor.width = x = vmsvga_fifo_read(s);
  524 + cursor.height = y = vmsvga_fifo_read(s);
  525 + vmsvga_fifo_read(s);
  526 + cursor.bpp = vmsvga_fifo_read(s);
  527 + for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args ++)
  528 + cursor.mask[args] = vmsvga_fifo_read(s);
  529 + for (args = 0; args < SVGA_PIXMAP_SIZE(x, y, cursor.bpp); args ++)
  530 + cursor.image[args] = vmsvga_fifo_read(s);
  531 +#ifdef HW_MOUSE_ACCEL
  532 + vmsvga_cursor_define(s, &cursor);
  533 + break;
  534 +#else
  535 + args = 0;
  536 + goto badcmd;
  537 +#endif
  538 +
  539 + /*
  540 + * Other commands that we at least know the number of arguments
  541 + * for so we can avoid FIFO desync if driver uses them illegally.
  542 + */
  543 + case SVGA_CMD_DEFINE_ALPHA_CURSOR:
  544 + vmsvga_fifo_read(s);
  545 + vmsvga_fifo_read(s);
  546 + vmsvga_fifo_read(s);
  547 + x = vmsvga_fifo_read(s);
  548 + y = vmsvga_fifo_read(s);
  549 + args = x * y;
  550 + goto badcmd;
  551 + case SVGA_CMD_RECT_ROP_FILL:
  552 + args = 6;
  553 + goto badcmd;
  554 + case SVGA_CMD_RECT_ROP_COPY:
  555 + args = 7;
  556 + goto badcmd;
  557 + case SVGA_CMD_DRAW_GLYPH_CLIPPED:
  558 + vmsvga_fifo_read(s);
  559 + vmsvga_fifo_read(s);
  560 + args = 7 + (vmsvga_fifo_read(s) >> 2);
  561 + goto badcmd;
  562 + case SVGA_CMD_SURFACE_ALPHA_BLEND:
  563 + args = 12;
  564 + goto badcmd;
  565 +
  566 + /*
  567 + * Other commands that are not listed as depending on any
  568 + * CAPABILITIES bits, but are not described in the README either.
  569 + */
  570 + case SVGA_CMD_SURFACE_FILL:
  571 + case SVGA_CMD_SURFACE_COPY:
  572 + case SVGA_CMD_FRONT_ROP_FILL:
  573 + case SVGA_CMD_FENCE:
  574 + case SVGA_CMD_INVALID_CMD:
  575 + break; /* Nop */
  576 +
  577 + default:
  578 + badcmd:
  579 + while (args --)
  580 + vmsvga_fifo_read(s);
  581 + printf("%s: Unknown command 0x%02x in SVGA command FIFO\n",
  582 + __FUNCTION__, cmd);
  583 + break;
  584 + }
  585 +
  586 + s->syncing = 0;
  587 +}
  588 +
  589 +static uint32_t vmsvga_index_read(void *opaque, uint32_t address)
  590 +{
  591 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  592 + return s->index;
  593 +}
  594 +
  595 +static void vmsvga_index_write(void *opaque, uint32_t address, uint32_t index)
  596 +{
  597 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  598 + s->index = index;
  599 +}
  600 +
  601 +static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
  602 +{
  603 + uint32_t caps;
  604 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  605 + switch (s->index) {
  606 + case SVGA_REG_ID:
  607 + return s->svgaid;
  608 +
  609 + case SVGA_REG_ENABLE:
  610 + return s->enable;
  611 +
  612 + case SVGA_REG_WIDTH:
  613 + return s->width;
  614 +
  615 + case SVGA_REG_HEIGHT:
  616 + return s->height;
  617 +
  618 + case SVGA_REG_MAX_WIDTH:
  619 + return SVGA_MAX_WIDTH;
  620 +
  621 + case SVGA_REG_MAX_HEIGHT:
  622 + return SVGA_MAX_WIDTH;
  623 +
  624 + case SVGA_REG_DEPTH:
  625 + return s->depth;
  626 +
  627 + case SVGA_REG_BITS_PER_PIXEL:
  628 + return (s->depth + 7) & ~7;
  629 +
  630 + case SVGA_REG_PSEUDOCOLOR:
  631 + return 0x0;
  632 +
  633 + case SVGA_REG_RED_MASK:
  634 + return s->wred;
  635 + case SVGA_REG_GREEN_MASK:
  636 + return s->wgreen;
  637 + case SVGA_REG_BLUE_MASK:
  638 + return s->wblue;
  639 +
  640 + case SVGA_REG_BYTES_PER_LINE:
  641 + return ((s->depth + 7) >> 3) * s->new_width;
  642 +
  643 + case SVGA_REG_FB_START:
  644 + return SVGA_MEM_BASE;
  645 +
  646 + case SVGA_REG_FB_OFFSET:
  647 + return 0x0;
  648 +
  649 + case SVGA_REG_VRAM_SIZE:
  650 + return s->vram_size - SVGA_FIFO_SIZE;
  651 +
  652 + case SVGA_REG_FB_SIZE:
  653 + return s->fb_size;
  654 +
  655 + case SVGA_REG_CAPABILITIES:
  656 + caps = SVGA_CAP_NONE;
  657 +#ifdef HW_RECT_ACCEL
  658 + caps |= SVGA_CAP_RECT_COPY;
  659 +#endif
  660 +#ifdef HW_FILL_ACCEL
  661 + caps |= SVGA_CAP_RECT_FILL;
  662 +#endif
  663 +#ifdef HW_MOUSE_ACCEL
  664 + if (s->ds->mouse_set)
  665 + caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 |
  666 + SVGA_CAP_CURSOR_BYPASS;
  667 +#endif
  668 + return caps;
  669 +
  670 + case SVGA_REG_MEM_START:
  671 + return SVGA_MEM_BASE + s->vram_size - SVGA_FIFO_SIZE;
  672 +
  673 + case SVGA_REG_MEM_SIZE:
  674 + return SVGA_FIFO_SIZE;
  675 +
  676 + case SVGA_REG_CONFIG_DONE:
  677 + return s->config;
  678 +
  679 + case SVGA_REG_SYNC:
  680 + case SVGA_REG_BUSY:
  681 + return s->syncing;
  682 +
  683 + case SVGA_REG_GUEST_ID:
  684 + return s->guest;
  685 +
  686 + case SVGA_REG_CURSOR_ID:
  687 + return s->cursor.id;
  688 +
  689 + case SVGA_REG_CURSOR_X:
  690 + return s->cursor.x;
  691 +
  692 + case SVGA_REG_CURSOR_Y:
  693 + return s->cursor.x;
  694 +
  695 + case SVGA_REG_CURSOR_ON:
  696 + return s->cursor.on;
  697 +
  698 + case SVGA_REG_HOST_BITS_PER_PIXEL:
  699 + return (s->depth + 7) & ~7;
  700 +
  701 + case SVGA_REG_SCRATCH_SIZE:
  702 + return s->scratch_size;
  703 +
  704 + case SVGA_REG_MEM_REGS:
  705 + case SVGA_REG_NUM_DISPLAYS:
  706 + case SVGA_REG_PITCHLOCK:
  707 + case SVGA_PALETTE_BASE ... SVGA_PALETTE_END:
  708 + return 0;
  709 +
  710 + default:
  711 + if (s->index >= SVGA_SCRATCH_BASE &&
  712 + s->index < SVGA_SCRATCH_BASE + s->scratch_size)
  713 + return s->scratch[s->index - SVGA_SCRATCH_BASE];
  714 + printf("%s: Bad register %02x\n", __FUNCTION__, s->index);
  715 + }
  716 +
  717 + return 0;
  718 +}
  719 +
  720 +static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
  721 +{
  722 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  723 + switch (s->index) {
  724 + case SVGA_REG_ID:
  725 + if (value == SVGA_ID_2 || value == SVGA_ID_1 || value == SVGA_ID_0)
  726 + s->svgaid = value;
  727 + break;
  728 +
  729 + case SVGA_REG_ENABLE:
  730 + s->enable = s->config = value & s->config;
  731 + s->width = -1;
  732 + s->height = -1;
  733 + s->invalidated = 1;
  734 +#ifdef EMBED_STDVGA
  735 + s->invalidate(opaque);
  736 +#endif
  737 + if (s->enable)
  738 + s->fb_size = ((s->depth + 7) >> 3) * s->new_width * s->new_height;
  739 + break;
  740 +
  741 + case SVGA_REG_WIDTH:
  742 + s->new_width = value;
  743 + s->invalidated = 1;
  744 + break;
  745 +
  746 + case SVGA_REG_HEIGHT:
  747 + s->new_height = value;
  748 + s->invalidated = 1;
  749 + break;
  750 +
  751 + case SVGA_REG_DEPTH:
  752 + case SVGA_REG_BITS_PER_PIXEL:
  753 + if (value != s->depth) {
  754 + printf("%s: Bad colour depth: %i bits\n", __FUNCTION__, value);
  755 + s->config = 0;
  756 + }
  757 + break;
  758 +
  759 + case SVGA_REG_CONFIG_DONE:
  760 + if (value) {
  761 + s->fifo = (uint32_t *) &s->vram[s->vram_size - SVGA_FIFO_SIZE];
  762 + /* Check range and alignment. */
  763 + if ((s->cmd->min | s->cmd->max |
  764 + s->cmd->next_cmd | s->cmd->stop) & 3)
  765 + break;
  766 + if (s->cmd->min < (uint8_t *) s->cmd->fifo - (uint8_t *) s->fifo)
  767 + break;
  768 + if (s->cmd->max > SVGA_FIFO_SIZE)
  769 + break;
  770 + if (s->cmd->max < s->cmd->min + 10 * 1024)
  771 + break;
  772 + }
  773 + s->config = value;
  774 + break;
  775 +
  776 + case SVGA_REG_SYNC:
  777 + s->syncing = 1;
  778 + vmsvga_fifo_run(s); /* Or should we just wait for update_display? */
  779 + break;
  780 +
  781 + case SVGA_REG_GUEST_ID:
  782 + s->guest = value;
  783 +#ifdef VERBOSE
  784 + if (value >= GUEST_OS_BASE && value < GUEST_OS_BASE +
  785 + sizeof(vmsvga_guest_id) / sizeof(*vmsvga_guest_id))
  786 + printf("%s: guest runs %s.\n", __FUNCTION__,
  787 + vmsvga_guest_id[value - GUEST_OS_BASE]);
  788 +#endif
  789 + break;
  790 +
  791 + case SVGA_REG_CURSOR_ID:
  792 + s->cursor.id = value;
  793 + break;
  794 +
  795 + case SVGA_REG_CURSOR_X:
  796 + s->cursor.x = value;
  797 + break;
  798 +
  799 + case SVGA_REG_CURSOR_Y:
  800 + s->cursor.y = value;
  801 + break;
  802 +
  803 + case SVGA_REG_CURSOR_ON:
  804 + s->cursor.on |= (value == SVGA_CURSOR_ON_SHOW);
  805 + s->cursor.on &= (value != SVGA_CURSOR_ON_HIDE);
  806 +#ifdef HW_MOUSE_ACCEL
  807 + if (s->ds->mouse_set && value <= SVGA_CURSOR_ON_SHOW)
  808 + s->ds->mouse_set(s->cursor.x, s->cursor.y, s->cursor.on);
  809 +#endif
  810 + break;
  811 +
  812 + case SVGA_REG_MEM_REGS:
  813 + case SVGA_REG_NUM_DISPLAYS:
  814 + case SVGA_REG_PITCHLOCK:
  815 + case SVGA_PALETTE_BASE ... SVGA_PALETTE_END:
  816 + break;
  817 +
  818 + default:
  819 + if (s->index >= SVGA_SCRATCH_BASE &&
  820 + s->index < SVGA_SCRATCH_BASE + s->scratch_size) {
  821 + s->scratch[s->index - SVGA_SCRATCH_BASE] = value;
  822 + break;
  823 + }
  824 + printf("%s: Bad register %02x\n", __FUNCTION__, s->index);
  825 + }
  826 +}
  827 +
  828 +static uint32_t vmsvga_bios_read(void *opaque, uint32_t address)
  829 +{
  830 + printf("%s: what are we supposed to return?\n", __FUNCTION__);
  831 + return 0xcafe;
  832 +}
  833 +
  834 +static void vmsvga_bios_write(void *opaque, uint32_t address, uint32_t data)
  835 +{
  836 + printf("%s: what are we supposed to do with (%08x)?\n",
  837 + __FUNCTION__, data);
  838 +}
  839 +
  840 +static inline void vmsvga_size(struct vmsvga_state_s *s)
  841 +{
  842 + if (s->new_width != s->width || s->new_height != s->height) {
  843 + s->width = s->new_width;
  844 + s->height = s->new_height;
  845 + dpy_resize(s->ds, s->width, s->height);
  846 + s->invalidated = 1;
  847 + }
  848 +}
  849 +
  850 +static void vmsvga_update_display(void *opaque)
  851 +{
  852 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  853 + if (!s->enable) {
  854 +#ifdef EMBED_STDVGA
  855 + s->update(opaque);
  856 +#endif
  857 + return;
  858 + }
  859 +
  860 + vmsvga_size(s);
  861 +
  862 + vmsvga_fifo_run(s);
  863 + vmsvga_update_rect_flush(s);
  864 +
  865 + /*
  866 + * Is it more efficient to look at vram VGA-dirty bits or wait
  867 + * for the driver to issue SVGA_CMD_UPDATE?
  868 + */
  869 + if (s->invalidated) {
  870 + s->invalidated = 0;
  871 + vmsvga_update_screen(s);
  872 + }
  873 +}
  874 +
  875 +static void vmsvga_reset(struct vmsvga_state_s *s)
  876 +{
  877 + s->index = 0;
  878 + s->enable = 0;
  879 + s->config = 0;
  880 + s->width = -1;
  881 + s->height = -1;
  882 + s->svgaid = SVGA_ID;
  883 + s->depth = s->ds->depth ? s->ds->depth : 24;
  884 + s->bypp = (s->depth + 7) >> 3;
  885 + s->cursor.on = 0;
  886 + s->redraw_fifo_first = 0;
  887 + s->redraw_fifo_last = 0;
  888 + switch (s->depth) {
  889 + case 8:
  890 + s->wred = 0x00000007;
  891 + s->wgreen = 0x00000038;
  892 + s->wblue = 0x000000c0;
  893 + break;
  894 + case 15:
  895 + s->wred = 0x0000001f;
  896 + s->wgreen = 0x000003e0;
  897 + s->wblue = 0x00007c00;
  898 + break;
  899 + case 16:
  900 + s->wred = 0x0000001f;
  901 + s->wgreen = 0x000007e0;
  902 + s->wblue = 0x0000f800;
  903 + break;
  904 + case 24:
  905 + s->wred = 0x000000ff;
  906 + s->wgreen = 0x0000ff00;
  907 + s->wblue = 0x00ff0000;
  908 + break;
  909 + case 32:
  910 + s->wred = 0x000000ff;
  911 + s->wgreen = 0x0000ff00;
  912 + s->wblue = 0x00ff0000;
  913 + break;
  914 + }
  915 + s->syncing = 0;
  916 +}
  917 +
  918 +static void vmsvga_invalidate_display(void *opaque)
  919 +{
  920 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  921 + if (!s->enable) {
  922 +#ifdef EMBED_STDVGA
  923 + s->invalidate(opaque);
  924 +#endif
  925 + return;
  926 + }
  927 +
  928 + s->invalidated = 1;
  929 +}
  930 +
  931 +static void vmsvga_screen_dump(void *opaque, const char *filename)
  932 +{
  933 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  934 + if (!s->enable) {
  935 +#ifdef EMBED_STDVGA
  936 + s->screen_dump(opaque, filename);
  937 +#endif
  938 + return;
  939 + }
  940 +
  941 + /* TODO */
  942 +}
  943 +
  944 +#ifdef DIRECT_VRAM
  945 +static uint32_t vmsvga_vram_readb(void *opaque, target_phys_addr_t addr)
  946 +{
  947 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  948 + addr -= SVGA_MEM_BASE;
  949 + if (addr < s->fb_size)
  950 + return *(uint8_t *) (s->ds->data + addr);
  951 + else
  952 + return *(uint8_t *) (s->vram + addr);
  953 +}
  954 +
  955 +static uint32_t vmsvga_vram_readw(void *opaque, target_phys_addr_t addr)
  956 +{
  957 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  958 + addr -= SVGA_MEM_BASE;
  959 + if (addr < s->fb_size)
  960 + return *(uint16_t *) (s->ds->data + addr);
  961 + else
  962 + return *(uint16_t *) (s->vram + addr);
  963 +}
  964 +
  965 +static uint32_t vmsvga_vram_readl(void *opaque, target_phys_addr_t addr)
  966 +{
  967 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  968 + addr -= SVGA_MEM_BASE;
  969 + if (addr < s->fb_size)
  970 + return *(uint32_t *) (s->ds->data + addr);
  971 + else
  972 + return *(uint32_t *) (s->vram + addr);
  973 +}
  974 +
  975 +static void vmsvga_vram_writeb(void *opaque, target_phys_addr_t addr,
  976 + uint32_t value)
  977 +{
  978 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  979 + addr -= SVGA_MEM_BASE;
  980 + if (addr < s->fb_size)
  981 + *(uint8_t *) (s->ds->data + addr) = value;
  982 + else
  983 + *(uint8_t *) (s->vram + addr) = value;
  984 +}
  985 +
  986 +static void vmsvga_vram_writew(void *opaque, target_phys_addr_t addr,
  987 + uint32_t value)
  988 +{
  989 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  990 + addr -= SVGA_MEM_BASE;
  991 + if (addr < s->fb_size)
  992 + *(uint16_t *) (s->ds->data + addr) = value;
  993 + else
  994 + *(uint16_t *) (s->vram + addr) = value;
  995 +}
  996 +
  997 +static void vmsvga_vram_writel(void *opaque, target_phys_addr_t addr,
  998 + uint32_t value)
  999 +{
  1000 + struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
  1001 + addr -= SVGA_MEM_BASE;
  1002 + if (addr < s->fb_size)
  1003 + *(uint32_t *) (s->ds->data + addr) = value;
  1004 + else
  1005 + *(uint32_t *) (s->vram + addr) = value;
  1006 +}
  1007 +
  1008 +static CPUReadMemoryFunc *vmsvga_vram_read[] = {
  1009 + vmsvga_vram_readb,
  1010 + vmsvga_vram_readw,
  1011 + vmsvga_vram_readl,
  1012 +};
  1013 +
  1014 +static CPUWriteMemoryFunc *vmsvga_vram_write[] = {
  1015 + vmsvga_vram_writeb,
  1016 + vmsvga_vram_writew,
  1017 + vmsvga_vram_writel,
  1018 +};
  1019 +#endif
  1020 +
  1021 +static void vmsvga_save(struct vmsvga_state_s *s, QEMUFile *f)
  1022 +{
  1023 + qemu_put_be32s(f, &s->depth);
  1024 + qemu_put_be32s(f, &s->enable);
  1025 + qemu_put_be32s(f, &s->config);
  1026 + qemu_put_be32s(f, &s->cursor.id);
  1027 + qemu_put_be32s(f, &s->cursor.x);
  1028 + qemu_put_be32s(f, &s->cursor.y);
  1029 + qemu_put_be32s(f, &s->cursor.on);
  1030 + qemu_put_be32s(f, &s->index);
  1031 + qemu_put_buffer(f, (uint8_t *) s->scratch, s->scratch_size * 4);
  1032 + qemu_put_be32s(f, &s->new_width);
  1033 + qemu_put_be32s(f, &s->new_height);
  1034 + qemu_put_be32s(f, &s->guest);
  1035 + qemu_put_be32s(f, &s->svgaid);
  1036 + qemu_put_be32s(f, &s->syncing);
  1037 + qemu_put_be32s(f, &s->fb_size);
  1038 +}
  1039 +
  1040 +static int vmsvga_load(struct vmsvga_state_s *s, QEMUFile *f)
  1041 +{
  1042 + int depth;
  1043 + qemu_get_be32s(f, &depth);
  1044 + qemu_get_be32s(f, &s->enable);
  1045 + qemu_get_be32s(f, &s->config);
  1046 + qemu_get_be32s(f, &s->cursor.id);
  1047 + qemu_get_be32s(f, &s->cursor.x);
  1048 + qemu_get_be32s(f, &s->cursor.y);
  1049 + qemu_get_be32s(f, &s->cursor.on);
  1050 + qemu_get_be32s(f, &s->index);
  1051 + qemu_get_buffer(f, (uint8_t *) s->scratch, s->scratch_size * 4);
  1052 + qemu_get_be32s(f, &s->new_width);
  1053 + qemu_get_be32s(f, &s->new_height);
  1054 + qemu_get_be32s(f, &s->guest);
  1055 + qemu_get_be32s(f, &s->svgaid);
  1056 + qemu_get_be32s(f, &s->syncing);
  1057 + qemu_get_be32s(f, &s->fb_size);
  1058 +
  1059 + if (s->enable && depth != s->depth) {
  1060 + printf("%s: need colour depth of %i bits to resume operation.\n",
  1061 + __FUNCTION__, depth);
  1062 + return -EINVAL;
  1063 + }
  1064 +
  1065 + s->invalidated = 1;
  1066 + if (s->config)
  1067 + s->fifo = (uint32_t *) &s->vram[s->vram_size - SVGA_FIFO_SIZE];
  1068 +
  1069 + return 0;
  1070 +}
  1071 +
  1072 +static void vmsvga_init(struct vmsvga_state_s *s, DisplayState *ds,
  1073 + uint8_t *vga_ram_base, unsigned long vga_ram_offset,
  1074 + int vga_ram_size)
  1075 +{
  1076 + int iomemtype;
  1077 + s->ds = ds;
  1078 + s->vram = vga_ram_base;
  1079 + s->vram_size = vga_ram_size;
  1080 +
  1081 + s->scratch_size = SVGA_SCRATCH_SIZE;
  1082 + s->scratch = (uint32_t *) qemu_malloc(s->scratch_size * 4);
  1083 +
  1084 + vmsvga_reset(s);
  1085 +
  1086 +#ifdef DIRECT_VRAM
  1087 + iomemtype = cpu_register_io_memory(0, vmsvga_vram_read,
  1088 + vmsvga_vram_write, s);
  1089 +#else
  1090 + iomemtype = vga_ram_offset | IO_MEM_RAM;
  1091 +#endif
  1092 + cpu_register_physical_memory(SVGA_MEM_BASE, vga_ram_size,
  1093 + iomemtype);
  1094 +
  1095 + register_ioport_read(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_INDEX_PORT,
  1096 + 1, 4, vmsvga_index_read, s);
  1097 + register_ioport_write(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_INDEX_PORT,
  1098 + 1, 4, vmsvga_index_write, s);
  1099 + register_ioport_read(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_VALUE_PORT,
  1100 + 1, 4, vmsvga_value_read, s);
  1101 + register_ioport_write(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_VALUE_PORT,
  1102 + 1, 4, vmsvga_value_write, s);
  1103 + register_ioport_read(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_BIOS_PORT,
  1104 + 1, 4, vmsvga_bios_read, s);
  1105 + register_ioport_write(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_BIOS_PORT,
  1106 + 1, 4, vmsvga_bios_write, s);
  1107 +
  1108 + graphic_console_init(ds, vmsvga_update_display,
  1109 + vmsvga_invalidate_display, vmsvga_screen_dump, s);
  1110 +
  1111 +#ifdef EMBED_STDVGA
  1112 + vga_common_init((VGAState *) s, ds,
  1113 + vga_ram_base, vga_ram_offset, vga_ram_size);
  1114 + vga_init((VGAState *) s);
  1115 +#endif
  1116 +}
  1117 +
  1118 +static void pci_vmsvga_save(QEMUFile *f, void *opaque)
  1119 +{
  1120 + struct pci_vmsvga_state_s *s = (struct pci_vmsvga_state_s *) opaque;
  1121 + pci_device_save(&s->card, f);
  1122 + vmsvga_save(&s->chip, f);
  1123 +}
  1124 +
  1125 +static int pci_vmsvga_load(QEMUFile *f, void *opaque, int version_id)
  1126 +{
  1127 + struct pci_vmsvga_state_s *s = (struct pci_vmsvga_state_s *) opaque;
  1128 + int ret;
  1129 +
  1130 + ret = pci_device_load(&s->card, f);
  1131 + if (ret < 0)
  1132 + return ret;
  1133 +
  1134 + ret = vmsvga_load(&s->chip, f);
  1135 + if (ret < 0)
  1136 + return ret;
  1137 +
  1138 + return 0;
  1139 +}
  1140 +
  1141 +#define PCI_VENDOR_ID_VMWARE 0x15ad
  1142 +#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405
  1143 +#define PCI_DEVICE_ID_VMWARE_SVGA 0x0710
  1144 +#define PCI_DEVICE_ID_VMWARE_NET 0x0720
  1145 +#define PCI_DEVICE_ID_VMWARE_SCSI 0x0730
  1146 +#define PCI_DEVICE_ID_VMWARE_IDE 0x1729
  1147 +#define PCI_CLASS_BASE_DISPLAY 0x03
  1148 +#define PCI_CLASS_SUB_VGA 0x00
  1149 +#define PCI_CLASS_HEADERTYPE_00h 0x00
  1150 +
  1151 +void pci_vmsvga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
  1152 + unsigned long vga_ram_offset, int vga_ram_size)
  1153 +{
  1154 + struct pci_vmsvga_state_s *s;
  1155 +
  1156 + /* Setup PCI configuration */
  1157 + s = (struct pci_vmsvga_state_s *)
  1158 + pci_register_device(bus, "QEMUware SVGA",
  1159 + sizeof(struct pci_vmsvga_state_s), -1, 0, 0);
  1160 + s->card.config[PCI_VENDOR_ID] = PCI_VENDOR_ID_VMWARE & 0xff;
  1161 + s->card.config[PCI_VENDOR_ID + 1] = PCI_VENDOR_ID_VMWARE >> 8;
  1162 + s->card.config[PCI_DEVICE_ID] = SVGA_PCI_DEVICE_ID & 0xff;
  1163 + s->card.config[PCI_DEVICE_ID + 1] = SVGA_PCI_DEVICE_ID >> 8;
  1164 + s->card.config[PCI_COMMAND] = 0x07; /* I/O + Memory */
  1165 + s->card.config[PCI_CLASS_DEVICE] = PCI_CLASS_SUB_VGA;
  1166 + s->card.config[0x0b] = PCI_CLASS_BASE_DISPLAY;
  1167 + s->card.config[0x0c] = 0x08; /* Cache line size */
  1168 + s->card.config[0x0d] = 0x40; /* Latency timer */
  1169 + s->card.config[0x0e] = PCI_CLASS_HEADERTYPE_00h;
  1170 + s->card.config[0x10] = ((SVGA_IO_BASE >> 0) & 0xff) | 1;
  1171 + s->card.config[0x11] = (SVGA_IO_BASE >> 8) & 0xff;
  1172 + s->card.config[0x12] = (SVGA_IO_BASE >> 16) & 0xff;
  1173 + s->card.config[0x13] = (SVGA_IO_BASE >> 24) & 0xff;
  1174 + s->card.config[0x18] = (SVGA_MEM_BASE >> 0) & 0xff;
  1175 + s->card.config[0x19] = (SVGA_MEM_BASE >> 8) & 0xff;
  1176 + s->card.config[0x1a] = (SVGA_MEM_BASE >> 16) & 0xff;
  1177 + s->card.config[0x1b] = (SVGA_MEM_BASE >> 24) & 0xff;
  1178 + s->card.config[0x2c] = PCI_VENDOR_ID_VMWARE & 0xff;
  1179 + s->card.config[0x2d] = PCI_VENDOR_ID_VMWARE >> 8;
  1180 + s->card.config[0x2e] = SVGA_PCI_DEVICE_ID & 0xff;
  1181 + s->card.config[0x2f] = SVGA_PCI_DEVICE_ID >> 8;
  1182 + s->card.config[0x3c] = 0xff; /* End */
  1183 +
  1184 + vmsvga_init(&s->chip, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
  1185 +
  1186 + register_savevm("vmware_vga", 0, 0, pci_vmsvga_save, pci_vmsvga_load, s);
  1187 +}
... ...
... ... @@ -44,6 +44,9 @@ static int width, height;
44 44 static SDL_Cursor *sdl_cursor_normal;
45 45 static SDL_Cursor *sdl_cursor_hidden;
46 46 static int absolute_enabled = 0;
  47 +static int guest_cursor = 0;
  48 +static int guest_x, guest_y;
  49 +static SDL_Cursor *guest_sprite = 0;
47 50  
48 51 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
49 52 {
... ... @@ -245,13 +248,21 @@ static void sdl_show_cursor(void)
245 248 {
246 249 if (!kbd_mouse_is_absolute()) {
247 250 SDL_ShowCursor(1);
248   - SDL_SetCursor(sdl_cursor_normal);
  251 + if (guest_cursor &&
  252 + (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
  253 + SDL_SetCursor(guest_sprite);
  254 + else
  255 + SDL_SetCursor(sdl_cursor_normal);
249 256 }
250 257 }
251 258  
252 259 static void sdl_grab_start(void)
253 260 {
254   - sdl_hide_cursor();
  261 + if (guest_cursor) {
  262 + SDL_SetCursor(guest_sprite);
  263 + SDL_WarpMouse(guest_x, guest_y);
  264 + } else
  265 + sdl_hide_cursor();
255 266 SDL_WM_GrabInput(SDL_GRAB_ON);
256 267 /* dummy read to avoid moving the mouse */
257 268 SDL_GetRelativeMouseState(NULL, NULL);
... ... @@ -262,8 +273,8 @@ static void sdl_grab_start(void)
262 273 static void sdl_grab_end(void)
263 274 {
264 275 SDL_WM_GrabInput(SDL_GRAB_OFF);
265   - sdl_show_cursor();
266 276 gui_grab = 0;
  277 + sdl_show_cursor();
267 278 sdl_update_caption();
268 279 }
269 280  
... ... @@ -294,6 +305,12 @@ static void sdl_send_mouse_event(int dz)
294 305 } else if (absolute_enabled) {
295 306 sdl_show_cursor();
296 307 absolute_enabled = 0;
  308 + } else if (guest_cursor) {
  309 + SDL_GetMouseState(&dx, &dy);
  310 + dx -= guest_x;
  311 + dy -= guest_y;
  312 + guest_x += dx;
  313 + guest_y += dy;
297 314 }
298 315  
299 316 kbd_mouse_event(dx, dy, dz, buttons);
... ... @@ -472,8 +489,77 @@ static void sdl_refresh(DisplayState *ds)
472 489 }
473 490 }
474 491  
  492 +static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c)
  493 +{
  494 + SDL_Rect dst = { x, y, w, h };
  495 + SDL_FillRect(screen, &dst, c);
  496 +}
  497 +
  498 +static void sdl_mouse_warp(int x, int y, int on)
  499 +{
  500 + if (on) {
  501 + if (!guest_cursor)
  502 + sdl_show_cursor();
  503 + if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) {
  504 + SDL_SetCursor(guest_sprite);
  505 + SDL_WarpMouse(x, y);
  506 + }
  507 + } else if (gui_grab)
  508 + sdl_hide_cursor();
  509 + guest_cursor = on;
  510 + guest_x = x, guest_y = y;
  511 +}
  512 +
  513 +static void sdl_mouse_define(int width, int height, int bpp,
  514 + int hot_x, int hot_y,
  515 + uint8_t *image, uint8_t *mask)
  516 +{
  517 + uint8_t sprite[256], *line;
  518 + int x, y, dst, bypl, src = 0;
  519 + if (guest_sprite)
  520 + SDL_FreeCursor(guest_sprite);
  521 +
  522 + memset(sprite, 0, 256);
  523 + bypl = ((width * bpp + 31) >> 5) << 2;
  524 + for (y = 0, dst = 0; y < height; y ++, image += bypl) {
  525 + line = image;
  526 + for (x = 0; x < width; x ++, dst ++) {
  527 + switch (bpp) {
  528 + case 24:
  529 + src = *(line ++); src |= *(line ++); src |= *(line ++);
  530 + break;
  531 + case 16:
  532 + case 15:
  533 + src = *(line ++); src |= *(line ++);
  534 + break;
  535 + case 8:
  536 + src = *(line ++);
  537 + break;
  538 + case 4:
  539 + src = 0xf & (line[x >> 1] >> ((x & 1)) << 2);
  540 + break;
  541 + case 2:
  542 + src = 3 & (line[x >> 2] >> ((x & 3)) << 1);
  543 + break;
  544 + case 1:
  545 + src = 1 & (line[x >> 3] >> (x & 7));
  546 + break;
  547 + }
  548 + if (!src)
  549 + sprite[dst >> 3] |= (1 << (~dst & 7)) & mask[dst >> 3];
  550 + }
  551 + }
  552 + guest_sprite = SDL_CreateCursor(sprite, mask, width, height, hot_x, hot_y);
  553 +
  554 + if (guest_cursor &&
  555 + (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
  556 + SDL_SetCursor(guest_sprite);
  557 +}
  558 +
475 559 static void sdl_cleanup(void)
476 560 {
  561 + if (guest_sprite)
  562 + SDL_FreeCursor(guest_sprite);
477 563 SDL_Quit();
478 564 }
479 565  
... ... @@ -510,6 +596,9 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
510 596 ds->dpy_update = sdl_update;
511 597 ds->dpy_resize = sdl_resize;
512 598 ds->dpy_refresh = sdl_refresh;
  599 + ds->dpy_fill = sdl_fill;
  600 + ds->mouse_set = sdl_mouse_warp;
  601 + ds->cursor_define = sdl_mouse_define;
513 602  
514 603 sdl_resize(ds, 640, 400);
515 604 sdl_update_caption();
... ...
... ... @@ -154,6 +154,7 @@ QEMUTimer *gui_timer;
154 154 int vm_running;
155 155 int rtc_utc = 1;
156 156 int cirrus_vga_enabled = 1;
  157 +int vmsvga_enabled = 0;
157 158 #ifdef TARGET_SPARC
158 159 int graphic_width = 1024;
159 160 int graphic_height = 768;
... ... @@ -543,6 +544,10 @@ int kbd_mouse_is_absolute(void)
543 544 return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
544 545 }
545 546  
  547 +void (*kbd_mouse_set)(int x, int y, int on) = NULL;
  548 +void (*kbd_cursor_define)(int width, int height, int bpp, int hot_x, int hot_y,
  549 + uint8_t *image, uint8_t *mask) = NULL;
  550 +
546 551 void do_info_mice(void)
547 552 {
548 553 QEMUPutMouseEntry *cursor;
... ... @@ -6509,6 +6514,7 @@ enum {
6509 6514 QEMU_OPTION_k,
6510 6515 QEMU_OPTION_localtime,
6511 6516 QEMU_OPTION_cirrusvga,
  6517 + QEMU_OPTION_vmsvga,
6512 6518 QEMU_OPTION_g,
6513 6519 QEMU_OPTION_std_vga,
6514 6520 QEMU_OPTION_echr,
... ... @@ -6616,6 +6622,7 @@ const QEMUOption qemu_options[] = {
6616 6622 /* temporary options */
6617 6623 { "usb", 0, QEMU_OPTION_usb },
6618 6624 { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
  6625 + { "vmwarevga", 0, QEMU_OPTION_vmsvga },
6619 6626 { "no-acpi", 0, QEMU_OPTION_no_acpi },
6620 6627 { "no-reboot", 0, QEMU_OPTION_no_reboot },
6621 6628 { "daemonize", 0, QEMU_OPTION_daemonize },
... ... @@ -7184,9 +7191,15 @@ int main(int argc, char **argv)
7184 7191 break;
7185 7192 case QEMU_OPTION_cirrusvga:
7186 7193 cirrus_vga_enabled = 1;
  7194 + vmsvga_enabled = 0;
  7195 + break;
  7196 + case QEMU_OPTION_vmsvga:
  7197 + cirrus_vga_enabled = 0;
  7198 + vmsvga_enabled = 1;
7187 7199 break;
7188 7200 case QEMU_OPTION_std_vga:
7189 7201 cirrus_vga_enabled = 0;
  7202 + vmsvga_enabled = 0;
7190 7203 break;
7191 7204 case QEMU_OPTION_g:
7192 7205 {
... ...
... ... @@ -149,6 +149,7 @@ extern int ram_size;
149 149 extern int bios_size;
150 150 extern int rtc_utc;
151 151 extern int cirrus_vga_enabled;
  152 +extern int vmsvga_enabled;
152 153 extern int graphic_width;
153 154 extern int graphic_height;
154 155 extern int graphic_depth;
... ... @@ -903,7 +904,13 @@ struct DisplayState {
903 904 void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
904 905 void (*dpy_resize)(struct DisplayState *s, int w, int h);
905 906 void (*dpy_refresh)(struct DisplayState *s);
906   - void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h);
  907 + void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
  908 + int dst_x, int dst_y, int w, int h);
  909 + void (*dpy_fill)(struct DisplayState *s, int x, int y,
  910 + int w, int h, uint32_t c);
  911 + void (*mouse_set)(int x, int y, int on);
  912 + void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y,
  913 + uint8_t *image, uint8_t *mask);
907 914 };
908 915  
909 916 static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
... ... @@ -928,6 +935,10 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
928 935 void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
929 936 unsigned long vga_ram_offset, int vga_ram_size);
930 937  
  938 +/* vmware_vga.c */
  939 +void pci_vmsvga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
  940 + unsigned long vga_ram_offset, int vga_ram_size);
  941 +
931 942 /* sdl.c */
932 943 void sdl_display_init(DisplayState *ds, int full_screen, int no_frame);
933 944  
... ...