spelling fixes
[qemu] / hw / vga.c
index 3a634a4..2a0a9c3 100644 (file)
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -22,6 +22,7 @@
  * THE SOFTWARE.
  */
 #include "vl.h"
+#include "vga_int.h"
 
 //#define DEBUG_VGA
 //#define DEBUG_VGA_MEM
 //#define DEBUG_S3
 //#define DEBUG_BOCHS_VBE
 
-#define CONFIG_S3VGA
-
-#define MSR_COLOR_EMULATION 0x01
-#define MSR_PAGE_SELECT     0x20
-
-#define ST01_V_RETRACE      0x08
-#define ST01_DISP_ENABLE    0x01
-
-/* bochs VBE support */
-#define CONFIG_BOCHS_VBE
-
-#define VBE_DISPI_MAX_XRES              1024
-#define VBE_DISPI_MAX_YRES              768
-
-#define VBE_DISPI_INDEX_ID              0x0
-#define VBE_DISPI_INDEX_XRES            0x1
-#define VBE_DISPI_INDEX_YRES            0x2
-#define VBE_DISPI_INDEX_BPP             0x3
-#define VBE_DISPI_INDEX_ENABLE          0x4
-#define VBE_DISPI_INDEX_BANK            0x5
-#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
-#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
-#define VBE_DISPI_INDEX_X_OFFSET        0x8
-#define VBE_DISPI_INDEX_Y_OFFSET        0x9
-#define VBE_DISPI_INDEX_NB              0xa
-      
-#define VBE_DISPI_ID0                   0xB0C0
-#define VBE_DISPI_ID1                   0xB0C1
-#define VBE_DISPI_ID2                   0xB0C2
-  
-#define VBE_DISPI_DISABLED              0x00
-#define VBE_DISPI_ENABLED               0x01
-#define VBE_DISPI_LFB_ENABLED           0x40
-#define VBE_DISPI_NOCLEARMEM            0x80
-  
-#define VBE_DISPI_LFB_PHYSICAL_ADDRESS  0xE0000000
-
-typedef struct VGAState {
-    uint8_t *vram_ptr;
-    unsigned long vram_offset;
-    unsigned int vram_size;
-    uint32_t latch;
-    uint8_t sr_index;
-    uint8_t sr[8];
-    uint8_t gr_index;
-    uint8_t gr[16];
-    uint8_t ar_index;
-    uint8_t ar[21];
-    int ar_flip_flop;
-    uint8_t cr_index;
-    uint8_t cr[256]; /* CRT registers */
-    uint8_t msr; /* Misc Output Register */
-    uint8_t fcr; /* Feature Control Register */
-    uint8_t st00; /* status 0 */
-    uint8_t st01; /* status 1 */
-    uint8_t dac_state;
-    uint8_t dac_sub_index;
-    uint8_t dac_read_index;
-    uint8_t dac_write_index;
-    uint8_t dac_cache[3]; /* used when writing */
-    uint8_t palette[768];
-    uint32_t bank_offset;
-#ifdef CONFIG_BOCHS_VBE
-    uint16_t vbe_index;
-    uint16_t vbe_regs[VBE_DISPI_INDEX_NB];
-    uint32_t vbe_start_addr;
-    uint32_t vbe_line_offset;
-    uint32_t vbe_bank_mask;
-#endif
-    /* display refresh support */
-    DisplayState *ds;
-    uint32_t font_offsets[2];
-    int graphic_mode;
-    uint8_t shift_control;
-    uint8_t double_scan;
-    uint32_t line_offset;
-    uint32_t line_compare;
-    uint32_t start_addr;
-    uint8_t last_cw, last_ch;
-    uint32_t last_width, last_height; /* in chars or pixels */
-    uint32_t last_scr_width, last_scr_height; /* in pixels */
-    uint8_t cursor_start, cursor_end;
-    uint32_t cursor_offset;
-    unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
-    /* tell for each page if it has been updated since the last time */
-    uint32_t last_palette[256];
-#define CH_ATTR_SIZE (160 * 100)
-    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
-} VGAState;
+/* S3 VGA is deprecated - another graphic card will be emulated */
+//#define CONFIG_S3VGA
 
 /* force some bits to zero */
-static const uint8_t sr_mask[8] = {
+const uint8_t sr_mask[8] = {
     (uint8_t)~0xfc,
     (uint8_t)~0xc2,
     (uint8_t)~0xf0,
@@ -132,7 +46,7 @@ static const uint8_t sr_mask[8] = {
     (uint8_t)~0x00,
 };
 
-static const uint8_t gr_mask[16] = {
+const uint8_t gr_mask[16] = {
     (uint8_t)~0xf0, /* 0x00 */
     (uint8_t)~0xf0, /* 0x01 */
     (uint8_t)~0xf0, /* 0x02 */
@@ -233,7 +147,7 @@ static uint32_t expand4[256];
 static uint16_t expand2[256];
 static uint8_t expand4to8[16];
 
-VGAState vga_state;
+VGAState *vga_state;
 int vga_io_memory;
 
 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
@@ -276,6 +190,9 @@ static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
         case 0x3c7:
             val = s->dac_state;
             break;
+       case 0x3c8:
+           val = s->dac_write_index;
+           break;
         case 0x3c9:
             val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
             if (++s->dac_sub_index == 3) {
@@ -335,7 +252,7 @@ static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
 static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
     VGAState *s = opaque;
-    int index, v;
+    int index;
 
     /* check port range access depending on color/monochrome mode */
     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
@@ -453,15 +370,21 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
             break;
         case 0x31:
             /* update start address */
-            s->cr[s->cr_index] = val;
-            v = (val >> 4) & 3;
-            s->cr[0x69] = (s->cr[69] & ~0x03) | v;
+            {
+                int v;
+                s->cr[s->cr_index] = val;
+                v = (val >> 4) & 3;
+                s->cr[0x69] = (s->cr[69] & ~0x03) | v;
+            }
             break;
         case 0x51:
             /* update start address */
-            s->cr[s->cr_index] = val;
-            v = val & 3;
-            s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
+            {
+                int v;
+                s->cr[s->cr_index] = val;
+                v = val & 3;
+                s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
+            }
             break;
 #endif
         default:
@@ -482,34 +405,40 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 }
 
 #ifdef CONFIG_BOCHS_VBE
-static uint32_t vbe_ioport_read(void *opaque, uint32_t addr)
+static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
 {
     VGAState *s = opaque;
     uint32_t val;
+    val = s->vbe_index;
+    return val;
+}
 
-    addr &= 1;
-    if (addr == 0) {
-        val = s->vbe_index;
-    } else {
-        if (s->vbe_index <= VBE_DISPI_INDEX_NB)
-            val = s->vbe_regs[s->vbe_index];
-        else
-            val = 0;
+static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
+{
+    VGAState *s = opaque;
+    uint32_t val;
+
+    if (s->vbe_index <= VBE_DISPI_INDEX_NB)
+        val = s->vbe_regs[s->vbe_index];
+    else
+        val = 0;
 #ifdef DEBUG_BOCHS_VBE
-        printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
+    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
 #endif
-    }
     return val;
 }
 
-static void vbe_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
 {
     VGAState *s = opaque;
+    s->vbe_index = val;
+}
 
-    addr &= 1;
-    if (addr == 0) {
-        s->vbe_index = val;
-    } else if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
+static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
+{
+    VGAState *s = opaque;
+
+    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
 #ifdef DEBUG_BOCHS_VBE
         printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
 #endif
@@ -542,7 +471,7 @@ static void vbe_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         case VBE_DISPI_INDEX_BANK:
             val &= s->vbe_bank_mask;
             s->vbe_regs[s->vbe_index] = val;
-            s->bank_offset = (val << 16) - 0xa0000;
+            s->bank_offset = (val << 16);
             break;
         case VBE_DISPI_INDEX_ENABLE:
             if (val & VBE_DISPI_ENABLED) {
@@ -590,14 +519,16 @@ static void vbe_ioport_write(void *opaque, uint32_t addr, uint32_t val)
                     s->sr[0x01] &= ~8; /* no double line */
                 } else {
                     shift_control = 2;
+                    s->sr[4] |= 0x08; /* set chain 4 mode */
+                    s->sr[2] |= 0x0f; /* activate all planes */
                 }
                 s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
                 s->cr[0x09] &= ~0x9f; /* no double scan */
-                s->vbe_regs[s->vbe_index] = val;
             } else {
                 /* XXX: the bios should do that */
-                s->bank_offset = -0xa0000;
+                s->bank_offset = 0;
             }
+            s->vbe_regs[s->vbe_index] = val;
             break;
         case VBE_DISPI_INDEX_VIRT_WIDTH:
             {
@@ -641,31 +572,31 @@ static void vbe_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 #endif
 
 /* called for accesses between 0xa0000 and 0xc0000 */
-static uint32_t vga_mem_readb(uint32_t addr)
+uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
 {
-    VGAState *s = &vga_state;
+    VGAState *s = opaque;
     int memory_map_mode, plane;
     uint32_t ret;
     
     /* convert to VGA memory offset */
     memory_map_mode = (s->gr[6] >> 2) & 3;
+    addr &= 0x1ffff;
     switch(memory_map_mode) {
     case 0:
-        addr -= 0xa0000;
         break;
     case 1:
-        if (addr >= 0xb0000)
+        if (addr >= 0x10000)
             return 0xff;
         addr += s->bank_offset;
         break;
     case 2:
-        addr -= 0xb0000;
+        addr -= 0x10000;
         if (addr >= 0x8000)
             return 0xff;
         break;
     default:
     case 3:
-        addr -= 0xb8000;
+        addr -= 0x18000;
         if (addr >= 0x8000)
             return 0xff;
         break;
@@ -697,28 +628,40 @@ static uint32_t vga_mem_readb(uint32_t addr)
     return ret;
 }
 
-static uint32_t vga_mem_readw(uint32_t addr)
+static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
 {
     uint32_t v;
-    v = vga_mem_readb(addr);
-    v |= vga_mem_readb(addr + 1) << 8;
+#ifdef TARGET_WORDS_BIGENDIAN
+    v = vga_mem_readb(opaque, addr) << 8;
+    v |= vga_mem_readb(opaque, addr + 1);
+#else
+    v = vga_mem_readb(opaque, addr);
+    v |= vga_mem_readb(opaque, addr + 1) << 8;
+#endif
     return v;
 }
 
-static uint32_t vga_mem_readl(uint32_t addr)
+static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
 {
     uint32_t v;
-    v = vga_mem_readb(addr);
-    v |= vga_mem_readb(addr + 1) << 8;
-    v |= vga_mem_readb(addr + 2) << 16;
-    v |= vga_mem_readb(addr + 3) << 24;
+#ifdef TARGET_WORDS_BIGENDIAN
+    v = vga_mem_readb(opaque, addr) << 24;
+    v |= vga_mem_readb(opaque, addr + 1) << 16;
+    v |= vga_mem_readb(opaque, addr + 2) << 8;
+    v |= vga_mem_readb(opaque, addr + 3);
+#else
+    v = vga_mem_readb(opaque, addr);
+    v |= vga_mem_readb(opaque, addr + 1) << 8;
+    v |= vga_mem_readb(opaque, addr + 2) << 16;
+    v |= vga_mem_readb(opaque, addr + 3) << 24;
+#endif
     return v;
 }
 
 /* called for accesses between 0xa0000 and 0xc0000 */
-static void vga_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
+void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
-    VGAState *s = &vga_state;
+    VGAState *s = opaque;
     int memory_map_mode, plane, write_mode, b, func_select;
     uint32_t write_mask, bit_mask, set_mask;
 
@@ -727,23 +670,23 @@ static void vga_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
 #endif
     /* convert to VGA memory offset */
     memory_map_mode = (s->gr[6] >> 2) & 3;
+    addr &= 0x1ffff;
     switch(memory_map_mode) {
     case 0:
-        addr -= 0xa0000;
         break;
     case 1:
-        if (addr >= 0xb0000)
+        if (addr >= 0x10000)
             return;
         addr += s->bank_offset;
         break;
     case 2:
-        addr -= 0xb0000;
+        addr -= 0x10000;
         if (addr >= 0x8000)
             return;
         break;
     default:
     case 3:
-        addr -= 0xb8000;
+        addr -= 0x18000;
         if (addr >= 0x8000)
             return;
         break;
@@ -844,18 +787,30 @@ static void vga_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
     }
 }
 
-static void vga_mem_writew(uint32_t addr, uint32_t val, uint32_t vaddr)
+static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
-    vga_mem_writeb(addr, val & 0xff, vaddr);
-    vga_mem_writeb(addr + 1, (val >> 8) & 0xff, vaddr);
+#ifdef TARGET_WORDS_BIGENDIAN
+    vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
+    vga_mem_writeb(opaque, addr + 1, val & 0xff);
+#else
+    vga_mem_writeb(opaque, addr, val & 0xff);
+    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+#endif
 }
 
-static void vga_mem_writel(uint32_t addr, uint32_t val, uint32_t vaddr)
+static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
-    vga_mem_writeb(addr, val & 0xff, vaddr);
-    vga_mem_writeb(addr + 1, (val >> 8) & 0xff, vaddr);
-    vga_mem_writeb(addr + 2, (val >> 16) & 0xff, vaddr);
-    vga_mem_writeb(addr + 3, (val >> 24) & 0xff, vaddr);
+#ifdef TARGET_WORDS_BIGENDIAN
+    vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
+    vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
+    vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
+    vga_mem_writeb(opaque, addr + 3, val & 0xff);
+#else
+    vga_mem_writeb(opaque, addr, val & 0xff);
+    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+#endif
 }
 
 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
@@ -900,14 +855,6 @@ static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsign
 #define DEPTH 32
 #include "vga_template.h"
 
-static inline int c6_to_8(int v)
-{
-    int b;
-    v &= 0x3f;
-    b = v & 1;
-    return (v << 2) | (b << 1) | b;
-}
-
 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
 {
     unsigned int col;
@@ -988,14 +935,11 @@ static int update_palette256(VGAState *s)
     return full_update;
 }
 
-/* update start_addr and line_offset. Return TRUE if modified */
-static int update_basic_params(VGAState *s)
+static void vga_get_offsets(VGAState *s, 
+                            uint32_t *pline_offset, 
+                            uint32_t *pstart_addr)
 {
-    int full_update;
-    uint32_t start_addr, line_offset, line_compare, v;
-    
-    full_update = 0;
-
+    uint32_t start_addr, line_offset;
 #ifdef CONFIG_BOCHS_VBE
     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
         line_offset = s->vbe_line_offset;
@@ -1006,10 +950,13 @@ static int update_basic_params(VGAState *s)
         /* compute line_offset in bytes */
         line_offset = s->cr[0x13];
 #ifdef CONFIG_S3VGA
-        v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
-        if (v == 0)
-            v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
-        line_offset |= (v << 8);
+        {
+            uinr32_t v;
+            v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
+            if (v == 0)
+                v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
+            line_offset |= (v << 8);
+        }
 #endif
         line_offset <<= 3;
         
@@ -1019,7 +966,19 @@ static int update_basic_params(VGAState *s)
         start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
 #endif
     }
+    *pline_offset = line_offset;
+    *pstart_addr = start_addr;
+}
+
+/* update start_addr and line_offset. Return TRUE if modified */
+static int update_basic_params(VGAState *s)
+{
+    int full_update;
+    uint32_t start_addr, line_offset, line_compare;
     
+    full_update = 0;
+
+    s->get_offsets(s, &line_offset, &start_addr);
     /* line compare */
     line_compare = s->cr[0x18] | 
         ((s->cr[0x07] & 0x10) << 4) |
@@ -1117,14 +1076,14 @@ static void vga_draw_text(VGAState *s, int full_update)
     
     /* compute font data address (in plane 2) */
     v = s->sr[3];
-    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
+    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
     if (offset != s->font_offsets[0]) {
         s->font_offsets[0] = offset;
         full_update = 1;
     }
     font_base[0] = s->vram_ptr + offset;
 
-    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
+    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
     font_base[1] = s->vram_ptr + offset;
     if (offset != s->font_offsets[1]) {
         s->font_offsets[1] = offset;
@@ -1331,11 +1290,47 @@ static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
     vga_draw_line32_32,
 };
 
+static int vga_get_bpp(VGAState *s)
+{
+    int ret;
+#ifdef CONFIG_BOCHS_VBE
+    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
+        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
+    } else 
+#endif
+    {
+        ret = 0;
+    }
+    return ret;
+}
+
+static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
+{
+    int width, height;
+    
+    width = (s->cr[0x01] + 1) * 8;
+    height = s->cr[0x12] | 
+        ((s->cr[0x07] & 0x02) << 7) | 
+        ((s->cr[0x07] & 0x40) << 3);
+    height = (height + 1);
+    *pwidth = width;
+    *pheight = height;
+}
+
+void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
+{
+    int y;
+    if (y1 >= VGA_MAX_HEIGHT)
+        return;
+    if (y2 >= VGA_MAX_HEIGHT)
+        y2 = VGA_MAX_HEIGHT;
+    for(y = y1; y < y2; y++) {
+        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
+    }
+}
+
 /* 
  * graphic modes
- * Missing:
- * - double scan
- * - double width 
  */
 static void vga_draw_graphic(VGAState *s, int full_update)
 {
@@ -1348,13 +1343,9 @@ static void vga_draw_graphic(VGAState *s, int full_update)
     
     full_update |= update_basic_params(s);
 
-    width = (s->cr[0x01] + 1) * 8;
-    height = s->cr[0x12] | 
-        ((s->cr[0x07] & 0x02) << 7) | 
-        ((s->cr[0x07] & 0x40) << 3);
-    height = (height + 1);
+    s->get_resolution(s, &width, &height);
     disp_width = width;
-    
+
     shift_control = (s->gr[0x05] >> 5) & 3;
     double_scan = (s->cr[0x09] & 0x80);
     if (shift_control > 1) {
@@ -1387,32 +1378,28 @@ static void vga_draw_graphic(VGAState *s, int full_update)
             v = VGA_DRAW_LINE2;
         }
     } else {
-#ifdef CONFIG_BOCHS_VBE
-        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
-            switch(s->vbe_regs[VBE_DISPI_INDEX_BPP]) {
-            default:
-            case 8:
-                full_update |= update_palette256(s);
-                v = VGA_DRAW_LINE8;
-                break;
-            case 15:
-                v = VGA_DRAW_LINE15;
-                break;
-            case 16:
-                v = VGA_DRAW_LINE16;
-                break;
-            case 24:
-                v = VGA_DRAW_LINE24;
-                break;
-            case 32:
-                v = VGA_DRAW_LINE32;
-                break;
-            }
-        } else 
-#endif
-        {
+        switch(s->get_bpp(s)) {
+        default:
+        case 0:
             full_update |= update_palette256(s);
             v = VGA_DRAW_LINE8D2;
+            break;
+        case 8:
+            full_update |= update_palette256(s);
+            v = VGA_DRAW_LINE8;
+            break;
+        case 15:
+            v = VGA_DRAW_LINE15;
+            break;
+        case 16:
+            v = VGA_DRAW_LINE16;
+            break;
+        case 24:
+            v = VGA_DRAW_LINE24;
+            break;
+        case 32:
+            v = VGA_DRAW_LINE32;
+            break;
         }
     }
     vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
@@ -1426,7 +1413,9 @@ static void vga_draw_graphic(VGAState *s, int full_update)
         s->last_height = height;
         full_update = 1;
     }
-
+    if (s->cursor_invalidate)
+        s->cursor_invalidate(s);
+    
     line_offset = s->line_offset;
 #if 0
     printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
@@ -1459,6 +1448,8 @@ static void vga_draw_graphic(VGAState *s, int full_update)
             /* if wide line, can use another page */
             update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
         }
+        /* explicit invalidation for the hardware cursor */
+        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
         if (update) {
             if (y_start < 0)
                 y_start = y;
@@ -1467,6 +1458,8 @@ static void vga_draw_graphic(VGAState *s, int full_update)
             if (page1 > page_max)
                 page_max = page1;
             vga_draw_line(s, d, s->vram_ptr + addr, width);
+            if (s->cursor_draw_line)
+                s->cursor_draw_line(s, d, y);
         } else {
             if (y_start >= 0) {
                 /* flush to display */
@@ -1502,6 +1495,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
     if (page_max != -1) {
         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
     }
+    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
 }
 
 static void vga_draw_blank(VGAState *s, int full_update)
@@ -1533,7 +1527,7 @@ static void vga_draw_blank(VGAState *s, int full_update)
 
 void vga_update_display(void)
 {
-    VGAState *s = &vga_state;
+    VGAState *s = vga_state;
     int full_update, graphic_mode;
 
     if (s->ds->depth == 0) {
@@ -1580,6 +1574,15 @@ void vga_update_display(void)
     }
 }
 
+/* force a full display refresh */
+void vga_invalidate_display(void)
+{
+    VGAState *s = vga_state;
+    
+    s->last_width = -1;
+    s->last_height = -1;
+}
+
 static void vga_reset(VGAState *s)
 {
     memset(s, 0, sizeof(VGAState));
@@ -1697,10 +1700,17 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, 
-                   unsigned long vga_ram_offset, int vga_ram_size)
+static void vga_map(PCIDevice *pci_dev, int region_num, 
+                    uint32_t addr, uint32_t size, int type)
+{
+    VGAState *s = vga_state;
+
+    cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
+}
+
+void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
+                     unsigned long vga_ram_offset, int vga_ram_size)
 {
-    VGAState *s = &vga_state;
     int i, j, v, b;
 
     for(i = 0;i < 256; i++) {
@@ -1732,6 +1742,24 @@ int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base,
     s->vram_offset = vga_ram_offset;
     s->vram_size = vga_ram_size;
     s->ds = ds;
+    s->get_bpp = vga_get_bpp;
+    s->get_offsets = vga_get_offsets;
+    s->get_resolution = vga_get_resolution;
+    /* XXX: currently needed for display */
+    vga_state = s;
+}
+
+
+int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
+                   unsigned long vga_ram_offset, int vga_ram_size)
+{
+    VGAState *s;
+
+    s = qemu_mallocz(sizeof(VGAState));
+    if (!s)
+        return -1;
+
+    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
 
     register_savevm("vga", 0, 1, vga_save, vga_load, s);
 
@@ -1748,29 +1776,63 @@ int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base,
     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
-    s->bank_offset = -0xa0000;
+    s->bank_offset = 0;
 
 #ifdef CONFIG_BOCHS_VBE
     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
     s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
-    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read, s);
-    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read, s);
+#if defined (TARGET_I386)
+    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
+    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
 
-    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write, s);
-    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write, s);
-#endif
+    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
+    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
 
-    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write);
-#if defined (TARGET_I386)
-    cpu_register_physical_memory(0x000a0000, 0x20000, vga_io_memory);
-#ifdef CONFIG_BOCHS_VBE
-    /* XXX: use optimized standard vga accesses */
-    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
-                                 vga_ram_size, vga_ram_offset);
+    /* old Bochs IO ports */
+    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
+    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
+
+    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
+    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); 
+#else
+    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
+    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
+
+    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
+    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
 #endif
-#elif defined (TARGET_PPC)
-    cpu_register_physical_memory(0xf00a0000, 0x20000, vga_io_memory);
+#endif /* CONFIG_BOCHS_VBE */
+
+    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
+    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
+                                 vga_io_memory);
+
+    if (bus) {
+        PCIDevice *d;
+        uint8_t *pci_conf;
+
+        d = pci_register_device(bus, "VGA", 
+                                sizeof(PCIDevice),
+                                -1, NULL, NULL);
+        pci_conf = d->config;
+        pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
+        pci_conf[0x01] = 0x12;
+        pci_conf[0x02] = 0x11;
+        pci_conf[0x03] = 0x11;
+        pci_conf[0x0a] = 0x00; // VGA controller 
+        pci_conf[0x0b] = 0x03;
+        pci_conf[0x0e] = 0x00; // header_type
+
+        /* XXX: vga_ram_size must be a power of two */
+        pci_register_io_region(d, 0, vga_ram_size, 
+                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+    } else {
+#ifdef CONFIG_BOCHS_VBE
+        /* XXX: use optimized standard vga accesses */
+        cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
+                                     vga_ram_size, vga_ram_offset);
 #endif
+    }
     return 0;
 }
 
@@ -1829,12 +1891,11 @@ static int ppm_save(const char *filename, uint8_t *data,
    available */
 void vga_screen_dump(const char *filename)
 {
-    VGAState *s = &vga_state;
+    VGAState *s = vga_state;
     DisplayState *saved_ds, ds1, *ds = &ds1;
     
     /* XXX: this is a little hackish */
-    s->last_width = -1;
-    s->last_height = -1;
+    vga_invalidate_display();
     saved_ds = s->ds;
 
     memset(ds, 0, sizeof(DisplayState));