]> git.proxmox.com Git - qemu.git/blobdiff - hw/vmware_vga.c
xilinx_timer: Fixed deadlock issue
[qemu.git] / hw / vmware_vga.c
index 12bff480eb796afde6b58c5a2e5a1a9c34382e67..142d9f4ea08c2850a9d55e29f875bae7d064cf48 100644 (file)
@@ -27,8 +27,7 @@
 #include "pci.h"
 #include "vmware_vga.h"
 
-#define VERBOSE
-#undef DIRECT_VRAM
+#undef VERBOSE
 #define HW_RECT_ACCEL
 #define HW_FILL_ACCEL
 #define HW_MOUSE_ACCEL
@@ -52,8 +51,6 @@ struct vmsvga_state_s {
         int on;
     } cursor;
 
-    target_phys_addr_t vram_base;
-
     int index;
     int scratch_size;
     uint32_t *scratch;
@@ -67,14 +64,13 @@ struct vmsvga_state_s {
     int syncing;
     int fb_size;
 
-    ram_addr_t fifo_offset;
+    MemoryRegion fifo_ram;
     uint8_t *fifo_ptr;
     unsigned int fifo_size;
-    target_phys_addr_t fifo_base;
 
     union {
         uint32_t *fifo;
-        struct __attribute__((__packed__)) {
+        struct QEMU_PACKED {
             uint32_t min;
             uint32_t max;
             uint32_t next_cmd;
@@ -94,6 +90,7 @@ struct vmsvga_state_s {
 struct pci_vmsvga_state_s {
     PCIDevice card;
     struct vmsvga_state_s chip;
+    MemoryRegion io_bar;
 };
 
 #define SVGA_MAGIC             0x900000UL
@@ -114,14 +111,12 @@ struct pci_vmsvga_state_s {
 # define SVGA_IO_BASE          SVGA_LEGACY_BASE_PORT
 # define SVGA_IO_MUL           1
 # define SVGA_FIFO_SIZE                0x10000
-# define SVGA_MEM_BASE         0xe0000000
 # 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_MEM_BASE         0xe0000000
 # define SVGA_PCI_DEVICE_ID    PCI_DEVICE_ID_VMWARE_SVGA
 #endif
 
@@ -296,7 +291,6 @@ enum {
 static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
                 int x, int y, int w, int h)
 {
-#ifndef DIRECT_VRAM
     int line;
     int bypl;
     int width;
@@ -327,23 +321,17 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
 
     for (; line > 0; line --, src += bypl, dst += bypl)
         memcpy(dst, src, width);
-#endif
 
     dpy_update(s->vga.ds, x, y, w, h);
 }
 
 static inline void vmsvga_update_screen(struct vmsvga_state_s *s)
 {
-#ifndef DIRECT_VRAM
-    memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr, s->bypp * s->width * s->height);
-#endif
-
+    memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr,
+           s->bypp * s->width * s->height);
     dpy_update(s->vga.ds, 0, 0, s->width, s->height);
 }
 
-#ifdef DIRECT_VRAM
-# define vmsvga_update_rect_delayed    vmsvga_update_rect
-#else
 static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
                 int x, int y, int w, int h)
 {
@@ -354,7 +342,6 @@ static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
     rect->w = w;
     rect->h = h;
 }
-#endif
 
 static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s)
 {
@@ -376,32 +363,23 @@ static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s)
 static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
                 int x0, int y0, int x1, int y1, int w, int h)
 {
-# ifdef DIRECT_VRAM
-    uint8_t *vram = ds_get_data(s->ds);
-# else
     uint8_t *vram = s->vga.vram_ptr;
-# endif
     int bypl = s->bypp * s->width;
     int width = s->bypp * w;
     int line = h;
     uint8_t *ptr[2];
 
-# ifdef DIRECT_VRAM
-    if (s->ds->dpy_copy)
-        qemu_console_copy(s->ds, x0, y0, x1, y1, w, h);
-    else
-# endif
-    {
-        if (y1 > y0) {
-            ptr[0] = vram + s->bypp * x0 + bypl * (y0 + h - 1);
-            ptr[1] = vram + s->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 + s->bypp * x0 + bypl * y0;
-            ptr[1] = vram + s->bypp * x1 + bypl * y1;
-            for (; line > 0; line --, ptr[0] += bypl, ptr[1] += bypl)
-                memmove(ptr[1], ptr[0], width);
+    if (y1 > y0) {
+        ptr[0] = vram + s->bypp * x0 + bypl * (y0 + h - 1);
+        ptr[1] = vram + s->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 + s->bypp * x0 + bypl * y0;
+        ptr[1] = vram + s->bypp * x1 + bypl * y1;
+        for (; line > 0; line --, ptr[0] += bypl, ptr[1] += bypl) {
+            memmove(ptr[1], ptr[0], width);
         }
     }
 
@@ -413,11 +391,7 @@ static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
 static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
                 uint32_t c, int x, int y, int w, int h)
 {
-# ifdef DIRECT_VRAM
-    uint8_t *vram = ds_get_data(s->ds);
-# else
     uint8_t *vram = s->vga.vram_ptr;
-# endif
     int bypp = s->bypp;
     int bypl = bypp * s->width;
     int width = bypp * w;
@@ -428,31 +402,25 @@ static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
     uint8_t *src;
     uint8_t col[4];
 
-# ifdef DIRECT_VRAM
-    if (s->ds->dpy_fill)
-        s->ds->dpy_fill(s->ds, x, y, w, h, c);
-    else
-# endif
-    {
-        col[0] = c;
-        col[1] = c >> 8;
-        col[2] = c >> 16;
-        col[3] = c >> 24;
-
-        if (line --) {
-            dst = fst;
-            src = col;
-            for (column = width; column > 0; column --) {
-                *(dst ++) = *(src ++);
-                if (src - col == bypp)
-                    src = col;
-            }
-            dst = fst;
-            for (; line > 0; line --) {
-                dst += bypl;
-                memcpy(dst, fst, width);
+    col[0] = c;
+    col[1] = c >> 8;
+    col[2] = c >> 16;
+    col[3] = c >> 24;
+
+    if (line--) {
+        dst = fst;
+        src = col;
+        for (column = width; column > 0; column--) {
+            *(dst++) = *(src++);
+            if (src - col == bypp) {
+                src = col;
             }
         }
+        dst = fst;
+        for (; line > 0; line--) {
+            dst += bypl;
+            memcpy(dst, fst, width);
+        }
     }
 
     vmsvga_update_rect_delayed(s, x, y, w, h);
@@ -519,11 +487,15 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
 
 #define CMD(f) le32_to_cpu(s->cmd->f)
 
-static inline int vmsvga_fifo_empty(struct vmsvga_state_s *s)
+static inline int vmsvga_fifo_length(struct vmsvga_state_s *s)
 {
+    int num;
     if (!s->config || !s->enable)
-        return 1;
-    return (s->cmd->next_cmd == s->cmd->stop);
+        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)
@@ -543,13 +515,23 @@ static inline uint32_t vmsvga_fifo_read(struct vmsvga_state_s *s)
 static void vmsvga_fifo_run(struct vmsvga_state_s *s)
 {
     uint32_t cmd, colour;
-    int args = 0;
+    int args, len;
     int x, y, dx, dy, width, height;
     struct vmsvga_cursor_definition_s cursor;
-    while (!vmsvga_fifo_empty(s))
+    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);
@@ -558,6 +540,10 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
             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);
@@ -567,10 +553,15 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
             vmsvga_fill_rect(s, colour, x, y, width, height);
             break;
 #else
+            args = 0;
             goto badcmd;
 #endif
 
         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);
@@ -581,10 +572,15 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
             vmsvga_copy_rect(s, x, y, dx, dy, width, height);
             break;
 #else
+            args = 0;
             goto badcmd;
 #endif
 
         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);
@@ -593,11 +589,14 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
             vmsvga_fifo_read(s);
             cursor.bpp = vmsvga_fifo_read(s);
 
-           if (SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask ||
-               SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) {
-                   args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp);
-                   goto badcmd;
-           }
+            args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp);
+            if (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);
@@ -616,6 +615,10 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
          * 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);
@@ -630,6 +633,10 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
             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);
@@ -650,13 +657,22 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
             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",
                             __FUNCTION__, cmd);
             break;
+
+        rewind:
+            s->cmd->stop = cmd_start;
+            break;
         }
+    }
 
     s->syncing = 0;
 }
@@ -715,8 +731,11 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
     case SVGA_REG_BYTES_PER_LINE:
         return ((s->depth + 7) >> 3) * s->new_width;
 
-    case SVGA_REG_FB_START:
-        return s->vram_base;
+    case SVGA_REG_FB_START: {
+        struct pci_vmsvga_state_s *pci_vmsvga
+            = container_of(s, struct pci_vmsvga_state_s, chip);
+        return pci_get_bar_addr(&pci_vmsvga->card, 1);
+    }
 
     case SVGA_REG_FB_OFFSET:
         return 0x0;
@@ -742,8 +761,11 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
 #endif
         return caps;
 
-    case SVGA_REG_MEM_START:
-        return s->fifo_base;
+    case SVGA_REG_MEM_START: {
+        struct pci_vmsvga_state_s *pci_vmsvga
+            = container_of(s, struct pci_vmsvga_state_s, chip);
+        return pci_get_bar_addr(&pci_vmsvga->card, 2);
+    }
 
     case SVGA_REG_MEM_SIZE:
         return s->fifo_size;
@@ -809,11 +831,11 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
         s->invalidated = 1;
         s->vga.invalidate(&s->vga);
         if (s->enable) {
-         s->fb_size = ((s->depth + 7) >> 3) * s->new_width * s->new_height;
-         vga_dirty_log_stop(&s->vga);
-       } else {
-         vga_dirty_log_start(&s->vga);
-       }
+            s->fb_size = ((s->depth + 7) >> 3) * s->new_width * s->new_height;
+            vga_dirty_log_stop(&s->vga);
+        } else {
+            vga_dirty_log_start(&s->vga);
+        }
         break;
 
     case SVGA_REG_WIDTH:
@@ -948,46 +970,21 @@ static void vmsvga_update_display(void *opaque)
     }
 }
 
-static void vmsvga_reset(struct vmsvga_state_s *s)
+static void vmsvga_reset(DeviceState *dev)
 {
+    struct pci_vmsvga_state_s *pci =
+        DO_UPCAST(struct pci_vmsvga_state_s, card.qdev, dev);
+    struct vmsvga_state_s *s = &pci->chip;
+
     s->index = 0;
     s->enable = 0;
     s->config = 0;
     s->width = -1;
     s->height = -1;
     s->svgaid = SVGA_ID;
-    s->depth = ds_get_bits_per_pixel(s->vga.ds);
-    s->bypp = ds_get_bytes_per_pixel(s->vga.ds);
     s->cursor.on = 0;
     s->redraw_fifo_first = 0;
     s->redraw_fifo_last = 0;
-    switch (s->depth) {
-    case 8:
-        s->wred   = 0x00000007;
-        s->wgreen = 0x00000038;
-        s->wblue  = 0x000000c0;
-        break;
-    case 15:
-        s->wred   = 0x0000001f;
-        s->wgreen = 0x000003e0;
-        s->wblue  = 0x00007c00;
-        break;
-    case 16:
-        s->wred   = 0x0000001f;
-        s->wgreen = 0x000007e0;
-        s->wblue  = 0x0000f800;
-        break;
-    case 24:
-        s->wred   = 0x00ff0000;
-        s->wgreen = 0x0000ff00;
-        s->wblue  = 0x000000ff;
-        break;
-    case 32:
-        s->wred   = 0x00ff0000;
-        s->wgreen = 0x0000ff00;
-        s->wblue  = 0x000000ff;
-        break;
-    }
     s->syncing = 0;
 
     vga_dirty_log_start(&s->vga);
@@ -1006,11 +1003,11 @@ static void vmsvga_invalidate_display(void *opaque)
 
 /* save the vga display in a PPM image even if no display is
    available */
-static void vmsvga_screen_dump(void *opaque, const char *filename)
+static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch)
 {
     struct vmsvga_state_s *s = opaque;
     if (!s->enable) {
-        s->vga.screen_dump(&s->vga, filename);
+        s->vga.screen_dump(&s->vga, filename, cswitch);
         return;
     }
 
@@ -1018,7 +1015,7 @@ static void vmsvga_screen_dump(void *opaque, const char *filename)
         DisplaySurface *ds = qemu_create_displaysurface_from(s->width,
                 s->height, 32, ds_get_linesize(s->vga.ds), s->vga.vram_ptr);
         ppm_save(filename, ds);
-        qemu_free(ds);
+        g_free(ds);
     }
 }
 
@@ -1030,77 +1027,6 @@ static void vmsvga_text_update(void *opaque, console_ch_t *chardata)
         s->vga.text_update(&s->vga, chardata);
 }
 
-#ifdef DIRECT_VRAM
-static uint32_t vmsvga_vram_readb(void *opaque, target_phys_addr_t addr)
-{
-    struct vmsvga_state_s *s = opaque;
-    if (addr < s->fb_size)
-        return *(uint8_t *) (ds_get_data(s->ds) + addr);
-    else
-        return *(uint8_t *) (s->vram_ptr + addr);
-}
-
-static uint32_t vmsvga_vram_readw(void *opaque, target_phys_addr_t addr)
-{
-    struct vmsvga_state_s *s = opaque;
-    if (addr < s->fb_size)
-        return *(uint16_t *) (ds_get_data(s->ds) + addr);
-    else
-        return *(uint16_t *) (s->vram_ptr + addr);
-}
-
-static uint32_t vmsvga_vram_readl(void *opaque, target_phys_addr_t addr)
-{
-    struct vmsvga_state_s *s = opaque;
-    if (addr < s->fb_size)
-        return *(uint32_t *) (ds_get_data(s->ds) + addr);
-    else
-        return *(uint32_t *) (s->vram_ptr + addr);
-}
-
-static void vmsvga_vram_writeb(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct vmsvga_state_s *s = opaque;
-    if (addr < s->fb_size)
-        *(uint8_t *) (ds_get_data(s->ds) + addr) = value;
-    else
-        *(uint8_t *) (s->vram_ptr + addr) = value;
-}
-
-static void vmsvga_vram_writew(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct vmsvga_state_s *s = opaque;
-    if (addr < s->fb_size)
-        *(uint16_t *) (ds_get_data(s->ds) + addr) = value;
-    else
-        *(uint16_t *) (s->vram_ptr + addr) = value;
-}
-
-static void vmsvga_vram_writel(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct vmsvga_state_s *s = opaque;
-    if (addr < s->fb_size)
-        *(uint32_t *) (ds_get_data(s->ds) + addr) = value;
-    else
-        *(uint32_t *) (s->vram_ptr + addr) = value;
-}
-
-static CPUReadMemoryFunc * const vmsvga_vram_read[] = {
-    vmsvga_vram_readb,
-    vmsvga_vram_readw,
-    vmsvga_vram_readl,
-};
-
-static CPUWriteMemoryFunc * const vmsvga_vram_write[] = {
-    vmsvga_vram_writeb,
-    vmsvga_vram_writew,
-    vmsvga_vram_writel,
-};
-#endif
-
 static int vmsvga_post_load(void *opaque, int version_id)
 {
     struct vmsvga_state_s *s = opaque;
@@ -1152,10 +1078,11 @@ static const VMStateDescription vmstate_vmware_vga = {
     }
 };
 
-static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
+static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size,
+                        MemoryRegion *address_space, MemoryRegion *io)
 {
     s->scratch_size = SVGA_SCRATCH_SIZE;
-    s->scratch = qemu_malloc(s->scratch_size * 4);
+    s->scratch = g_malloc(s->scratch_size * 4);
 
     s->vga.ds = graphic_console_init(vmsvga_update_display,
                                      vmsvga_invalidate_display,
@@ -1164,118 +1091,141 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
 
 
     s->fifo_size = SVGA_FIFO_SIZE;
-    s->fifo_offset = qemu_ram_alloc(NULL, "vmsvga.fifo", s->fifo_size);
-    s->fifo_ptr = qemu_get_ram_ptr(s->fifo_offset);
+    memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size);
+    vmstate_register_ram_global(&s->fifo_ram);
+    s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
 
     vga_common_init(&s->vga, vga_ram_size);
-    vga_init(&s->vga);
+    vga_init(&s->vga, address_space, io, true);
     vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
 
-    vga_init_vbe(&s->vga);
-
-    rom_add_vga(VGABIOS_FILENAME);
-
-    vmsvga_reset(s);
+    s->depth = ds_get_bits_per_pixel(s->vga.ds);
+    s->bypp = ds_get_bytes_per_pixel(s->vga.ds);
+    switch (s->depth) {
+    case 8:
+        s->wred   = 0x00000007;
+        s->wgreen = 0x00000038;
+        s->wblue  = 0x000000c0;
+        break;
+    case 15:
+        s->wred   = 0x0000001f;
+        s->wgreen = 0x000003e0;
+        s->wblue  = 0x00007c00;
+        break;
+    case 16:
+        s->wred   = 0x0000001f;
+        s->wgreen = 0x000007e0;
+        s->wblue  = 0x0000f800;
+        break;
+    case 24:
+        s->wred   = 0x00ff0000;
+        s->wgreen = 0x0000ff00;
+        s->wblue  = 0x000000ff;
+        break;
+    case 32:
+        s->wred   = 0x00ff0000;
+        s->wgreen = 0x0000ff00;
+        s->wblue  = 0x000000ff;
+        break;
+    }
 }
 
-static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
-                pcibus_t addr, pcibus_t size, int type)
+static uint64_t vmsvga_io_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
-    struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
-    struct vmsvga_state_s *s = &d->chip;
-
-    register_ioport_read(addr + SVGA_IO_MUL * SVGA_INDEX_PORT,
-                    1, 4, vmsvga_index_read, s);
-    register_ioport_write(addr + SVGA_IO_MUL * SVGA_INDEX_PORT,
-                    1, 4, vmsvga_index_write, s);
-    register_ioport_read(addr + SVGA_IO_MUL * SVGA_VALUE_PORT,
-                    1, 4, vmsvga_value_read, s);
-    register_ioport_write(addr + SVGA_IO_MUL * SVGA_VALUE_PORT,
-                    1, 4, vmsvga_value_write, s);
-    register_ioport_read(addr + SVGA_IO_MUL * SVGA_BIOS_PORT,
-                    1, 4, vmsvga_bios_read, s);
-    register_ioport_write(addr + SVGA_IO_MUL * SVGA_BIOS_PORT,
-                    1, 4, vmsvga_bios_write, s);
+    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 pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
-                pcibus_t addr, pcibus_t size, int type)
+static void vmsvga_io_write(void *opaque, target_phys_addr_t addr,
+                            uint64_t data, unsigned size)
 {
-    struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
-    struct vmsvga_state_s *s = &d->chip;
-    ram_addr_t iomemtype;
-
-    s->vram_base = addr;
-#ifdef DIRECT_VRAM
-    iomemtype = cpu_register_io_memory(vmsvga_vram_read,
-                    vmsvga_vram_write, s);
-#else
-    iomemtype = s->vga.vram_offset | IO_MEM_RAM;
-#endif
-    cpu_register_physical_memory(s->vram_base, s->vga.vram_size,
-                    iomemtype);
+    struct vmsvga_state_s *s = opaque;
 
-    s->vga.map_addr = addr;
-    s->vga.map_end = addr + s->vga.vram_size;
-    vga_dirty_log_restart(&s->vga);
+    switch (addr) {
+    case SVGA_IO_MUL * SVGA_INDEX_PORT:
+        return vmsvga_index_write(s, addr, data);
+    case SVGA_IO_MUL * SVGA_VALUE_PORT:
+        return vmsvga_value_write(s, addr, data);
+    case SVGA_IO_MUL * SVGA_BIOS_PORT:
+        return vmsvga_bios_write(s, addr, data);
+    }
 }
 
-static void pci_vmsvga_map_fifo(PCIDevice *pci_dev, int region_num,
-                pcibus_t addr, pcibus_t size, int type)
-{
-    struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
-    struct vmsvga_state_s *s = &d->chip;
-    ram_addr_t iomemtype;
-
-    s->fifo_base = addr;
-    iomemtype = s->fifo_offset | IO_MEM_RAM;
-    cpu_register_physical_memory(s->fifo_base, s->fifo_size,
-                    iomemtype);
-}
+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,
+    },
+};
 
 static int pci_vmsvga_initfn(PCIDevice *dev)
 {
     struct pci_vmsvga_state_s *s =
         DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
+    MemoryRegion *iomem;
+
+    iomem = &s->chip.vga.vram;
 
-    pci_config_set_vendor_id(s->card.config, PCI_VENDOR_ID_VMWARE);
-    pci_config_set_device_id(s->card.config, SVGA_PCI_DEVICE_ID);
-    pci_config_set_class(s->card.config, PCI_CLASS_DISPLAY_VGA);
     s->card.config[PCI_CACHE_LINE_SIZE]        = 0x08;         /* Cache line size */
     s->card.config[PCI_LATENCY_TIMER] = 0x40;          /* Latency timer */
-    s->card.config[PCI_SUBSYSTEM_VENDOR_ID] = PCI_VENDOR_ID_VMWARE & 0xff;
-    s->card.config[PCI_SUBSYSTEM_VENDOR_ID + 1]        = PCI_VENDOR_ID_VMWARE >> 8;
-    s->card.config[PCI_SUBSYSTEM_ID] = SVGA_PCI_DEVICE_ID & 0xff;
-    s->card.config[PCI_SUBSYSTEM_ID + 1] = SVGA_PCI_DEVICE_ID >> 8;
     s->card.config[PCI_INTERRUPT_LINE] = 0xff;         /* End */
 
-    pci_register_bar(&s->card, 0, 0x10,
-                    PCI_BASE_ADDRESS_SPACE_IO, pci_vmsvga_map_ioport);
-    pci_register_bar(&s->card, 1, VGA_RAM_SIZE,
-                    PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_mem);
+    memory_region_init_io(&s->io_bar, &vmsvga_io_ops, &s->chip,
+                          "vmsvga-io", 0x10);
+    pci_register_bar(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
+
+    vmsvga_init(&s->chip, VGA_RAM_SIZE, pci_address_space(dev),
+                pci_address_space_io(dev));
 
-    pci_register_bar(&s->card, 2, SVGA_FIFO_SIZE,
-                    PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_fifo);
+    pci_register_bar(&s->card, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, iomem);
+    pci_register_bar(&s->card, 2, PCI_BASE_ADDRESS_MEM_PREFETCH,
+                     &s->chip.fifo_ram);
 
-    vmsvga_init(&s->chip, VGA_RAM_SIZE);
+    if (!dev->rom_bar) {
+        /* compatibility with pc-0.13 and older */
+        vga_init_vbe(&s->chip.vga, pci_address_space(dev));
+    }
 
     return 0;
 }
 
-void pci_vmsvga_init(PCIBus *bus)
+static void vmsvga_class_init(ObjectClass *klass, void *data)
 {
-    pci_create_simple(bus, -1, "vmware-svga");
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug = 1;
+    k->init = pci_vmsvga_initfn;
+    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;
 }
 
-static PCIDeviceInfo vmsvga_info = {
-    .qdev.name    = "vmware-svga",
-    .qdev.size    = sizeof(struct pci_vmsvga_state_s),
-    .qdev.vmsd    = &vmstate_vmware_vga,
-    .init         = pci_vmsvga_initfn,
+static TypeInfo vmsvga_info = {
+    .name          = "vmware-svga",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(struct pci_vmsvga_state_s),
+    .class_init    = vmsvga_class_init,
 };
 
-static void vmsvga_register(void)
+static void vmsvga_register_types(void)
 {
-    pci_qdev_register(&vmsvga_info);
+    type_register_static(&vmsvga_info);
 }
-device_init(vmsvga_register);
+
+type_init(vmsvga_register_types)