diff --git a/qemu/hw/cirrus_vga.c b/qemu/hw/cirrus_vga.c
index 9dfe76a..e31dd75 100644
--- a/qemu/hw/cirrus_vga.c
+++ b/qemu/hw/cirrus_vga.c
@@ -2586,6 +2586,9 @@ static CPUWriteMemoryFunc * const cirrus_linear_bitblt_write[3] = {
 
 static void map_linear_vram(CirrusVGAState *s)
 {
+    if (!s->vga.vga_io_memory)
+        return;
+
     if (!s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
         s->vga.map_addr = s->vga.lfb_addr;
         s->vga.map_end = s->vga.lfb_end;
@@ -2619,6 +2622,9 @@ static void map_linear_vram(CirrusVGAState *s)
 
 static void unmap_linear_vram(CirrusVGAState *s)
 {
+    if (!s->vga.vga_io_memory)
+        return;
+
     if (s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end)
         s->vga.map_addr = s->vga.map_end = 0;
 
@@ -3062,7 +3068,8 @@ static void cirrus_reset(void *opaque)
     s->cirrus_hidden_dac_data = 0;
 }
 
-static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
+static void cirrus_init_device(CirrusVGAState * s,
+                               int device_id, int vram_size, int is_pci)
 {
     int i;
     static int inited;
@@ -3094,6 +3101,21 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
             s->bustype = CIRRUS_BUSTYPE_ISA;
     }
 
+    s->real_vram_size = vram_size;
+
+    /* XXX: s->vga.vram_size must be a power of two */
+    s->cirrus_addr_mask = s->real_vram_size - 1;
+    s->linear_mmio_mask = s->real_vram_size - 256;
+
+    s->vga.get_bpp = cirrus_get_bpp;
+    s->vga.get_offsets = cirrus_get_offsets;
+    s->vga.get_resolution = cirrus_get_resolution;
+    s->vga.cursor_invalidate = cirrus_cursor_invalidate;
+    s->vga.cursor_draw_line = cirrus_cursor_draw_line;
+}
+
+static void cirrus_init_ioport(CirrusVGAState * s)
+{
     register_ioport_write(0x3c0, 16, 1, cirrus_vga_ioport_write, s);
 
     register_ioport_write(0x3b4, 2, 1, cirrus_vga_ioport_write, s);
@@ -3126,20 +3148,15 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
     /* I/O handler for memory-mapped I/O */
     s->cirrus_mmio_io_addr =
         cpu_register_io_memory(cirrus_mmio_read, cirrus_mmio_write, s);
+}
 
-    s->real_vram_size =
+static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
+{
+    int vram_size =
         (s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024;
 
-    /* XXX: s->vga.vram_size must be a power of two */
-    s->cirrus_addr_mask = s->real_vram_size - 1;
-    s->linear_mmio_mask = s->real_vram_size - 256;
-
-    s->vga.get_bpp = cirrus_get_bpp;
-    s->vga.get_offsets = cirrus_get_offsets;
-    s->vga.get_resolution = cirrus_get_resolution;
-    s->vga.cursor_invalidate = cirrus_cursor_invalidate;
-    s->vga.cursor_draw_line = cirrus_cursor_draw_line;
-
+    cirrus_init_device(s, device_id, vram_size, is_pci);
+    cirrus_init_ioport(s);
     qemu_register_reset(cirrus_reset, s);
     cirrus_reset(s);
 }
@@ -3254,6 +3271,106 @@ void pci_cirrus_vga_init(PCIBus *bus)
     pci_create_simple(bus, -1, "Cirrus VGA");
 }
 
+/***************************************
+ *
+ *  NEC PC-9821
+ *
+ ***************************************/
+
+uint32_t pc98_cirrus_vram_readb(void *opaque, target_phys_addr_t addr)
+{
+    return cirrus_vga_mem_readb(opaque, addr & 0xffff);
+}
+
+uint32_t pc98_cirrus_vram_readw(void *opaque, target_phys_addr_t addr)
+{
+    return cirrus_vga_mem_readw(opaque, addr & 0xffff);
+}
+
+uint32_t pc98_cirrus_vram_readl(void *opaque, target_phys_addr_t addr)
+{
+    return cirrus_vga_mem_readl(opaque, addr & 0xffff);
+}
+
+void pc98_cirrus_vram_writeb(void *opaque,
+                             target_phys_addr_t addr, uint32_t value)
+{
+    cirrus_vga_mem_writeb(opaque, addr & 0xffff, value);
+}
+
+void pc98_cirrus_vram_writew(void *opaque,
+                             target_phys_addr_t addr, uint32_t value)
+{
+    cirrus_vga_mem_writew(opaque, addr & 0xffff, value);
+}
+
+void pc98_cirrus_vram_writel(void *opaque,
+                             target_phys_addr_t addr, uint32_t value)
+{
+    cirrus_vga_mem_writel(opaque, addr & 0xffff, value);
+}
+
+static uint32_t pc98_cirrus_vga_ioport_read(void *opaque,
+                                            target_phys_addr_t addr)
+{
+    addr = 0x300 | ((addr >> 8) & 0xf0) | (addr & 0x0f);
+    return cirrus_vga_ioport_read(opaque, addr);
+}
+
+static void pc98_cirrus_vga_ioport_write(void *opaque,
+                                         target_phys_addr_t addr, uint32_t val)
+{
+    addr = 0x300 | ((addr >> 8) & 0xf0) | (addr & 0x0f);
+    cirrus_vga_ioport_write(opaque, addr, val);
+}
+
+void *pc98_cirrus_vga_init(DisplayState *ds)
+{
+    CirrusVGAState *s;
+
+    s = qemu_mallocz(sizeof(CirrusVGAState));
+
+    vga_common_init(&s->vga, PC98_CIRRUS_VRAM_SIZE);
+    cirrus_init_device(s, CIRRUS_ID_CLGD5430, PC98_CIRRUS_VRAM_SIZE, 0);
+
+    register_ioport_write(0xca0, 16, 1, pc98_cirrus_vga_ioport_write, s);
+    register_ioport_write(0xda4, 2, 1, pc98_cirrus_vga_ioport_write, s);
+    register_ioport_write(0xdaa, 1, 1, pc98_cirrus_vga_ioport_write, s);
+    register_ioport_read(0xca0, 16, 1, pc98_cirrus_vga_ioport_read, s);
+    register_ioport_read(0xda4, 2, 1, pc98_cirrus_vga_ioport_read, s);
+    register_ioport_read(0xdaa, 1, 1, pc98_cirrus_vga_ioport_read, s);
+
+    qemu_register_reset(cirrus_reset, s);
+    cirrus_reset(s);
+
+    s->vga.ds = ds;
+    vmstate_register(0, &vmstate_cirrus_vga, s);
+
+    return s;
+}
+
+void pc98_cirrus_vga_invalidate_display_size(void *opaque)
+{
+    CirrusVGAState *s = opaque;
+
+    s->vga.last_width = -1;
+    s->vga.last_height = -1;
+}
+
+void pc98_cirrus_vga_update_display(void *opaque)
+{
+    CirrusVGAState *s = opaque;
+
+    s->vga.update(&s->vga);
+}
+
+void pc98_cirrus_vga_invalidate_display(void *opaque)
+{
+    CirrusVGAState *s = opaque;
+
+    s->vga.invalidate(&s->vga);
+}
+
 static PCIDeviceInfo cirrus_vga_info = {
     .qdev.name    = "Cirrus VGA",
     .qdev.size    = sizeof(PCICirrusVGAState),
