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#include "qemu/osdep.h"
26#include "qemu/module.h"
27#include "qemu/units.h"
28#include "qapi/error.h"
29#include "qemu/log.h"
30#include "hw/loader.h"
31#include "trace.h"
32#include "hw/pci/pci.h"
33#include "hw/qdev-properties.h"
34#include "migration/vmstate.h"
35#include "qom/object.h"
36
37#undef VERBOSE
38#define HW_RECT_ACCEL
39#define HW_FILL_ACCEL
40#define HW_MOUSE_ACCEL
41
42#include "vga_int.h"
43
44
45
46struct vmsvga_state_s {
47 VGACommonState vga;
48
49 int invalidated;
50 int enable;
51 int config;
52 struct {
53 int id;
54 int x;
55 int y;
56 int on;
57 } cursor;
58
59 int index;
60 int scratch_size;
61 uint32_t *scratch;
62 int new_width;
63 int new_height;
64 int new_depth;
65 uint32_t guest;
66 uint32_t svgaid;
67 int syncing;
68
69 MemoryRegion fifo_ram;
70 uint8_t *fifo_ptr;
71 unsigned int fifo_size;
72
73 uint32_t *fifo;
74 uint32_t fifo_min;
75 uint32_t fifo_max;
76 uint32_t fifo_next;
77 uint32_t fifo_stop;
78
79#define REDRAW_FIFO_LEN 512
80 struct vmsvga_rect_s {
81 int x, y, w, h;
82 } redraw_fifo[REDRAW_FIFO_LEN];
83 int redraw_fifo_first, redraw_fifo_last;
84};
85
86#define TYPE_VMWARE_SVGA "vmware-svga"
87
88DECLARE_INSTANCE_CHECKER(struct pci_vmsvga_state_s, VMWARE_SVGA,
89 TYPE_VMWARE_SVGA)
90
91struct pci_vmsvga_state_s {
92
93 PCIDevice parent_obj;
94
95
96 struct vmsvga_state_s chip;
97 MemoryRegion io_bar;
98};
99
100#define SVGA_MAGIC 0x900000UL
101#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver))
102#define SVGA_ID_0 SVGA_MAKE_ID(0)
103#define SVGA_ID_1 SVGA_MAKE_ID(1)
104#define SVGA_ID_2 SVGA_MAKE_ID(2)
105
106#define SVGA_LEGACY_BASE_PORT 0x4560
107#define SVGA_INDEX_PORT 0x0
108#define SVGA_VALUE_PORT 0x1
109#define SVGA_BIOS_PORT 0x2
110
111#define SVGA_VERSION_2
112
113#ifdef SVGA_VERSION_2
114# define SVGA_ID SVGA_ID_2
115# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
116# define SVGA_IO_MUL 1
117# define SVGA_FIFO_SIZE 0x10000
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_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA
125#endif
126
127enum {
128
129 SVGA_REG_ID = 0,
130 SVGA_REG_ENABLE = 1,
131 SVGA_REG_WIDTH = 2,
132 SVGA_REG_HEIGHT = 3,
133 SVGA_REG_MAX_WIDTH = 4,
134 SVGA_REG_MAX_HEIGHT = 5,
135 SVGA_REG_DEPTH = 6,
136 SVGA_REG_BITS_PER_PIXEL = 7,
137 SVGA_REG_PSEUDOCOLOR = 8,
138 SVGA_REG_RED_MASK = 9,
139 SVGA_REG_GREEN_MASK = 10,
140 SVGA_REG_BLUE_MASK = 11,
141 SVGA_REG_BYTES_PER_LINE = 12,
142 SVGA_REG_FB_START = 13,
143 SVGA_REG_FB_OFFSET = 14,
144 SVGA_REG_VRAM_SIZE = 15,
145 SVGA_REG_FB_SIZE = 16,
146
147
148 SVGA_REG_CAPABILITIES = 17,
149 SVGA_REG_MEM_START = 18,
150 SVGA_REG_MEM_SIZE = 19,
151 SVGA_REG_CONFIG_DONE = 20,
152 SVGA_REG_SYNC = 21,
153 SVGA_REG_BUSY = 22,
154 SVGA_REG_GUEST_ID = 23,
155 SVGA_REG_CURSOR_ID = 24,
156 SVGA_REG_CURSOR_X = 25,
157 SVGA_REG_CURSOR_Y = 26,
158 SVGA_REG_CURSOR_ON = 27,
159 SVGA_REG_HOST_BITS_PER_PIXEL = 28,
160 SVGA_REG_SCRATCH_SIZE = 29,
161 SVGA_REG_MEM_REGS = 30,
162 SVGA_REG_NUM_DISPLAYS = 31,
163 SVGA_REG_PITCHLOCK = 32,
164
165 SVGA_PALETTE_BASE = 1024,
166 SVGA_PALETTE_END = SVGA_PALETTE_BASE + 767,
167 SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + 768,
168};
169
170#define SVGA_CAP_NONE 0
171#define SVGA_CAP_RECT_FILL (1 << 0)
172#define SVGA_CAP_RECT_COPY (1 << 1)
173#define SVGA_CAP_RECT_PAT_FILL (1 << 2)
174#define SVGA_CAP_LEGACY_OFFSCREEN (1 << 3)
175#define SVGA_CAP_RASTER_OP (1 << 4)
176#define SVGA_CAP_CURSOR (1 << 5)
177#define SVGA_CAP_CURSOR_BYPASS (1 << 6)
178#define SVGA_CAP_CURSOR_BYPASS_2 (1 << 7)
179#define SVGA_CAP_8BIT_EMULATION (1 << 8)
180#define SVGA_CAP_ALPHA_CURSOR (1 << 9)
181#define SVGA_CAP_GLYPH (1 << 10)
182#define SVGA_CAP_GLYPH_CLIPPING (1 << 11)
183#define SVGA_CAP_OFFSCREEN_1 (1 << 12)
184#define SVGA_CAP_ALPHA_BLEND (1 << 13)
185#define SVGA_CAP_3D (1 << 14)
186#define SVGA_CAP_EXTENDED_FIFO (1 << 15)
187#define SVGA_CAP_MULTIMON (1 << 16)
188#define SVGA_CAP_PITCHLOCK (1 << 17)
189
190
191
192
193enum {
194
195
196
197 SVGA_FIFO_MIN = 0,
198 SVGA_FIFO_MAX,
199 SVGA_FIFO_NEXT,
200 SVGA_FIFO_STOP,
201
202
203
204
205 SVGA_FIFO_CAPABILITIES = 4,
206 SVGA_FIFO_FLAGS,
207 SVGA_FIFO_FENCE,
208 SVGA_FIFO_3D_HWVERSION,
209 SVGA_FIFO_PITCHLOCK,
210};
211
212#define SVGA_FIFO_CAP_NONE 0
213#define SVGA_FIFO_CAP_FENCE (1 << 0)
214#define SVGA_FIFO_CAP_ACCELFRONT (1 << 1)
215#define SVGA_FIFO_CAP_PITCHLOCK (1 << 2)
216
217#define SVGA_FIFO_FLAG_NONE 0
218#define SVGA_FIFO_FLAG_ACCELFRONT (1 << 0)
219
220
221#define SVGA_SCRATCH_SIZE 0x8000
222#define SVGA_MAX_WIDTH 2368
223#define SVGA_MAX_HEIGHT 1770
224
225#ifdef VERBOSE
226# define GUEST_OS_BASE 0x5001
227static const char *vmsvga_guest_id[] = {
228 [0x00] = "Dos",
229 [0x01] = "Windows 3.1",
230 [0x02] = "Windows 95",
231 [0x03] = "Windows 98",
232 [0x04] = "Windows ME",
233 [0x05] = "Windows NT",
234 [0x06] = "Windows 2000",
235 [0x07] = "Linux",
236 [0x08] = "OS/2",
237 [0x09] = "an unknown OS",
238 [0x0a] = "BSD",
239 [0x0b] = "Whistler",
240 [0x0c] = "an unknown OS",
241 [0x0d] = "an unknown OS",
242 [0x0e] = "an unknown OS",
243 [0x0f] = "an unknown OS",
244 [0x10] = "an unknown OS",
245 [0x11] = "an unknown OS",
246 [0x12] = "an unknown OS",
247 [0x13] = "an unknown OS",
248 [0x14] = "an unknown OS",
249 [0x15] = "Windows 2003",
250};
251#endif
252
253enum {
254 SVGA_CMD_INVALID_CMD = 0,
255 SVGA_CMD_UPDATE = 1,
256 SVGA_CMD_RECT_FILL = 2,
257 SVGA_CMD_RECT_COPY = 3,
258 SVGA_CMD_DEFINE_BITMAP = 4,
259 SVGA_CMD_DEFINE_BITMAP_SCANLINE = 5,
260 SVGA_CMD_DEFINE_PIXMAP = 6,
261 SVGA_CMD_DEFINE_PIXMAP_SCANLINE = 7,
262 SVGA_CMD_RECT_BITMAP_FILL = 8,
263 SVGA_CMD_RECT_PIXMAP_FILL = 9,
264 SVGA_CMD_RECT_BITMAP_COPY = 10,
265 SVGA_CMD_RECT_PIXMAP_COPY = 11,
266 SVGA_CMD_FREE_OBJECT = 12,
267 SVGA_CMD_RECT_ROP_FILL = 13,
268 SVGA_CMD_RECT_ROP_COPY = 14,
269 SVGA_CMD_RECT_ROP_BITMAP_FILL = 15,
270 SVGA_CMD_RECT_ROP_PIXMAP_FILL = 16,
271 SVGA_CMD_RECT_ROP_BITMAP_COPY = 17,
272 SVGA_CMD_RECT_ROP_PIXMAP_COPY = 18,
273 SVGA_CMD_DEFINE_CURSOR = 19,
274 SVGA_CMD_DISPLAY_CURSOR = 20,
275 SVGA_CMD_MOVE_CURSOR = 21,
276 SVGA_CMD_DEFINE_ALPHA_CURSOR = 22,
277 SVGA_CMD_DRAW_GLYPH = 23,
278 SVGA_CMD_DRAW_GLYPH_CLIPPED = 24,
279 SVGA_CMD_UPDATE_VERBOSE = 25,
280 SVGA_CMD_SURFACE_FILL = 26,
281 SVGA_CMD_SURFACE_COPY = 27,
282 SVGA_CMD_SURFACE_ALPHA_BLEND = 28,
283 SVGA_CMD_FRONT_ROP_FILL = 29,
284 SVGA_CMD_FENCE = 30,
285};
286
287
288enum {
289 SVGA_CURSOR_ON_HIDE = 0,
290 SVGA_CURSOR_ON_SHOW = 1,
291 SVGA_CURSOR_ON_REMOVE_FROM_FB = 2,
292 SVGA_CURSOR_ON_RESTORE_TO_FB = 3,
293};
294
295static inline bool vmsvga_verify_rect(DisplaySurface *surface,
296 const char *name,
297 int x, int y, int w, int h)
298{
299 if (x < 0) {
300 trace_vmware_verify_rect_less_than_zero(name, "x", x);
301 return false;
302 }
303 if (x > SVGA_MAX_WIDTH) {
304 trace_vmware_verify_rect_greater_than_bound(name, "x", SVGA_MAX_WIDTH,
305 x);
306 return false;
307 }
308 if (w < 0) {
309 trace_vmware_verify_rect_less_than_zero(name, "w", w);
310 return false;
311 }
312 if (w > SVGA_MAX_WIDTH) {
313 trace_vmware_verify_rect_greater_than_bound(name, "w", SVGA_MAX_WIDTH,
314 w);
315 return false;
316 }
317 if (x + w > surface_width(surface)) {
318 trace_vmware_verify_rect_surface_bound_exceeded(name, "width",
319 surface_width(surface),
320 "x", x, "w", w);
321 return false;
322 }
323
324 if (y < 0) {
325 trace_vmware_verify_rect_less_than_zero(name, "y", y);
326 return false;
327 }
328 if (y > SVGA_MAX_HEIGHT) {
329 trace_vmware_verify_rect_greater_than_bound(name, "y", SVGA_MAX_HEIGHT,
330 y);
331 return false;
332 }
333 if (h < 0) {
334 trace_vmware_verify_rect_less_than_zero(name, "h", h);
335 return false;
336 }
337 if (h > SVGA_MAX_HEIGHT) {
338 trace_vmware_verify_rect_greater_than_bound(name, "y", SVGA_MAX_HEIGHT,
339 y);
340 return false;
341 }
342 if (y + h > surface_height(surface)) {
343 trace_vmware_verify_rect_surface_bound_exceeded(name, "height",
344 surface_height(surface),
345 "y", y, "h", h);
346 return false;
347 }
348
349 return true;
350}
351
352static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
353 int x, int y, int w, int h)
354{
355 DisplaySurface *surface = qemu_console_surface(s->vga.con);
356 int line;
357 int bypl;
358 int width;
359 int start;
360 uint8_t *src;
361 uint8_t *dst;
362
363 if (!vmsvga_verify_rect(surface, __func__, x, y, w, h)) {
364
365 x = 0;
366 y = 0;
367 w = surface_width(surface);
368 h = surface_height(surface);
369 }
370
371 bypl = surface_stride(surface);
372 width = surface_bytes_per_pixel(surface) * w;
373 start = surface_bytes_per_pixel(surface) * x + bypl * y;
374 src = s->vga.vram_ptr + start;
375 dst = surface_data(surface) + start;
376
377 for (line = h; line > 0; line--, src += bypl, dst += bypl) {
378 memcpy(dst, src, width);
379 }
380 dpy_gfx_update(s->vga.con, x, y, w, h);
381}
382
383static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
384 int x, int y, int w, int h)
385{
386 struct vmsvga_rect_s *rect = &s->redraw_fifo[s->redraw_fifo_last++];
387
388 s->redraw_fifo_last &= REDRAW_FIFO_LEN - 1;
389 rect->x = x;
390 rect->y = y;
391 rect->w = w;
392 rect->h = h;
393}
394
395static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s)
396{
397 struct vmsvga_rect_s *rect;
398
399 if (s->invalidated) {
400 s->redraw_fifo_first = s->redraw_fifo_last;
401 return;
402 }
403
404
405 while (s->redraw_fifo_first != s->redraw_fifo_last) {
406 rect = &s->redraw_fifo[s->redraw_fifo_first++];
407 s->redraw_fifo_first &= REDRAW_FIFO_LEN - 1;
408 vmsvga_update_rect(s, rect->x, rect->y, rect->w, rect->h);
409 }
410}
411
412#ifdef HW_RECT_ACCEL
413static inline int vmsvga_copy_rect(struct vmsvga_state_s *s,
414 int x0, int y0, int x1, int y1, int w, int h)
415{
416 DisplaySurface *surface = qemu_console_surface(s->vga.con);
417 uint8_t *vram = s->vga.vram_ptr;
418 int bypl = surface_stride(surface);
419 int bypp = surface_bytes_per_pixel(surface);
420 int width = bypp * w;
421 int line = h;
422 uint8_t *ptr[2];
423
424 if (!vmsvga_verify_rect(surface, "vmsvga_copy_rect/src", x0, y0, w, h)) {
425 return -1;
426 }
427 if (!vmsvga_verify_rect(surface, "vmsvga_copy_rect/dst", x1, y1, w, h)) {
428 return -1;
429 }
430
431 if (y1 > y0) {
432 ptr[0] = vram + bypp * x0 + bypl * (y0 + h - 1);
433 ptr[1] = vram + bypp * x1 + bypl * (y1 + h - 1);
434 for (; line > 0; line --, ptr[0] -= bypl, ptr[1] -= bypl) {
435 memmove(ptr[1], ptr[0], width);
436 }
437 } else {
438 ptr[0] = vram + bypp * x0 + bypl * y0;
439 ptr[1] = vram + bypp * x1 + bypl * y1;
440 for (; line > 0; line --, ptr[0] += bypl, ptr[1] += bypl) {
441 memmove(ptr[1], ptr[0], width);
442 }
443 }
444
445 vmsvga_update_rect_delayed(s, x1, y1, w, h);
446 return 0;
447}
448#endif
449
450#ifdef HW_FILL_ACCEL
451static inline int vmsvga_fill_rect(struct vmsvga_state_s *s,
452 uint32_t c, int x, int y, int w, int h)
453{
454 DisplaySurface *surface = qemu_console_surface(s->vga.con);
455 int bypl = surface_stride(surface);
456 int width = surface_bytes_per_pixel(surface) * w;
457 int line = h;
458 int column;
459 uint8_t *fst;
460 uint8_t *dst;
461 uint8_t *src;
462 uint8_t col[4];
463
464 if (!vmsvga_verify_rect(surface, __func__, x, y, w, h)) {
465 return -1;
466 }
467
468 col[0] = c;
469 col[1] = c >> 8;
470 col[2] = c >> 16;
471 col[3] = c >> 24;
472
473 fst = s->vga.vram_ptr + surface_bytes_per_pixel(surface) * x + bypl * y;
474
475 if (line--) {
476 dst = fst;
477 src = col;
478 for (column = width; column > 0; column--) {
479 *(dst++) = *(src++);
480 if (src - col == surface_bytes_per_pixel(surface)) {
481 src = col;
482 }
483 }
484 dst = fst;
485 for (; line > 0; line--) {
486 dst += bypl;
487 memcpy(dst, fst, width);
488 }
489 }
490
491 vmsvga_update_rect_delayed(s, x, y, w, h);
492 return 0;
493}
494#endif
495
496struct vmsvga_cursor_definition_s {
497 uint32_t width;
498 uint32_t height;
499 int id;
500 uint32_t bpp;
501 int hot_x;
502 int hot_y;
503 uint32_t mask[1024];
504 uint32_t image[4096];
505};
506
507#define SVGA_BITMAP_SIZE(w, h) ((((w) + 31) >> 5) * (h))
508#define SVGA_PIXMAP_SIZE(w, h, bpp) (((((w) * (bpp)) + 31) >> 5) * (h))
509
510#ifdef HW_MOUSE_ACCEL
511static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
512 struct vmsvga_cursor_definition_s *c)
513{
514 QEMUCursor *qc;
515 int i, pixels;
516
517 qc = cursor_alloc(c->width, c->height);
518 assert(qc != NULL);
519
520 qc->hot_x = c->hot_x;
521 qc->hot_y = c->hot_y;
522 switch (c->bpp) {
523 case 1:
524 cursor_set_mono(qc, 0xffffff, 0x000000, (void *)c->image,
525 1, (void *)c->mask);
526#ifdef DEBUG
527 cursor_print_ascii_art(qc, "vmware/mono");
528#endif
529 break;
530 case 32:
531
532 cursor_set_mono(qc, 0x000000, 0x000000, (void *)c->mask,
533 1, (void *)c->mask);
534
535 pixels = c->width * c->height;
536 for (i = 0; i < pixels; i++) {
537 qc->data[i] |= c->image[i] & 0xffffff;
538 }
539#ifdef DEBUG
540 cursor_print_ascii_art(qc, "vmware/32bit");
541#endif
542 break;
543 default:
544 fprintf(stderr, "%s: unhandled bpp %d, using fallback cursor\n",
545 __func__, c->bpp);
546 cursor_put(qc);
547 qc = cursor_builtin_left_ptr();
548 }
549
550 dpy_cursor_define(s->vga.con, qc);
551 cursor_put(qc);
552}
553#endif
554
555static inline int vmsvga_fifo_length(struct vmsvga_state_s *s)
556{
557 int num;
558
559 if (!s->config || !s->enable) {
560 return 0;
561 }
562
563 s->fifo_min = le32_to_cpu(s->fifo[SVGA_FIFO_MIN]);
564 s->fifo_max = le32_to_cpu(s->fifo[SVGA_FIFO_MAX]);
565 s->fifo_next = le32_to_cpu(s->fifo[SVGA_FIFO_NEXT]);
566 s->fifo_stop = le32_to_cpu(s->fifo[SVGA_FIFO_STOP]);
567
568
569 if ((s->fifo_min | s->fifo_max | s->fifo_next | s->fifo_stop) & 3) {
570 return 0;
571 }
572 if (s->fifo_min < sizeof(uint32_t) * 4) {
573 return 0;
574 }
575 if (s->fifo_max > SVGA_FIFO_SIZE ||
576 s->fifo_min >= SVGA_FIFO_SIZE ||
577 s->fifo_stop >= SVGA_FIFO_SIZE ||
578 s->fifo_next >= SVGA_FIFO_SIZE) {
579 return 0;
580 }
581 if (s->fifo_max < s->fifo_min + 10 * KiB) {
582 return 0;
583 }
584
585 num = s->fifo_next - s->fifo_stop;
586 if (num < 0) {
587 num += s->fifo_max - s->fifo_min;
588 }
589 return num >> 2;
590}
591
592static inline uint32_t vmsvga_fifo_read_raw(struct vmsvga_state_s *s)
593{
594 uint32_t cmd = s->fifo[s->fifo_stop >> 2];
595
596 s->fifo_stop += 4;
597 if (s->fifo_stop >= s->fifo_max) {
598 s->fifo_stop = s->fifo_min;
599 }
600 s->fifo[SVGA_FIFO_STOP] = cpu_to_le32(s->fifo_stop);
601 return cmd;
602}
603
604static inline uint32_t vmsvga_fifo_read(struct vmsvga_state_s *s)
605{
606 return le32_to_cpu(vmsvga_fifo_read_raw(s));
607}
608
609static void vmsvga_fifo_run(struct vmsvga_state_s *s)
610{
611 uint32_t cmd, colour;
612 int args, len, maxloop = 1024;
613 int x, y, dx, dy, width, height;
614 struct vmsvga_cursor_definition_s cursor;
615 uint32_t cmd_start;
616
617 len = vmsvga_fifo_length(s);
618 while (len > 0 && --maxloop > 0) {
619
620 cmd_start = s->fifo_stop;
621
622 switch (cmd = vmsvga_fifo_read(s)) {
623 case SVGA_CMD_UPDATE:
624 case SVGA_CMD_UPDATE_VERBOSE:
625 len -= 5;
626 if (len < 0) {
627 goto rewind;
628 }
629
630 x = vmsvga_fifo_read(s);
631 y = vmsvga_fifo_read(s);
632 width = vmsvga_fifo_read(s);
633 height = vmsvga_fifo_read(s);
634 vmsvga_update_rect_delayed(s, x, y, width, height);
635 break;
636
637 case SVGA_CMD_RECT_FILL:
638 len -= 6;
639 if (len < 0) {
640 goto rewind;
641 }
642
643 colour = vmsvga_fifo_read(s);
644 x = vmsvga_fifo_read(s);
645 y = vmsvga_fifo_read(s);
646 width = vmsvga_fifo_read(s);
647 height = vmsvga_fifo_read(s);
648#ifdef HW_FILL_ACCEL
649 if (vmsvga_fill_rect(s, colour, x, y, width, height) == 0) {
650 break;
651 }
652#endif
653 args = 0;
654 goto badcmd;
655
656 case SVGA_CMD_RECT_COPY:
657 len -= 7;
658 if (len < 0) {
659 goto rewind;
660 }
661
662 x = vmsvga_fifo_read(s);
663 y = vmsvga_fifo_read(s);
664 dx = vmsvga_fifo_read(s);
665 dy = vmsvga_fifo_read(s);
666 width = vmsvga_fifo_read(s);
667 height = vmsvga_fifo_read(s);
668#ifdef HW_RECT_ACCEL
669 if (vmsvga_copy_rect(s, x, y, dx, dy, width, height) == 0) {
670 break;
671 }
672#endif
673 args = 0;
674 goto badcmd;
675
676 case SVGA_CMD_DEFINE_CURSOR:
677 len -= 8;
678 if (len < 0) {
679 goto rewind;
680 }
681
682 cursor.id = vmsvga_fifo_read(s);
683 cursor.hot_x = vmsvga_fifo_read(s);
684 cursor.hot_y = vmsvga_fifo_read(s);
685 cursor.width = x = vmsvga_fifo_read(s);
686 cursor.height = y = vmsvga_fifo_read(s);
687 vmsvga_fifo_read(s);
688 cursor.bpp = vmsvga_fifo_read(s);
689
690 args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp);
691 if (cursor.width > 256
692 || cursor.height > 256
693 || cursor.bpp > 32
694 || SVGA_BITMAP_SIZE(x, y) > ARRAY_SIZE(cursor.mask)
695 || SVGA_PIXMAP_SIZE(x, y, cursor.bpp)
696 > ARRAY_SIZE(cursor.image)) {
697 goto badcmd;
698 }
699
700 len -= args;
701 if (len < 0) {
702 goto rewind;
703 }
704
705 for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args++) {
706 cursor.mask[args] = vmsvga_fifo_read_raw(s);
707 }
708 for (args = 0; args < SVGA_PIXMAP_SIZE(x, y, cursor.bpp); args++) {
709 cursor.image[args] = vmsvga_fifo_read_raw(s);
710 }
711#ifdef HW_MOUSE_ACCEL
712 vmsvga_cursor_define(s, &cursor);
713 break;
714#else
715 args = 0;
716 goto badcmd;
717#endif
718
719
720
721
722
723 case SVGA_CMD_DEFINE_ALPHA_CURSOR:
724 len -= 6;
725 if (len < 0) {
726 goto rewind;
727 }
728 vmsvga_fifo_read(s);
729 vmsvga_fifo_read(s);
730 vmsvga_fifo_read(s);
731 x = vmsvga_fifo_read(s);
732 y = vmsvga_fifo_read(s);
733 args = x * y;
734 goto badcmd;
735 case SVGA_CMD_RECT_ROP_FILL:
736 args = 6;
737 goto badcmd;
738 case SVGA_CMD_RECT_ROP_COPY:
739 args = 7;
740 goto badcmd;
741 case SVGA_CMD_DRAW_GLYPH_CLIPPED:
742 len -= 4;
743 if (len < 0) {
744 goto rewind;
745 }
746 vmsvga_fifo_read(s);
747 vmsvga_fifo_read(s);
748 args = 7 + (vmsvga_fifo_read(s) >> 2);
749 goto badcmd;
750 case SVGA_CMD_SURFACE_ALPHA_BLEND:
751 args = 12;
752 goto badcmd;
753
754
755
756
757
758 case SVGA_CMD_SURFACE_FILL:
759 case SVGA_CMD_SURFACE_COPY:
760 case SVGA_CMD_FRONT_ROP_FILL:
761 case SVGA_CMD_FENCE:
762 case SVGA_CMD_INVALID_CMD:
763 break;
764
765 default:
766 args = 0;
767 badcmd:
768 len -= args;
769 if (len < 0) {
770 goto rewind;
771 }
772 while (args--) {
773 vmsvga_fifo_read(s);
774 }
775 printf("%s: Unknown command 0x%02x in SVGA command FIFO\n",
776 __func__, cmd);
777 break;
778
779 rewind:
780 s->fifo_stop = cmd_start;
781 s->fifo[SVGA_FIFO_STOP] = cpu_to_le32(s->fifo_stop);
782 break;
783 }
784 }
785
786 s->syncing = 0;
787}
788
789static uint32_t vmsvga_index_read(void *opaque, uint32_t address)
790{
791 struct vmsvga_state_s *s = opaque;
792
793 return s->index;
794}
795
796static void vmsvga_index_write(void *opaque, uint32_t address, uint32_t index)
797{
798 struct vmsvga_state_s *s = opaque;
799
800 s->index = index;
801}
802
803static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
804{
805 uint32_t caps;
806 struct vmsvga_state_s *s = opaque;
807 DisplaySurface *surface = qemu_console_surface(s->vga.con);
808 PixelFormat pf;
809 uint32_t ret;
810
811 switch (s->index) {
812 case SVGA_REG_ID:
813 ret = s->svgaid;
814 break;
815
816 case SVGA_REG_ENABLE:
817 ret = s->enable;
818 break;
819
820 case SVGA_REG_WIDTH:
821 ret = s->new_width ? s->new_width : surface_width(surface);
822 break;
823
824 case SVGA_REG_HEIGHT:
825 ret = s->new_height ? s->new_height : surface_height(surface);
826 break;
827
828 case SVGA_REG_MAX_WIDTH:
829 ret = SVGA_MAX_WIDTH;
830 break;
831
832 case SVGA_REG_MAX_HEIGHT:
833 ret = SVGA_MAX_HEIGHT;
834 break;
835
836 case SVGA_REG_DEPTH:
837 ret = (s->new_depth == 32) ? 24 : s->new_depth;
838 break;
839
840 case SVGA_REG_BITS_PER_PIXEL:
841 case SVGA_REG_HOST_BITS_PER_PIXEL:
842 ret = s->new_depth;
843 break;
844
845 case SVGA_REG_PSEUDOCOLOR:
846 ret = 0x0;
847 break;
848
849 case SVGA_REG_RED_MASK:
850 pf = qemu_default_pixelformat(s->new_depth);
851 ret = pf.rmask;
852 break;
853
854 case SVGA_REG_GREEN_MASK:
855 pf = qemu_default_pixelformat(s->new_depth);
856 ret = pf.gmask;
857 break;
858
859 case SVGA_REG_BLUE_MASK:
860 pf = qemu_default_pixelformat(s->new_depth);
861 ret = pf.bmask;
862 break;
863
864 case SVGA_REG_BYTES_PER_LINE:
865 if (s->new_width) {
866 ret = (s->new_depth * s->new_width) / 8;
867 } else {
868 ret = surface_stride(surface);
869 }
870 break;
871
872 case SVGA_REG_FB_START: {
873 struct pci_vmsvga_state_s *pci_vmsvga
874 = container_of(s, struct pci_vmsvga_state_s, chip);
875 ret = pci_get_bar_addr(PCI_DEVICE(pci_vmsvga), 1);
876 break;
877 }
878
879 case SVGA_REG_FB_OFFSET:
880 ret = 0x0;
881 break;
882
883 case SVGA_REG_VRAM_SIZE:
884 ret = s->vga.vram_size;
885 break;
886
887 case SVGA_REG_FB_SIZE:
888 ret = s->vga.vram_size;
889 break;
890
891 case SVGA_REG_CAPABILITIES:
892 caps = SVGA_CAP_NONE;
893#ifdef HW_RECT_ACCEL
894 caps |= SVGA_CAP_RECT_COPY;
895#endif
896#ifdef HW_FILL_ACCEL
897 caps |= SVGA_CAP_RECT_FILL;
898#endif
899#ifdef HW_MOUSE_ACCEL
900 if (dpy_cursor_define_supported(s->vga.con)) {
901 caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 |
902 SVGA_CAP_CURSOR_BYPASS;
903 }
904#endif
905 ret = caps;
906 break;
907
908 case SVGA_REG_MEM_START: {
909 struct pci_vmsvga_state_s *pci_vmsvga
910 = container_of(s, struct pci_vmsvga_state_s, chip);
911 ret = pci_get_bar_addr(PCI_DEVICE(pci_vmsvga), 2);
912 break;
913 }
914
915 case SVGA_REG_MEM_SIZE:
916 ret = s->fifo_size;
917 break;
918
919 case SVGA_REG_CONFIG_DONE:
920 ret = s->config;
921 break;
922
923 case SVGA_REG_SYNC:
924 case SVGA_REG_BUSY:
925 ret = s->syncing;
926 break;
927
928 case SVGA_REG_GUEST_ID:
929 ret = s->guest;
930 break;
931
932 case SVGA_REG_CURSOR_ID:
933 ret = s->cursor.id;
934 break;
935
936 case SVGA_REG_CURSOR_X:
937 ret = s->cursor.x;
938 break;
939
940 case SVGA_REG_CURSOR_Y:
941 ret = s->cursor.y;
942 break;
943
944 case SVGA_REG_CURSOR_ON:
945 ret = s->cursor.on;
946 break;
947
948 case SVGA_REG_SCRATCH_SIZE:
949 ret = s->scratch_size;
950 break;
951
952 case SVGA_REG_MEM_REGS:
953 case SVGA_REG_NUM_DISPLAYS:
954 case SVGA_REG_PITCHLOCK:
955 case SVGA_PALETTE_BASE ... SVGA_PALETTE_END:
956 ret = 0;
957 break;
958
959 default:
960 if (s->index >= SVGA_SCRATCH_BASE &&
961 s->index < SVGA_SCRATCH_BASE + s->scratch_size) {
962 ret = s->scratch[s->index - SVGA_SCRATCH_BASE];
963 break;
964 }
965 qemu_log_mask(LOG_GUEST_ERROR,
966 "%s: Bad register %02x\n", __func__, s->index);
967 ret = 0;
968 break;
969 }
970
971 if (s->index >= SVGA_SCRATCH_BASE) {
972 trace_vmware_scratch_read(s->index, ret);
973 } else if (s->index >= SVGA_PALETTE_BASE) {
974 trace_vmware_palette_read(s->index, ret);
975 } else {
976 trace_vmware_value_read(s->index, ret);
977 }
978 return ret;
979}
980
981static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
982{
983 struct vmsvga_state_s *s = opaque;
984
985 if (s->index >= SVGA_SCRATCH_BASE) {
986 trace_vmware_scratch_write(s->index, value);
987 } else if (s->index >= SVGA_PALETTE_BASE) {
988 trace_vmware_palette_write(s->index, value);
989 } else {
990 trace_vmware_value_write(s->index, value);
991 }
992 switch (s->index) {
993 case SVGA_REG_ID:
994 if (value == SVGA_ID_2 || value == SVGA_ID_1 || value == SVGA_ID_0) {
995 s->svgaid = value;
996 }
997 break;
998
999 case SVGA_REG_ENABLE:
1000 s->enable = !!value;
1001 s->invalidated = 1;
1002 s->vga.hw_ops->invalidate(&s->vga);
1003 if (s->enable && s->config) {
1004 vga_dirty_log_stop(&s->vga);
1005 } else {
1006 vga_dirty_log_start(&s->vga);
1007 }
1008 break;
1009
1010 case SVGA_REG_WIDTH:
1011 if (value <= SVGA_MAX_WIDTH) {
1012 s->new_width = value;
1013 s->invalidated = 1;
1014 } else {
1015 qemu_log_mask(LOG_GUEST_ERROR,
1016 "%s: Bad width: %i\n", __func__, value);
1017 }
1018 break;
1019
1020 case SVGA_REG_HEIGHT:
1021 if (value <= SVGA_MAX_HEIGHT) {
1022 s->new_height = value;
1023 s->invalidated = 1;
1024 } else {
1025 qemu_log_mask(LOG_GUEST_ERROR,
1026 "%s: Bad height: %i\n", __func__, value);
1027 }
1028 break;
1029
1030 case SVGA_REG_BITS_PER_PIXEL:
1031 if (value != 32) {
1032 qemu_log_mask(LOG_GUEST_ERROR,
1033 "%s: Bad bits per pixel: %i bits\n", __func__, value);
1034 s->config = 0;
1035 s->invalidated = 1;
1036 }
1037 break;
1038
1039 case SVGA_REG_CONFIG_DONE:
1040 if (value) {
1041 s->fifo = (uint32_t *) s->fifo_ptr;
1042 vga_dirty_log_stop(&s->vga);
1043 }
1044 s->config = !!value;
1045 break;
1046
1047 case SVGA_REG_SYNC:
1048 s->syncing = 1;
1049 vmsvga_fifo_run(s);
1050 break;
1051
1052 case SVGA_REG_GUEST_ID:
1053 s->guest = value;
1054#ifdef VERBOSE
1055 if (value >= GUEST_OS_BASE && value < GUEST_OS_BASE +
1056 ARRAY_SIZE(vmsvga_guest_id)) {
1057 printf("%s: guest runs %s.\n", __func__,
1058 vmsvga_guest_id[value - GUEST_OS_BASE]);
1059 }
1060#endif
1061 break;
1062
1063 case SVGA_REG_CURSOR_ID:
1064 s->cursor.id = value;
1065 break;
1066
1067 case SVGA_REG_CURSOR_X:
1068 s->cursor.x = value;
1069 break;
1070
1071 case SVGA_REG_CURSOR_Y:
1072 s->cursor.y = value;
1073 break;
1074
1075 case SVGA_REG_CURSOR_ON:
1076 s->cursor.on |= (value == SVGA_CURSOR_ON_SHOW);
1077 s->cursor.on &= (value != SVGA_CURSOR_ON_HIDE);
1078#ifdef HW_MOUSE_ACCEL
1079 if (value <= SVGA_CURSOR_ON_SHOW) {
1080 dpy_mouse_set(s->vga.con, s->cursor.x, s->cursor.y, s->cursor.on);
1081 }
1082#endif
1083 break;
1084
1085 case SVGA_REG_DEPTH:
1086 case SVGA_REG_MEM_REGS:
1087 case SVGA_REG_NUM_DISPLAYS:
1088 case SVGA_REG_PITCHLOCK:
1089 case SVGA_PALETTE_BASE ... SVGA_PALETTE_END:
1090 break;
1091
1092 default:
1093 if (s->index >= SVGA_SCRATCH_BASE &&
1094 s->index < SVGA_SCRATCH_BASE + s->scratch_size) {
1095 s->scratch[s->index - SVGA_SCRATCH_BASE] = value;
1096 break;
1097 }
1098 qemu_log_mask(LOG_GUEST_ERROR,
1099 "%s: Bad register %02x\n", __func__, s->index);
1100 }
1101}
1102
1103static uint32_t vmsvga_bios_read(void *opaque, uint32_t address)
1104{
1105 printf("%s: what are we supposed to return?\n", __func__);
1106 return 0xcafe;
1107}
1108
1109static void vmsvga_bios_write(void *opaque, uint32_t address, uint32_t data)
1110{
1111 printf("%s: what are we supposed to do with (%08x)?\n", __func__, data);
1112}
1113
1114static inline void vmsvga_check_size(struct vmsvga_state_s *s)
1115{
1116 DisplaySurface *surface = qemu_console_surface(s->vga.con);
1117
1118 if (s->new_width != surface_width(surface) ||
1119 s->new_height != surface_height(surface) ||
1120 s->new_depth != surface_bits_per_pixel(surface)) {
1121 int stride = (s->new_depth * s->new_width) / 8;
1122 pixman_format_code_t format =
1123 qemu_default_pixman_format(s->new_depth, true);
1124 trace_vmware_setmode(s->new_width, s->new_height, s->new_depth);
1125 surface = qemu_create_displaysurface_from(s->new_width, s->new_height,
1126 format, stride,
1127 s->vga.vram_ptr);
1128 dpy_gfx_replace_surface(s->vga.con, surface);
1129 s->invalidated = 1;
1130 }
1131}
1132
1133static void vmsvga_update_display(void *opaque)
1134{
1135 struct vmsvga_state_s *s = opaque;
1136
1137 if (!s->enable || !s->config) {
1138
1139 s->vga.hw_ops->gfx_update(&s->vga);
1140 return;
1141 }
1142
1143 vmsvga_check_size(s);
1144
1145 vmsvga_fifo_run(s);
1146 vmsvga_update_rect_flush(s);
1147
1148 if (s->invalidated) {
1149 s->invalidated = 0;
1150 dpy_gfx_update_full(s->vga.con);
1151 }
1152}
1153
1154static void vmsvga_reset(DeviceState *dev)
1155{
1156 struct pci_vmsvga_state_s *pci = VMWARE_SVGA(dev);
1157 struct vmsvga_state_s *s = &pci->chip;
1158
1159 s->index = 0;
1160 s->enable = 0;
1161 s->config = 0;
1162 s->svgaid = SVGA_ID;
1163 s->cursor.on = 0;
1164 s->redraw_fifo_first = 0;
1165 s->redraw_fifo_last = 0;
1166 s->syncing = 0;
1167
1168 vga_dirty_log_start(&s->vga);
1169}
1170
1171static void vmsvga_invalidate_display(void *opaque)
1172{
1173 struct vmsvga_state_s *s = opaque;
1174 if (!s->enable) {
1175 s->vga.hw_ops->invalidate(&s->vga);
1176 return;
1177 }
1178
1179 s->invalidated = 1;
1180}
1181
1182static void vmsvga_text_update(void *opaque, console_ch_t *chardata)
1183{
1184 struct vmsvga_state_s *s = opaque;
1185
1186 if (s->vga.hw_ops->text_update) {
1187 s->vga.hw_ops->text_update(&s->vga, chardata);
1188 }
1189}
1190
1191static int vmsvga_post_load(void *opaque, int version_id)
1192{
1193 struct vmsvga_state_s *s = opaque;
1194
1195 s->invalidated = 1;
1196 if (s->config) {
1197 s->fifo = (uint32_t *) s->fifo_ptr;
1198 }
1199 return 0;
1200}
1201
1202static const VMStateDescription vmstate_vmware_vga_internal = {
1203 .name = "vmware_vga_internal",
1204 .version_id = 0,
1205 .minimum_version_id = 0,
1206 .post_load = vmsvga_post_load,
1207 .fields = (VMStateField[]) {
1208 VMSTATE_INT32_EQUAL(new_depth, struct vmsvga_state_s, NULL),
1209 VMSTATE_INT32(enable, struct vmsvga_state_s),
1210 VMSTATE_INT32(config, struct vmsvga_state_s),
1211 VMSTATE_INT32(cursor.id, struct vmsvga_state_s),
1212 VMSTATE_INT32(cursor.x, struct vmsvga_state_s),
1213 VMSTATE_INT32(cursor.y, struct vmsvga_state_s),
1214 VMSTATE_INT32(cursor.on, struct vmsvga_state_s),
1215 VMSTATE_INT32(index, struct vmsvga_state_s),
1216 VMSTATE_VARRAY_INT32(scratch, struct vmsvga_state_s,
1217 scratch_size, 0, vmstate_info_uint32, uint32_t),
1218 VMSTATE_INT32(new_width, struct vmsvga_state_s),
1219 VMSTATE_INT32(new_height, struct vmsvga_state_s),
1220 VMSTATE_UINT32(guest, struct vmsvga_state_s),
1221 VMSTATE_UINT32(svgaid, struct vmsvga_state_s),
1222 VMSTATE_INT32(syncing, struct vmsvga_state_s),
1223 VMSTATE_UNUSED(4),
1224 VMSTATE_END_OF_LIST()
1225 }
1226};
1227
1228static const VMStateDescription vmstate_vmware_vga = {
1229 .name = "vmware_vga",
1230 .version_id = 0,
1231 .minimum_version_id = 0,
1232 .fields = (VMStateField[]) {
1233 VMSTATE_PCI_DEVICE(parent_obj, struct pci_vmsvga_state_s),
1234 VMSTATE_STRUCT(chip, struct pci_vmsvga_state_s, 0,
1235 vmstate_vmware_vga_internal, struct vmsvga_state_s),
1236 VMSTATE_END_OF_LIST()
1237 }
1238};
1239
1240static const GraphicHwOps vmsvga_ops = {
1241 .invalidate = vmsvga_invalidate_display,
1242 .gfx_update = vmsvga_update_display,
1243 .text_update = vmsvga_text_update,
1244};
1245
1246static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s,
1247 MemoryRegion *address_space, MemoryRegion *io)
1248{
1249 s->scratch_size = SVGA_SCRATCH_SIZE;
1250 s->scratch = g_malloc(s->scratch_size * 4);
1251
1252 s->vga.con = graphic_console_init(dev, 0, &vmsvga_ops, s);
1253
1254 s->fifo_size = SVGA_FIFO_SIZE;
1255 memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size,
1256 &error_fatal);
1257 s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
1258
1259 vga_common_init(&s->vga, OBJECT(dev), &error_fatal);
1260 vga_init(&s->vga, OBJECT(dev), address_space, io, true);
1261 vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
1262 s->new_depth = 32;
1263}
1264
1265static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, unsigned size)
1266{
1267 struct vmsvga_state_s *s = opaque;
1268
1269 switch (addr) {
1270 case SVGA_IO_MUL * SVGA_INDEX_PORT: return vmsvga_index_read(s, addr);
1271 case SVGA_IO_MUL * SVGA_VALUE_PORT: return vmsvga_value_read(s, addr);
1272 case SVGA_IO_MUL * SVGA_BIOS_PORT: return vmsvga_bios_read(s, addr);
1273 default: return -1u;
1274 }
1275}
1276
1277static void vmsvga_io_write(void *opaque, hwaddr addr,
1278 uint64_t data, unsigned size)
1279{
1280 struct vmsvga_state_s *s = opaque;
1281
1282 switch (addr) {
1283 case SVGA_IO_MUL * SVGA_INDEX_PORT:
1284 vmsvga_index_write(s, addr, data);
1285 break;
1286 case SVGA_IO_MUL * SVGA_VALUE_PORT:
1287 vmsvga_value_write(s, addr, data);
1288 break;
1289 case SVGA_IO_MUL * SVGA_BIOS_PORT:
1290 vmsvga_bios_write(s, addr, data);
1291 break;
1292 }
1293}
1294
1295static const MemoryRegionOps vmsvga_io_ops = {
1296 .read = vmsvga_io_read,
1297 .write = vmsvga_io_write,
1298 .endianness = DEVICE_LITTLE_ENDIAN,
1299 .valid = {
1300 .min_access_size = 4,
1301 .max_access_size = 4,
1302 .unaligned = true,
1303 },
1304 .impl = {
1305 .unaligned = true,
1306 },
1307};
1308
1309static void pci_vmsvga_realize(PCIDevice *dev, Error **errp)
1310{
1311 struct pci_vmsvga_state_s *s = VMWARE_SVGA(dev);
1312
1313 dev->config[PCI_CACHE_LINE_SIZE] = 0x08;
1314 dev->config[PCI_LATENCY_TIMER] = 0x40;
1315 dev->config[PCI_INTERRUPT_LINE] = 0xff;
1316
1317 memory_region_init_io(&s->io_bar, OBJECT(dev), &vmsvga_io_ops, &s->chip,
1318 "vmsvga-io", 0x10);
1319 memory_region_set_flush_coalesced(&s->io_bar);
1320 pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
1321
1322 vmsvga_init(DEVICE(dev), &s->chip,
1323 pci_address_space(dev), pci_address_space_io(dev));
1324
1325 pci_register_bar(dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
1326 &s->chip.vga.vram);
1327 pci_register_bar(dev, 2, PCI_BASE_ADDRESS_MEM_PREFETCH,
1328 &s->chip.fifo_ram);
1329}
1330
1331static Property vga_vmware_properties[] = {
1332 DEFINE_PROP_UINT32("vgamem_mb", struct pci_vmsvga_state_s,
1333 chip.vga.vram_size_mb, 16),
1334 DEFINE_PROP_BOOL("global-vmstate", struct pci_vmsvga_state_s,
1335 chip.vga.global_vmstate, false),
1336 DEFINE_PROP_END_OF_LIST(),
1337};
1338
1339static void vmsvga_class_init(ObjectClass *klass, void *data)
1340{
1341 DeviceClass *dc = DEVICE_CLASS(klass);
1342 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1343
1344 k->realize = pci_vmsvga_realize;
1345 k->romfile = "vgabios-vmware.bin";
1346 k->vendor_id = PCI_VENDOR_ID_VMWARE;
1347 k->device_id = SVGA_PCI_DEVICE_ID;
1348 k->class_id = PCI_CLASS_DISPLAY_VGA;
1349 k->subsystem_vendor_id = PCI_VENDOR_ID_VMWARE;
1350 k->subsystem_id = SVGA_PCI_DEVICE_ID;
1351 dc->reset = vmsvga_reset;
1352 dc->vmsd = &vmstate_vmware_vga;
1353 device_class_set_props(dc, vga_vmware_properties);
1354 dc->hotpluggable = false;
1355 set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
1356}
1357
1358static const TypeInfo vmsvga_info = {
1359 .name = TYPE_VMWARE_SVGA,
1360 .parent = TYPE_PCI_DEVICE,
1361 .instance_size = sizeof(struct pci_vmsvga_state_s),
1362 .class_init = vmsvga_class_init,
1363 .interfaces = (InterfaceInfo[]) {
1364 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
1365 { },
1366 },
1367};
1368
1369static void vmsvga_register_types(void)
1370{
1371 type_register_static(&vmsvga_info);
1372}
1373
1374type_init(vmsvga_register_types)
1375