win32 compile fix
[qemu] / hw / vga.c
index 23695f5..49e5b21 100644 (file)
--- a/hw/vga.c
+++ b/hw/vga.c
 //#define DEBUG_VGA_MEM
 //#define DEBUG_VGA_REG
 
-//#define DEBUG_S3
 //#define DEBUG_BOCHS_VBE
 
-/* S3 VGA is deprecated - another graphic card will be emulated */
-//#define CONFIG_S3VGA
-
 /* force some bits to zero */
 const uint8_t sr_mask[8] = {
     (uint8_t)~0xfc,
@@ -190,6 +186,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) {
@@ -222,11 +221,6 @@ static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
 #ifdef DEBUG_VGA_REG
             printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
 #endif
-#ifdef DEBUG_S3
-            if (s->cr_index >= 0x20)
-                printf("S3: CR read index=0x%x val=0x%x\n",
-                       s->cr_index, val);
-#endif
             break;
         case 0x3ba:
         case 0x3da:
@@ -341,7 +335,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
 #endif
         /* handle CR0-7 protection */
-        if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
+        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
             /* can always write bit 4 of CR7 */
             if (s->cr_index == 7)
                 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
@@ -356,43 +350,10 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         case 0x12: /* veritcal display end */
             s->cr[s->cr_index] = val;
             break;
-
-#ifdef CONFIG_S3VGA
-            /* S3 registers */
-        case 0x2d:
-        case 0x2e:
-        case 0x2f:
-        case 0x30:
-            /* chip ID, cannot write */
-            break;
-        case 0x31:
-            /* update start address */
-            {
-                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 */
-            {
-                int v;
-                s->cr[s->cr_index] = val;
-                v = val & 3;
-                s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
-            }
-            break;
-#endif
         default:
             s->cr[s->cr_index] = val;
             break;
         }
-#ifdef DEBUG_S3
-        if (s->cr_index >= 0x20)
-            printf("S3: CR write index=0x%x val=0x%x\n",
-                   s->cr_index, val);
-#endif
         break;
     case 0x3ba:
     case 0x3da:
@@ -659,7 +620,7 @@ static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     VGAState *s = opaque;
-    int memory_map_mode, plane, write_mode, b, func_select;
+    int memory_map_mode, plane, write_mode, b, func_select, mask;
     uint32_t write_mask, bit_mask, set_mask;
 
 #ifdef DEBUG_VGA_MEM
@@ -692,22 +653,26 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
     if (s->sr[4] & 0x08) {
         /* chain 4 mode : simplest access */
         plane = addr & 3;
-        if (s->sr[2] & (1 << plane)) {
+        mask = (1 << plane);
+        if (s->sr[2] & mask) {
             s->vram_ptr[addr] = val;
 #ifdef DEBUG_VGA_MEM
             printf("vga: chain4: [0x%x]\n", addr);
 #endif
+            s->plane_updated |= mask; /* only used to detect font change */
             cpu_physical_memory_set_dirty(s->vram_offset + addr);
         }
     } else if (s->gr[5] & 0x10) {
         /* odd/even mode (aka text mode mapping) */
         plane = (s->gr[4] & 2) | (addr & 1);
-        if (s->sr[2] & (1 << plane)) {
+        mask = (1 << plane);
+        if (s->sr[2] & mask) {
             addr = ((addr & ~1) << 1) | plane;
             s->vram_ptr[addr] = val;
 #ifdef DEBUG_VGA_MEM
             printf("vga: odd/even: [0x%x]\n", addr);
 #endif
+            s->plane_updated |= mask; /* only used to detect font change */
             cpu_physical_memory_set_dirty(s->vram_offset + addr);
         }
     } else {
@@ -772,7 +737,9 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 
     do_write:
         /* mask data according to sr[2] */
-        write_mask = mask16[s->sr[2]];
+        mask = s->sr[2];
+        s->plane_updated |= mask; /* only used to detect font change */
+        write_mask = mask16[mask];
         ((uint32_t *)s->vram_ptr)[addr] = 
             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
             (val & write_mask);
@@ -821,8 +788,7 @@ typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
 
 static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
 {
-    /* XXX: TODO */
-    return 0;
+    return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
 }
 
 static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
@@ -946,22 +912,10 @@ static void vga_get_offsets(VGAState *s,
     {  
         /* compute line_offset in bytes */
         line_offset = s->cr[0x13];
-#ifdef CONFIG_S3VGA
-        {
-            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;
-        
+
         /* starting address */
         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
-#ifdef CONFIG_S3VGA
-        start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
-#endif
     }
     *pline_offset = line_offset;
     *pstart_addr = start_addr;
@@ -1086,7 +1040,12 @@ static void vga_draw_text(VGAState *s, int full_update)
         s->font_offsets[1] = offset;
         full_update = 1;
     }
-
+    if (s->plane_updated & (1 << 2)) {
+        /* if the plane 2 was modified since the last display, it
+           indicates the font may have been modified */
+        s->plane_updated = 0;
+        full_update = 1;
+    }
     full_update |= update_basic_params(s);
 
     line_offset = s->line_offset;
@@ -1301,6 +1260,19 @@ static int vga_get_bpp(VGAState *s)
     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;
@@ -1327,19 +1299,17 @@ 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) {
-        multi_scan = (s->cr[0x09] & 0x1f);
+    double_scan = (s->cr[0x09] >> 7);
+    if (shift_control != 1) {
+        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
     } else {
-        multi_scan = 0;
+        /* in CGA modes, multi_scan is ignored */
+        /* XXX: is it correct ? */
+        multi_scan = double_scan;
     }
     multi_run = multi_scan;
     if (shift_control != s->shift_control ||
@@ -1406,7 +1376,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
     
     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",
+    printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
 #endif
     addr1 = (s->start_addr * 4);
@@ -1430,11 +1400,13 @@ static void vga_draw_graphic(VGAState *s, int full_update)
         }
         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
-        update = full_update | cpu_physical_memory_is_dirty(page0) |
-            cpu_physical_memory_is_dirty(page1);
+        update = full_update | 
+            cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
+            cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
         if ((page1 - page0) > TARGET_PAGE_SIZE) {
             /* if wide line, can use another page */
-            update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
+            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE, 
+                                                    VGA_DIRTY_FLAG);
         }
         /* explicit invalidation for the hardware cursor */
         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
@@ -1457,21 +1429,17 @@ static void vga_draw_graphic(VGAState *s, int full_update)
             }
         }
         if (!multi_run) {
-            if (!double_scan || (y & 1) != 0) {
-                if (y1 == s->line_compare) {
-                    addr1 = 0;
-                } else {
-                    mask = (s->cr[0x17] & 3) ^ 3;
-                    if ((y1 & mask) == mask)
-                        addr1 += line_offset;
-                }
-                y1++;
-            }
+            mask = (s->cr[0x17] & 3) ^ 3;
+            if ((y1 & mask) == mask)
+                addr1 += line_offset;
+            y1++;
             multi_run = multi_scan;
         } else {
             multi_run--;
-            y1++;
         }
+        /* line compare acts on the displayed lines */
+        if (y == s->line_compare)
+            addr1 = 0;
         d += linesize;
     }
     if (y_start >= 0) {
@@ -1481,7 +1449,8 @@ static void vga_draw_graphic(VGAState *s, int full_update)
     }
     /* reset modified pages */
     if (page_max != -1) {
-        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
+        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
+                                        VGA_DIRTY_FLAG);
     }
     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
 }
@@ -1562,16 +1531,18 @@ 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));
-#ifdef CONFIG_S3VGA
-    /* chip ID for 8c968 */
-    s->cr[0x2d] = 0x88;
-    s->cr[0x2e] = 0xb0;
-    s->cr[0x2f] = 0x01; /* XXX: check revision code */
-    s->cr[0x30] = 0xe1;
-#endif
     s->graphic_mode = -1; /* force full update */
 }
 
@@ -1683,8 +1654,11 @@ 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);
+    if (region_num == PCI_ROM_SLOT) {
+        cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
+    } else {
+        cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
+    }
 }
 
 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
@@ -1723,14 +1697,15 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
     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(DisplayState *ds, uint8_t *vga_ram_base, 
-                   unsigned long vga_ram_offset, int vga_ram_size, 
-                   int is_pci)
+int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
+                   unsigned long vga_ram_offset, int vga_ram_size,
+                   unsigned long vga_bios_offset, int vga_bios_size)
 {
     VGAState *s;
 
@@ -1786,14 +1761,13 @@ int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base,
     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
                                  vga_io_memory);
 
-    if (is_pci) {
+    if (bus) {
         PCIDevice *d;
         uint8_t *pci_conf;
 
-        d = pci_register_device("VGA", 
+        d = pci_register_device(bus, "VGA", 
                                 sizeof(PCIDevice),
-                                0, -1, 
-                                NULL, NULL);
+                                -1, NULL, NULL);
         pci_conf = d->config;
         pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
         pci_conf[0x01] = 0x12;
@@ -1806,6 +1780,17 @@ int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base,
         /* 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);
+        if (vga_bios_size != 0) {
+            unsigned int bios_total_size;
+            s->bios_offset = vga_bios_offset;
+            s->bios_size = vga_bios_size;
+            /* must be a power of two */
+            bios_total_size = 1;
+            while (bios_total_size < vga_bios_size)
+                bios_total_size <<= 1;
+            pci_register_io_region(d, PCI_ROM_SLOT, bios_total_size, 
+                                   PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+        }
     } else {
 #ifdef CONFIG_BOCHS_VBE
         /* XXX: use optimized standard vga accesses */
@@ -1875,8 +1860,7 @@ void vga_screen_dump(const char *filename)
     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));