change ID to CLGD5446 - added solidfill support - fixed hidden dac access
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 5 Jun 2004 17:59:37 +0000 (17:59 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 5 Jun 2004 17:59:37 +0000 (17:59 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@899 c046a42c-6fe2-441c-8c8c-71466251a162

hw/cirrus_vga.c

index 0a408aa..6305c94 100644 (file)
@@ -30,6 +30,7 @@
 #include "vga_int.h"
 
 //#define DEBUG_CIRRUS
+//#define DEBUG_BITBLT
 
 /***************************************
  *
 #define CIRRUS_ID_CLGD5428  (0x26<<2)
 #define CIRRUS_ID_CLGD5430  (0x28<<2)
 #define CIRRUS_ID_CLGD5434  (0x2A<<2)
+#define CIRRUS_ID_CLGD5436  (0x2B<<2)
 #define CIRRUS_ID_CLGD5446  (0x2E<<2)
 
+/* this define is used to select the exact CLGD implementation we
+   emulate. */
+//#define CIRRUS_ID CIRRUS_ID_CLGD5430
+#define CIRRUS_ID CIRRUS_ID_CLGD5446
+
 // sequencer 0x07
 #define CIRRUS_SR7_BPP_VGA            0x00
 #define CIRRUS_SR7_BPP_SVGA           0x01
 #define CIRRUS_ROP_NOTSRC_OR_DST        0xd6
 #define CIRRUS_ROP_NOTSRC_AND_NOTDST    0xda
 
+// control 0x33
+#define CIRRUS_BLTMODEEXT_SOLIDFILL     0x04
+
 // memory-mapped IO
 #define CIRRUS_MMIO_BLTBGCOLOR        0x00     // dword
 #define CIRRUS_MMIO_BLTFGCOLOR        0x04     // dword
 
 // PCI 0x00: vendor, 0x02: device
 #define PCI_VENDOR_CIRRUS             0x1013
-#define PCI_DEVICE_CLGD5430           0x00a0   // CLGD5430 or CLGD5440
-#define PCI_DEVICE_CLGD5434           0x00a8
-#define PCI_DEVICE_CLGD5436           0x00ac
-#define PCI_DEVICE_CLGD5446           0x00b8
+#define PCI_DEVICE_ID                 CIRRUS_ID
 #define PCI_DEVICE_CLGD5462           0x00d0
 #define PCI_DEVICE_CLGD5465           0x00d6
+
 // PCI 0x04: command(word), 0x06(word): status
 #define PCI_COMMAND_IOACCESS                0x0001
 #define PCI_COMMAND_MEMACCESS               0x0002
 // PCI 0x38: reserved
 // PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat
 
-#define CIRRUS_PNPMMIO_SIZE         0x800
+#define CIRRUS_PNPMMIO_SIZE         0x1000
 
 
 /* I/O and memory hook */
@@ -264,7 +272,7 @@ static void cirrus_bitblt_reset(CirrusVGAState * s);
  *
  ***************************************/
 
-#define IMPLEMENT_FORWARD_BITBLT(name,opline) \
+#define IMPLEMENT_BITBLT(name,opline) \
   static void \
   cirrus_bitblt_rop_fwd_##name( \
     uint8_t *dst,const uint8_t *src, \
@@ -283,9 +291,8 @@ static void cirrus_bitblt_reset(CirrusVGAState * s);
       dst += dstpitch; \
       src += srcpitch; \
       } \
-    }
-
-#define IMPLEMENT_BACKWARD_BITBLT(name,opline) \
+    } \
+ \
   static void \
   cirrus_bitblt_rop_bkwd_##name( \
     uint8_t *dst,const uint8_t *src, \
@@ -306,39 +313,22 @@ static void cirrus_bitblt_reset(CirrusVGAState * s);
     } \
   }
 
-IMPLEMENT_FORWARD_BITBLT(0, *dst = 0)
-    IMPLEMENT_FORWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst))
-    IMPLEMENT_FORWARD_BITBLT(nop, (void) 0)
-    IMPLEMENT_FORWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
-    IMPLEMENT_FORWARD_BITBLT(notdst, *dst = ~(*dst))
-    IMPLEMENT_FORWARD_BITBLT(src, *dst = *src)
-    IMPLEMENT_FORWARD_BITBLT(1, *dst = 0xff)
-    IMPLEMENT_FORWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
-    IMPLEMENT_FORWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
-    IMPLEMENT_FORWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst))
-    IMPLEMENT_FORWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
-    IMPLEMENT_FORWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
-    IMPLEMENT_FORWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
-    IMPLEMENT_FORWARD_BITBLT(notsrc, *dst = (~(*src)))
-    IMPLEMENT_FORWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
-    IMPLEMENT_FORWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
-
-    IMPLEMENT_BACKWARD_BITBLT(0, *dst = 0)
-    IMPLEMENT_BACKWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst))
-    IMPLEMENT_BACKWARD_BITBLT(nop, (void) 0)
-    IMPLEMENT_BACKWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
-    IMPLEMENT_BACKWARD_BITBLT(notdst, *dst = ~(*dst))
-    IMPLEMENT_BACKWARD_BITBLT(src, *dst = *src)
-    IMPLEMENT_BACKWARD_BITBLT(1, *dst = 0xff)
-    IMPLEMENT_BACKWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
-    IMPLEMENT_BACKWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
-    IMPLEMENT_BACKWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst))
-    IMPLEMENT_BACKWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
-    IMPLEMENT_BACKWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
-    IMPLEMENT_BACKWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
-    IMPLEMENT_BACKWARD_BITBLT(notsrc, *dst = (~(*src)))
-    IMPLEMENT_BACKWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
-    IMPLEMENT_BACKWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
+IMPLEMENT_BITBLT(0, *dst = 0)
+IMPLEMENT_BITBLT(src_and_dst, *dst = (*src) & (*dst))
+IMPLEMENT_BITBLT(nop, (void) 0)
+IMPLEMENT_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
+IMPLEMENT_BITBLT(notdst, *dst = ~(*dst))
+IMPLEMENT_BITBLT(src, *dst = *src)
+IMPLEMENT_BITBLT(1, *dst = 0xff)
+IMPLEMENT_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
+IMPLEMENT_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
+IMPLEMENT_BITBLT(src_or_dst, *dst = (*src) | (*dst))
+IMPLEMENT_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
+IMPLEMENT_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
+IMPLEMENT_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
+IMPLEMENT_BITBLT(notsrc, *dst = (~(*src)))
+IMPLEMENT_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
+IMPLEMENT_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
 
 static cirrus_bitblt_rop_t cirrus_get_fwd_rop_handler(uint8_t rop)
 {
@@ -666,7 +656,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
 #endif
        return 0;
     }
-
+    
     dst = s->vram_ptr + s->cirrus_blt_dstaddr;
     for (y = 0; y < s->cirrus_blt_height; y += 8) {
        dstc = dst;
@@ -686,6 +676,120 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
     return 1;
 }
 
+/* fill */
+
+static void cirrus_fill_8(CirrusVGAState *s,
+                          uint8_t *dst, int dst_pitch, int width, int height)
+{
+    uint8_t *d, *d1;
+    uint32_t val;
+    int x, y;
+
+    val = s->cirrus_shadow_gr1;
+
+    d1 = dst;
+    for(y = 0; y < height; y++) {
+        d = d1;
+        for(x = 0; x < width; x++) {
+            *d++ = val;
+        }
+        d1 += dst_pitch;
+    }
+}
+
+static void cirrus_fill_16(CirrusVGAState *s,
+                           uint8_t *dst, int dst_pitch, int width, int height)
+{
+    uint8_t *d, *d1;
+    uint32_t val;
+    int x, y;
+
+    val = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8);
+    val = le16_to_cpu(val);
+    width >>= 1;
+
+    d1 = dst;
+    for(y = 0; y < height; y++) {
+        d = d1;
+        for(x = 0; x < width; x++) {
+            ((uint16_t *)d)[0] = val;
+            d += 2;
+        }
+        d1 += dst_pitch;
+    }
+}
+
+static void cirrus_fill_24(CirrusVGAState *s,
+                           uint8_t *dst, int dst_pitch, int width, int height)
+{
+    uint8_t *d, *d1;
+    int x, y;
+
+    d1 = dst;
+    for(y = 0; y < height; y++) {
+        d = d1;
+        for(x = 0; x < width; x += 3) {
+            *d++ = s->cirrus_shadow_gr1;
+            *d++ = s->gr[0x11];
+            *d++ = s->gr[0x13];
+        }
+        d1 += dst_pitch;
+    }
+}
+
+static void cirrus_fill_32(CirrusVGAState *s,
+                           uint8_t *dst, int dst_pitch, int width, int height)
+{
+    uint8_t *d, *d1;
+    uint32_t val;
+    int x, y;
+
+    val = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) | 
+        (s->gr[0x13] << 8) | (s->gr[0x15] << 8);
+    val = le32_to_cpu(val);
+    width >>= 2;
+
+    d1 = dst;
+    for(y = 0; y < height; y++) {
+        d = d1;
+        for(x = 0; x < width; x++) {
+            ((uint32_t *)d)[0] = val;
+            d += 4;
+        }
+        d1 += dst_pitch;
+    }
+}
+
+static int cirrus_bitblt_solidfill(CirrusVGAState *s)
+{
+    uint8_t *dst;
+    dst = s->vram_ptr + s->cirrus_blt_dstaddr;
+    switch (s->cirrus_blt_pixelwidth) {
+    case 1:
+       cirrus_fill_8(s, dst, s->cirrus_blt_dstpitch,
+                      s->cirrus_blt_width, s->cirrus_blt_height);
+       break;
+    case 2:
+       cirrus_fill_16(s, dst, s->cirrus_blt_dstpitch,
+                       s->cirrus_blt_width, s->cirrus_blt_height);
+       break;
+    case 3:
+       cirrus_fill_24(s, dst, s->cirrus_blt_dstpitch,
+                       s->cirrus_blt_width, s->cirrus_blt_height);
+       break;
+    default:
+    case 4:
+       cirrus_fill_32(s, dst, s->cirrus_blt_dstpitch,
+                       s->cirrus_blt_width, s->cirrus_blt_height);
+       break;
+    }
+    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+                            s->cirrus_blt_dstpitch, s->cirrus_blt_width,
+                            s->cirrus_blt_height);
+    cirrus_bitblt_reset(s);
+    return 1;
+}
+
 /***************************************
  *
  *  bitblt (video-to-video)
@@ -952,6 +1056,19 @@ static void cirrus_bitblt_start(CirrusVGAState * s)
     s->cirrus_blt_mode = s->gr[0x30];
     blt_rop = s->gr[0x32];
 
+#ifdef DEBUG_BITBLT
+    printf("rop=%02x mode=%02x modeext=%02x w=%d h=%d dpitch=%d spicth=%d daddr=%08x saddr=%08x\n",
+           blt_rop, 
+           s->cirrus_blt_mode,
+           s->gr[0x33],
+           s->cirrus_blt_width,
+           s->cirrus_blt_height,
+           s->cirrus_blt_dstpitch,
+           s->cirrus_blt_srcpitch,
+           s->cirrus_blt_dstaddr,
+           s->cirrus_blt_srcaddr);
+#endif
+
     switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
     case CIRRUS_BLTMODE_PIXELWIDTH8:
        s->cirrus_blt_pixelwidth = 1;
@@ -983,26 +1100,34 @@ static void cirrus_bitblt_start(CirrusVGAState * s)
        goto bitblt_ignore;
     }
 
-    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
-       s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
-       s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
-       s->cirrus_rop = cirrus_get_bkwd_rop_handler(blt_rop);
+    if ((s->gr[0x33] & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
+        (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | 
+                               CIRRUS_BLTMODE_TRANSPARENTCOMP |
+                               CIRRUS_BLTMODE_PATTERNCOPY | 
+                               CIRRUS_BLTMODE_COLOREXPAND)) == 
+         (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
+        cirrus_bitblt_solidfill(s);
     } else {
-       s->cirrus_rop = cirrus_get_fwd_rop_handler(blt_rop);
+        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
+            s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
+            s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
+            s->cirrus_rop = cirrus_get_bkwd_rop_handler(blt_rop);
+        } else {
+            s->cirrus_rop = cirrus_get_fwd_rop_handler(blt_rop);
+        }
+        
+        // setup bitblt engine.
+        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
+            if (!cirrus_bitblt_cputovideo(s))
+                goto bitblt_ignore;
+        } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
+            if (!cirrus_bitblt_videotocpu(s))
+                goto bitblt_ignore;
+        } else {
+            if (!cirrus_bitblt_videotovideo(s))
+                goto bitblt_ignore;
+        }
     }
-
-    // setup bitblt engine.
-    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
-       if (!cirrus_bitblt_cputovideo(s))
-           goto bitblt_ignore;
-    } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
-       if (!cirrus_bitblt_videotocpu(s))
-           goto bitblt_ignore;
-    } else {
-       if (!cirrus_bitblt_videotovideo(s))
-           goto bitblt_ignore;
-    }
-
     return;
   bitblt_ignore:;
     cirrus_bitblt_reset(s);
@@ -1325,11 +1450,9 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
 static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value)
 {
     *reg_value = 0xff;
-    if (s->cirrus_hidden_dac_lockindex < 5) {
-       if (s->cirrus_hidden_dac_lockindex == 4) {
-           *reg_value = s->cirrus_hidden_dac_data;
-       }
-       s->cirrus_hidden_dac_lockindex++;
+    if (++s->cirrus_hidden_dac_lockindex == 5) {
+        *reg_value = s->cirrus_hidden_dac_data;
+       s->cirrus_hidden_dac_lockindex = 0;
     }
 }
 
@@ -1337,7 +1460,7 @@ static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
 {
     if (s->cirrus_hidden_dac_lockindex == 4) {
        s->cirrus_hidden_dac_data = reg_value;
-#ifdef DEBUG_CIRRUS
+#if defined(DEBUG_CIRRUS)
        printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
 #endif
     }
@@ -1468,6 +1591,7 @@ cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
     case 0x2d:                 // BLT SRC ADDR 0x00ff00
     case 0x30:                 // BLT MODE
     case 0x32:                 // RASTER OP
+    case 0x33:                 // BLT MODEEXT
     case 0x34:                 // BLT TRANSPARENT COLOR 0x00ff
     case 0x35:                 // BLT TRANSPARENT COLOR 0xff00
     case 0x38:                 // BLT TRANSPARENT COLOR MASK 0x00ff
@@ -1703,6 +1827,9 @@ static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
     case CIRRUS_MMIO_BLTROP:
        cirrus_hook_read_gr(s, 0x32, &value);
        break;
+    case CIRRUS_MMIO_BLTMODEEXT:
+       cirrus_hook_read_gr(s, 0x33, &value);
+       break;
     case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
        cirrus_hook_read_gr(s, 0x34, &value);
        break;
@@ -1810,6 +1937,9 @@ static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address,
     case CIRRUS_MMIO_BLTROP:
        cirrus_hook_write_gr(s, 0x32, value);
        break;
+    case CIRRUS_MMIO_BLTMODEEXT:
+       cirrus_hook_write_gr(s, 0x33, value);
+       break;
     case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
        cirrus_hook_write_gr(s, 0x34, value);
        break;
@@ -2592,7 +2722,7 @@ static void cirrus_init_common(CirrusVGAState * s)
     s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
     s->sr[0x1F] = 0x22;                // MemClock
 
-    s->cr[0x27] = CIRRUS_ID_CLGD5430;
+    s->cr[0x27] = CIRRUS_ID;
 
     s->cirrus_hidden_dac_lockindex = 5;
     s->cirrus_hidden_dac_data = 0;
@@ -2670,8 +2800,8 @@ void pci_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
     pci_conf = d->dev.config;
     pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
     pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8);
-    pci_conf[0x02] = (uint8_t) (PCI_DEVICE_CLGD5430 & 0xff);
-    pci_conf[0x03] = (uint8_t) (PCI_DEVICE_CLGD5430 >> 8);
+    pci_conf[0x02] = (uint8_t) (PCI_DEVICE_ID & 0xff);
+    pci_conf[0x03] = (uint8_t) (PCI_DEVICE_ID >> 8);
     pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
     pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
     pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
@@ -2689,8 +2819,10 @@ void pci_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
     /* memory #1 memory-mapped I/O */
     /* XXX: s->vram_size must be a power of two */
     pci_register_io_region((PCIDevice *)d, 0, s->vram_size,
-                          PCI_ADDRESS_SPACE_MEM, cirrus_pci_lfb_map);
-    pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
-                          PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
+                          PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
+    if (CIRRUS_ID == CIRRUS_ID_CLGD5446) {
+        pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
+                               PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
+    }
     /* XXX: ROM BIOS */
 }