/*
* TODO:
- * - add support for WRITEMASK (GR2F)
- * - add support for scanline modulo in pattern fill
+ * - destination write mask support not complete (bits 5..7)
* - optimize linear mappings
* - optimize bitblt functions
*/
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;
uint8_t *cirrus_srcptr;
uint8_t *cirrus_srcptr_end;
uint32_t cirrus_srccounter;
- uint8_t *cirrus_dstptr;
- uint8_t *cirrus_dstptr_end;
- uint32_t cirrus_dstcounter;
/* hwcursor display state */
int last_hw_cursor_size;
int last_hw_cursor_x;
int last_hw_cursor_y;
int last_hw_cursor_y_start;
int last_hw_cursor_y_end;
+ int real_vram_size; /* XXX: suppress that */
+ CPUWriteMemoryFunc **cirrus_linear_write;
} CirrusVGAState;
typedef struct PCICirrusVGAState {
***************************************/
-static void cirrus_bitblt_reset(CirrusVGAState * s);
+static void cirrus_bitblt_reset(CirrusVGAState *s);
+static void cirrus_update_memory_access(CirrusVGAState *s);
/***************************************
*
func,\
}
+static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = {
+ ROP2(cirrus_patternfill_0),
+ ROP2(cirrus_patternfill_src_and_dst),
+ ROP_NOP2(cirrus_bitblt_rop_nop),
+ ROP2(cirrus_patternfill_src_and_notdst),
+ ROP2(cirrus_patternfill_notdst),
+ ROP2(cirrus_patternfill_src),
+ ROP2(cirrus_patternfill_1),
+ ROP2(cirrus_patternfill_notsrc_and_dst),
+ ROP2(cirrus_patternfill_src_xor_dst),
+ ROP2(cirrus_patternfill_src_or_dst),
+ ROP2(cirrus_patternfill_notsrc_or_notdst),
+ ROP2(cirrus_patternfill_src_notxor_dst),
+ ROP2(cirrus_patternfill_src_or_notdst),
+ ROP2(cirrus_patternfill_notsrc),
+ ROP2(cirrus_patternfill_notsrc_or_dst),
+ ROP2(cirrus_patternfill_notsrc_and_notdst),
+};
+
static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = {
ROP2(cirrus_colorexpand_transp_0),
ROP2(cirrus_colorexpand_transp_src_and_dst),
ROP2(cirrus_colorexpand_transp_notsrc_and_notdst),
};
-static const cirrus_bitblt_rop_t cirrus_colorexpand_transp_inv[16][4] = {
- ROP2(cirrus_colorexpand_transp_inv_0),
- ROP2(cirrus_colorexpand_transp_inv_src_and_dst),
- ROP_NOP2(cirrus_bitblt_rop_nop),
- ROP2(cirrus_colorexpand_transp_inv_src_and_notdst),
- ROP2(cirrus_colorexpand_transp_inv_notdst),
- ROP2(cirrus_colorexpand_transp_inv_src),
- ROP2(cirrus_colorexpand_transp_inv_1),
- ROP2(cirrus_colorexpand_transp_inv_notsrc_and_dst),
- ROP2(cirrus_colorexpand_transp_inv_src_xor_dst),
- ROP2(cirrus_colorexpand_transp_inv_src_or_dst),
- ROP2(cirrus_colorexpand_transp_inv_notsrc_or_notdst),
- ROP2(cirrus_colorexpand_transp_inv_src_notxor_dst),
- ROP2(cirrus_colorexpand_transp_inv_src_or_notdst),
- ROP2(cirrus_colorexpand_transp_inv_notsrc),
- ROP2(cirrus_colorexpand_transp_inv_notsrc_or_dst),
- ROP2(cirrus_colorexpand_transp_inv_notsrc_and_notdst),
-};
-
static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = {
ROP2(cirrus_colorexpand_0),
ROP2(cirrus_colorexpand_src_and_dst),
ROP2(cirrus_colorexpand_notsrc_and_notdst),
};
+static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = {
+ ROP2(cirrus_colorexpand_pattern_transp_0),
+ ROP2(cirrus_colorexpand_pattern_transp_src_and_dst),
+ ROP_NOP2(cirrus_bitblt_rop_nop),
+ ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst),
+ ROP2(cirrus_colorexpand_pattern_transp_notdst),
+ ROP2(cirrus_colorexpand_pattern_transp_src),
+ ROP2(cirrus_colorexpand_pattern_transp_1),
+ ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst),
+ ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst),
+ ROP2(cirrus_colorexpand_pattern_transp_src_or_dst),
+ ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst),
+ ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst),
+ ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst),
+ ROP2(cirrus_colorexpand_pattern_transp_notsrc),
+ ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst),
+ ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst),
+};
+
+static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = {
+ ROP2(cirrus_colorexpand_pattern_0),
+ ROP2(cirrus_colorexpand_pattern_src_and_dst),
+ ROP_NOP2(cirrus_bitblt_rop_nop),
+ ROP2(cirrus_colorexpand_pattern_src_and_notdst),
+ ROP2(cirrus_colorexpand_pattern_notdst),
+ ROP2(cirrus_colorexpand_pattern_src),
+ ROP2(cirrus_colorexpand_pattern_1),
+ ROP2(cirrus_colorexpand_pattern_notsrc_and_dst),
+ ROP2(cirrus_colorexpand_pattern_src_xor_dst),
+ ROP2(cirrus_colorexpand_pattern_src_or_dst),
+ ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst),
+ ROP2(cirrus_colorexpand_pattern_src_notxor_dst),
+ ROP2(cirrus_colorexpand_pattern_src_or_notdst),
+ ROP2(cirrus_colorexpand_pattern_notsrc),
+ ROP2(cirrus_colorexpand_pattern_notsrc_or_dst),
+ ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst),
+};
+
static const cirrus_fill_t cirrus_fill[16][4] = {
ROP2(cirrus_fill_0),
ROP2(cirrus_fill_src_and_dst),
static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
const uint8_t * src)
{
- uint8_t work_colorexp[256];
uint8_t *dst;
- uint8_t *dstc;
- int x, y;
- int tilewidth, tileheight;
- int patternbytes = s->cirrus_blt_pixelwidth * 8;
- if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
- cirrus_bitblt_rop_t rop_func;
- cirrus_bitblt_fgcol(s);
- cirrus_bitblt_bgcol(s);
- rop_func = cirrus_colorexpand[CIRRUS_ROP_SRC_INDEX][s->cirrus_blt_pixelwidth - 1];
- rop_func(s, work_colorexp, src, patternbytes, 1, patternbytes, 8);
- src = work_colorexp;
- s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_COLOREXPAND;
- }
- if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_PATTERNCOPY) {
-#ifdef DEBUG_BITBLT
- printf("cirrus: blt mode %02x (pattercopy) - unimplemented\n",
- s->cirrus_blt_mode);
-#endif
- return 0;
- }
-
dst = s->vram_ptr + s->cirrus_blt_dstaddr;
- for (y = 0; y < s->cirrus_blt_height; y += 8) {
- dstc = dst;
- tileheight = qemu_MIN(8, s->cirrus_blt_height - y);
- for (x = 0; x < s->cirrus_blt_width; x += patternbytes) {
- tilewidth = qemu_MIN(patternbytes, s->cirrus_blt_width - x);
- (*s->cirrus_rop) (s, dstc, src,
- s->cirrus_blt_dstpitch, patternbytes,
- tilewidth, tileheight);
- dstc += patternbytes;
- }
- dst += s->cirrus_blt_dstpitch * 8;
- }
+ (*s->cirrus_rop) (s, dst, src,
+ s->cirrus_blt_dstpitch, 0,
+ s->cirrus_blt_width, s->cirrus_blt_height);
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
- s->cirrus_blt_dstpitch, s->cirrus_blt_width,
- s->cirrus_blt_height);
+ s->cirrus_blt_dstpitch, s->cirrus_blt_width,
+ s->cirrus_blt_height);
return 1;
}
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
{
return cirrus_bitblt_common_patterncopy(s,
- s->vram_ptr +
- s->cirrus_blt_srcaddr);
+ s->vram_ptr +
+ (s->cirrus_blt_srcaddr & ~7));
}
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
s->cirrus_srcptr = &s->cirrus_bltbuf[0];
s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
s->cirrus_srccounter = 0;
- s->cirrus_dstptr = &s->cirrus_bltbuf[0];
- s->cirrus_dstptr_end = &s->cirrus_bltbuf[0];
- s->cirrus_dstcounter = 0;
+ cirrus_update_memory_access(s);
}
static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
s->cirrus_blt_srcpitch = 8;
} else {
+ /* XXX: check for 24 bpp */
s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth;
}
s->cirrus_srccounter = s->cirrus_blt_srcpitch;
else
s->cirrus_blt_srcpitch = ((w + 7) >> 3);
} else {
- s->cirrus_blt_srcpitch = s->cirrus_blt_width;
+ /* always align input size to 32 bits */
+ s->cirrus_blt_srcpitch = (s->cirrus_blt_width + 3) & ~3;
}
s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
}
s->cirrus_srcptr = s->cirrus_bltbuf;
s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
+ cirrus_update_memory_access(s);
return 1;
}
blt_rop = s->gr[0x32];
#ifdef DEBUG_BITBLT
- printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spicth=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
+ printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
blt_rop,
s->cirrus_blt_mode,
s->cirrus_blt_modeext,
s->cirrus_blt_srcpitch,
s->cirrus_blt_dstaddr,
s->cirrus_blt_srcaddr,
- s->sr[0x2f]);
+ s->gr[0x2f]);
#endif
switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
CIRRUS_BLTMODE_COLOREXPAND) {
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
- if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
+ if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
cirrus_bitblt_bgcol(s);
- s->cirrus_rop = cirrus_colorexpand_transp_inv[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
- } else {
+ else
cirrus_bitblt_fgcol(s);
- s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
- }
+ s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
} else {
cirrus_bitblt_fgcol(s);
cirrus_bitblt_bgcol(s);
s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
}
+ } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
+ if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
+ cirrus_bitblt_bgcol(s);
+ else
+ cirrus_bitblt_fgcol(s);
+ s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+ } else {
+ cirrus_bitblt_fgcol(s);
+ cirrus_bitblt_bgcol(s);
+ s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+ }
+ } else {
+ s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+ }
} else {
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
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
else
offset <<= 12;
- if (s->vram_size <= offset)
+ if (s->real_vram_size <= offset)
limit = 0;
else
- limit = s->vram_size - offset;
+ limit = s->real_vram_size - offset;
if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
if (limit > 0x8000) {
case 0x14: // Scratch Register 2
case 0x15: // Scratch Register 3
case 0x16: // Performance Tuning Register
- case 0x17: // Configuration Readback and Extended Control
case 0x18: // Signature Generator Control
case 0x19: // Signature Generator Result
case 0x1a: // Signature Generator Result
reg_index, reg_value);
#endif
break;
+ case 0x17: // Configuration Readback and Extended Control
+ s->sr[reg_index] = (s->sr[reg_index] & 0x38) | (reg_value & 0xc7);
+ cirrus_update_memory_access(s);
+ break;
default:
#ifdef DEBUG_CIRRUS
printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index,
return CIRRUS_HOOK_NOT_HANDLED;
case 0x05: // Standard VGA, Cirrus extended mode
s->gr[reg_index] = reg_value & 0x7f;
+ cirrus_update_memory_access(s);
break;
case 0x09: // bank offset #0
case 0x0A: // bank offset #1
+ s->gr[reg_index] = reg_value;
+ cirrus_update_bank_ptr(s, 0);
+ cirrus_update_bank_ptr(s, 1);
+ break;
case 0x0B:
s->gr[reg_index] = reg_value;
cirrus_update_bank_ptr(s, 0);
cirrus_update_bank_ptr(s, 1);
+ cirrus_update_memory_access(s);
break;
case 0x10: // BGCOLOR 0x0000ff00
case 0x11: // FGCOLOR 0x0000ff00
case 0x1a: // Miscellaneous Control
case 0x1b: // Extended Display Control
case 0x1c: // Sync Adjust and Genlock
+ case 0x1d: // Overlay Extended Control
s->cr[reg_index] = reg_value;
#ifdef DEBUG_CIRRUS
printf("cirrus: handled outport cr_index %02x, cr_value %02x\n",
case 0x26: // Attribute Controller Index Readback (R)
case 0x27: // Part ID (R)
break;
- case 0x1d: // Overlay Extended Control
case 0x25: // Part Status
default:
#ifdef DEBUG_CIRRUS
dst = s->vram_ptr + offset;
for (x = 0; x < 8; x++) {
if (val & 0x80) {
- *dst++ = s->cirrus_shadow_gr1;
+ *dst = s->cirrus_shadow_gr1;
} else if (mode == 5) {
- *dst++ = s->cirrus_shadow_gr0;
+ *dst = s->cirrus_shadow_gr0;
}
val <<= 1;
+ dst++;
}
cpu_physical_memory_set_dirty(s->vram_offset + offset);
cpu_physical_memory_set_dirty(s->vram_offset + offset + 7);
dst = s->vram_ptr + offset;
for (x = 0; x < 8; x++) {
if (val & 0x80) {
- *dst++ = s->cirrus_shadow_gr1;
- *dst++ = s->gr[0x11];
+ *dst = s->cirrus_shadow_gr1;
+ *(dst + 1) = s->gr[0x11];
} else if (mode == 5) {
- *dst++ = s->cirrus_shadow_gr0;
- *dst++ = s->gr[0x10];
+ *dst = s->cirrus_shadow_gr0;
+ *(dst + 1) = s->gr[0x10];
}
val <<= 1;
+ dst += 2;
}
cpu_physical_memory_set_dirty(s->vram_offset + offset);
cpu_physical_memory_set_dirty(s->vram_offset + offset + 15);
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;
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;
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) {
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) {
cirrus_linear_writel,
};
+static void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ addr &= s->cirrus_addr_mask;
+ *(s->vram_ptr + addr) = val;
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+}
+
+static void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ addr &= s->cirrus_addr_mask;
+ cpu_to_le16w((uint16_t *)(s->vram_ptr + addr), val);
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+}
+
+static void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ addr &= s->cirrus_addr_mask;
+ cpu_to_le32w((uint32_t *)(s->vram_ptr + addr), val);
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+}
+
/***************************************
*
* system to screen memory access
cirrus_linear_bitblt_writel,
};
+/* Compute the memory access functions */
+static void cirrus_update_memory_access(CirrusVGAState *s)
+{
+ unsigned mode;
+
+ if ((s->sr[0x17] & 0x44) == 0x44) {
+ goto generic_io;
+ } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
+ goto generic_io;
+ } else {
+ if ((s->gr[0x0B] & 0x14) == 0x14) {
+ goto generic_io;
+ } else if (s->gr[0x0B] & 0x02) {
+ goto generic_io;
+ }
+
+ mode = s->gr[0x05] & 0x7;
+ if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
+ s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
+ s->cirrus_linear_write[1] = cirrus_linear_mem_writew;
+ s->cirrus_linear_write[2] = cirrus_linear_mem_writel;
+ } else {
+ generic_io:
+ s->cirrus_linear_write[0] = cirrus_linear_writeb;
+ s->cirrus_linear_write[1] = cirrus_linear_writew;
+ s->cirrus_linear_write[2] = cirrus_linear_writel;
+ }
+ }
+}
+
+
/* I/O ports */
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
case 0x3c7:
val = s->dac_state;
break;
- case 0x3c9:
+ case 0x3c8:
+ val = s->dac_write_index;
+ s->cirrus_hidden_dac_lockindex = 0;
+ break;
+ case 0x3c9:
if (cirrus_hook_read_palette(s, &val))
break;
val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
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);
cirrus_mmio_writel,
};
+/* load/save state */
+
+static void cirrus_vga_save(QEMUFile *f, void *opaque)
+{
+ CirrusVGAState *s = opaque;
+
+ qemu_put_be32s(f, &s->latch);
+ qemu_put_8s(f, &s->sr_index);
+ qemu_put_buffer(f, s->sr, 256);
+ qemu_put_8s(f, &s->gr_index);
+ qemu_put_8s(f, &s->cirrus_shadow_gr0);
+ qemu_put_8s(f, &s->cirrus_shadow_gr1);
+ qemu_put_buffer(f, s->gr + 2, 254);
+ qemu_put_8s(f, &s->ar_index);
+ qemu_put_buffer(f, s->ar, 21);
+ qemu_put_be32s(f, &s->ar_flip_flop);
+ qemu_put_8s(f, &s->cr_index);
+ qemu_put_buffer(f, s->cr, 256);
+ qemu_put_8s(f, &s->msr);
+ qemu_put_8s(f, &s->fcr);
+ qemu_put_8s(f, &s->st00);
+ qemu_put_8s(f, &s->st01);
+
+ qemu_put_8s(f, &s->dac_state);
+ qemu_put_8s(f, &s->dac_sub_index);
+ qemu_put_8s(f, &s->dac_read_index);
+ qemu_put_8s(f, &s->dac_write_index);
+ qemu_put_buffer(f, s->dac_cache, 3);
+ qemu_put_buffer(f, s->palette, 768);
+
+ qemu_put_be32s(f, &s->bank_offset);
+
+ qemu_put_8s(f, &s->cirrus_hidden_dac_lockindex);
+ qemu_put_8s(f, &s->cirrus_hidden_dac_data);
+
+ qemu_put_be32s(f, &s->hw_cursor_x);
+ qemu_put_be32s(f, &s->hw_cursor_y);
+ /* XXX: we do not save the bitblt state - we assume we do not save
+ the state when the blitter is active */
+}
+
+static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
+{
+ CirrusVGAState *s = opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_be32s(f, &s->latch);
+ qemu_get_8s(f, &s->sr_index);
+ qemu_get_buffer(f, s->sr, 256);
+ qemu_get_8s(f, &s->gr_index);
+ qemu_get_8s(f, &s->cirrus_shadow_gr0);
+ qemu_get_8s(f, &s->cirrus_shadow_gr1);
+ s->gr[0x00] = s->cirrus_shadow_gr0 & 0x0f;
+ s->gr[0x01] = s->cirrus_shadow_gr1 & 0x0f;
+ qemu_get_buffer(f, s->gr + 2, 254);
+ qemu_get_8s(f, &s->ar_index);
+ qemu_get_buffer(f, s->ar, 21);
+ qemu_get_be32s(f, &s->ar_flip_flop);
+ qemu_get_8s(f, &s->cr_index);
+ qemu_get_buffer(f, s->cr, 256);
+ qemu_get_8s(f, &s->msr);
+ qemu_get_8s(f, &s->fcr);
+ qemu_get_8s(f, &s->st00);
+ qemu_get_8s(f, &s->st01);
+
+ qemu_get_8s(f, &s->dac_state);
+ qemu_get_8s(f, &s->dac_sub_index);
+ qemu_get_8s(f, &s->dac_read_index);
+ qemu_get_8s(f, &s->dac_write_index);
+ qemu_get_buffer(f, s->dac_cache, 3);
+ qemu_get_buffer(f, s->palette, 768);
+
+ qemu_get_be32s(f, &s->bank_offset);
+
+ qemu_get_8s(f, &s->cirrus_hidden_dac_lockindex);
+ qemu_get_8s(f, &s->cirrus_hidden_dac_data);
+
+ qemu_get_be32s(f, &s->hw_cursor_x);
+ qemu_get_be32s(f, &s->hw_cursor_y);
+
+ /* force refresh */
+ s->graphic_mode = -1;
+ cirrus_update_bank_ptr(s, 0);
+ cirrus_update_bank_ptr(s, 1);
+ return 0;
+}
+
/***************************************
*
* initialize
*
***************************************/
-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;
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 */
+ s->sr[0x1F] = 0x2d; // MemClock
+ s->gr[0x18] = 0x0f; // fastest memory configuration
+#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[0x1F] = 0x22; // MemClock
+ 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;
s->cirrus_linear_io_addr =
cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write,
s);
+ s->cirrus_linear_write = cpu_get_io_memory_write(s->cirrus_linear_io_addr);
+
/* I/O handler for LFB */
s->cirrus_linear_bitblt_io_addr =
cpu_register_io_memory(0, cirrus_linear_bitblt_read, cirrus_linear_bitblt_write,
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;
+
+ register_savevm("cirrus_vga", 0, 1, cirrus_vga_save, cirrus_vga_load, s);
}
/***************************************
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 */
}
s->cirrus_mmio_io_addr);
}
-void pci_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
+void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
unsigned long vga_ram_offset, int vga_ram_size)
{
PCICirrusVGAState *d;
device_id = CIRRUS_ID_CLGD5446;
/* setup PCI configuration registers */
- d = (PCICirrusVGAState *)pci_register_device("Cirrus VGA",
+ d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA",
sizeof(PCICirrusVGAState),
- 0, -1, NULL, NULL);
+ -1, NULL, NULL);
pci_conf = d->dev.config;
pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8);
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 */