set memory size to 4MB for 5446 - fixed memory size probe (aka Win2000 bug) - fixed interlace support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@914 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 55a866a..a883d52 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -31,6 +31,7 @@
 
 /*
  * TODO:
+ *    - fix 24 bpp pattern fills (source is 32 bpp in that case)
  *    - add support for WRITEMASK (GR2F)
  *    - add support for scanline modulo in pattern fill
  *    - optimize linear mappings
@@ -233,6 +234,7 @@
     int cirrus_linear_bitblt_io_addr;
     int cirrus_mmio_io_addr;
     uint32_t cirrus_addr_mask;
+    uint32_t linear_mmio_mask;
     uint8_t cirrus_shadow_gr0;
     uint8_t cirrus_shadow_gr1;
     uint8_t cirrus_hidden_dac_lockindex;
@@ -268,6 +270,7 @@
     int last_hw_cursor_y;
     int last_hw_cursor_y_start;
     int last_hw_cursor_y_end;
+    int real_vram_size; /* XXX: suppress that */
 } CirrusVGAState;
 
 typedef struct PCICirrusVGAState {
@@ -983,6 +986,22 @@
     return ret;
 }
 
+static void cirrus_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);
+    /* interlace support */
+    if (s->cr[0x1a] & 0x01)
+        height = height * 2;
+    *pwidth = width;
+    *pheight = height;
+}
+
 /***************************************
  *
  * bank memory
@@ -1970,7 +1989,7 @@
     uint32_t content;
     int y, y_min, y_max;
 
-    src = s->vram_ptr + 0x200000 - 16 * 1024;
+    src = s->vram_ptr + s->real_vram_size - 16 * 1024;
     if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
         src += (s->sr[0x13] & 0x3c) * 256;
         y_min = 64;
@@ -2064,7 +2083,7 @@
         scr_y >= (s->hw_cursor_y + h))
         return;
     
-    src = s->vram_ptr + 0x200000 - 16 * 1024;
+    src = s->vram_ptr + s->real_vram_size - 16 * 1024;
     if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
         src += (s->sr[0x13] & 0x3c) * 256;
         src += (scr_y - s->hw_cursor_y) * 16;
@@ -2130,10 +2149,10 @@
     CirrusVGAState *s = (CirrusVGAState *) opaque;
     uint32_t ret;
 
-    /* XXX: s->vram_size must be a power of two */
     addr &= s->cirrus_addr_mask;
 
-    if (((s->sr[0x17] & 0x44) == 0x44) && ((addr & 0x1fff00) == 0x1fff00)) {
+    if (((s->sr[0x17] & 0x44) == 0x44) && 
+        ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
 	/* memory-mapped I/O */
 	ret = cirrus_mmio_blt_read(s, addr & 0xff);
     } else if (0) {
@@ -2190,8 +2209,9 @@
     unsigned mode;
 
     addr &= s->cirrus_addr_mask;
-
-    if (((s->sr[0x17] & 0x44) == 0x44) && ((addr & 0x1fff00) == 0x1fff00)) {
+        
+    if (((s->sr[0x17] & 0x44) == 0x44) && 
+        ((addr & s->linear_mmio_mask) ==  s->linear_mmio_mask)) {
 	/* memory-mapped I/O */
 	cirrus_mmio_blt_write(s, addr & 0xff, val);
     } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
@@ -2715,7 +2735,7 @@
  *
  ***************************************/
 
-static void cirrus_init_common(CirrusVGAState * s, int device_id)
+static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
 {
     int vga_io_memory, i;
     static int inited;
@@ -2762,11 +2782,35 @@
                                  vga_io_memory);
 
     s->sr[0x06] = 0x0f;
-    s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
     s->sr[0x1F] = 0x22;		// MemClock
-
+    if (device_id == CIRRUS_ID_CLGD5446) {
+        /* 4MB 64 bit memory config, always PCI */
+#if 1
+        s->sr[0x0f] = 0x98;
+        s->sr[0x17] = 0x20;
+        s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */
+        s->real_vram_size = 4096 * 1024;
+#else
+        s->sr[0x0f] = 0x18;
+        s->sr[0x17] = 0x20;
+        s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
+        s->real_vram_size = 2048 * 1024;
+#endif
+    } else {
+        s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
+        if (is_pci) 
+            s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
+        else
+            s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
+        s->real_vram_size = 2048 * 1024;
+        s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
+    }
     s->cr[0x27] = device_id;
 
+    /* Win2K seems to assume that the pattern buffer is at 0xff
+       initially ! */
+    memset(s->vram_ptr, 0xff, s->real_vram_size);
+
     s->cirrus_hidden_dac_lockindex = 5;
     s->cirrus_hidden_dac_data = 0;
 
@@ -2784,10 +2828,12 @@
 	cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s);
 
     /* XXX: s->vram_size must be a power of two */
-    s->cirrus_addr_mask = s->vram_size - 1;
+    s->cirrus_addr_mask = s->real_vram_size - 1;
+    s->linear_mmio_mask = s->real_vram_size - 256;
 
     s->get_bpp = cirrus_get_bpp;
     s->get_offsets = cirrus_get_offsets;
+    s->get_resolution = cirrus_get_resolution;
     s->cursor_invalidate = cirrus_cursor_invalidate;
     s->cursor_draw_line = cirrus_cursor_draw_line;
 }
@@ -2807,8 +2853,7 @@
     
     vga_common_init((VGAState *)s, 
                     ds, vga_ram_base, vga_ram_offset, vga_ram_size);
-    cirrus_init_common(s, CIRRUS_ID_CLGD5430);
-    s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
+    cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0);
     /* XXX ISA-LFB support */
 }
 
@@ -2867,8 +2912,7 @@
     s = &d->cirrus_vga;
     vga_common_init((VGAState *)s, 
                     ds, vga_ram_base, vga_ram_offset, vga_ram_size);
-    cirrus_init_common(s, device_id);
-    s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
+    cirrus_init_common(s, device_id, 1);
 
     /* setup memory space */
     /* memory #0 LFB */