/*
* QEMU Cirrus CLGD 54xx VGA Emulator.
- *
+ *
* Copyright (c) 2004 Fabrice Bellard
* Copyright (c) 2004 Makoto Suzuki (suzu)
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* Reference: Finn Thogersons' VGADOC4b
* available at http://home.worldonline.dk/~finth/
*/
-#include "vl.h"
+#include "hw.h"
+#include "pc.h"
+#include "pci.h"
+#include "console.h"
#include "vga_int.h"
+#include "kvm.h"
/*
* TODO:
- * - add support for WRITEMASK (GR2F)
+ * - destination write mask support not complete (bits 5..7)
* - optimize linear mappings
* - optimize bitblt functions
*/
#define CIRRUS_HOOK_NOT_HANDLED 0
#define CIRRUS_HOOK_HANDLED 1
+#define ABS(a) ((signed)(a) > 0 ? a : -a)
+
+#define BLTUNSAFE(s) \
+ ( \
+ ( /* check dst is within bounds */ \
+ (s)->cirrus_blt_height * ABS((s)->cirrus_blt_dstpitch) \
+ + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \
+ (s)->vram_size \
+ ) || \
+ ( /* check src is within bounds */ \
+ (s)->cirrus_blt_height * ABS((s)->cirrus_blt_srcpitch) \
+ + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \
+ (s)->vram_size \
+ ) \
+ )
+
struct CirrusVGAState;
typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
uint8_t * dst, const uint8_t * src,
} PCICirrusVGAState;
static uint8_t rop_to_index[256];
-
+
/***************************************
*
* prototypes.
cirrus_bitblt_rop_bkwd_notsrc_or_dst,
cirrus_bitblt_rop_bkwd_notsrc_and_notdst,
};
-
+
+#define TRANSP_ROP(name) {\
+ name ## _8,\
+ name ## _16,\
+ }
+#define TRANSP_NOP(func) {\
+ func,\
+ func,\
+ }
+
+static const cirrus_bitblt_rop_t cirrus_fwd_transp_rop[16][2] = {
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_0),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_dst),
+ TRANSP_NOP(cirrus_bitblt_rop_nop),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_notdst),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notdst),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_1),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_dst),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_xor_dst),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_dst),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_notdst),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_notxor_dst),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_notdst),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_dst),
+ TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_notdst),
+};
+
+static const cirrus_bitblt_rop_t cirrus_bkwd_transp_rop[16][2] = {
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_0),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_dst),
+ TRANSP_NOP(cirrus_bitblt_rop_nop),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_notdst),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notdst),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_1),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_dst),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_xor_dst),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_dst),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_notdst),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_notxor_dst),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_notdst),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_dst),
+ TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_notdst),
+};
+
#define ROP2(name) {\
name ## _8,\
name ## _16,\
s->cirrus_blt_fgcol = le16_to_cpu(color);
break;
case 3:
- s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 |
+ s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 |
(s->gr[0x11] << 8) | (s->gr[0x13] << 16);
break;
default:
s->cirrus_blt_bgcol = le16_to_cpu(color);
break;
case 3:
- s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 |
+ s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 |
(s->gr[0x10] << 8) | (s->gr[0x12] << 16);
break;
default:
for (y = 0; y < lines; y++) {
off_cur = off_begin;
- off_cur_end = off_cur + bytesperline;
+ off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
off_cur &= TARGET_PAGE_MASK;
while (off_cur < off_cur_end) {
cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
{
uint8_t *dst;
- dst = s->vram_ptr + s->cirrus_blt_dstaddr;
+ dst = s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
+
+ if (BLTUNSAFE(s))
+ return 0;
+
(*s->cirrus_rop) (s, dst, src,
- s->cirrus_blt_dstpitch, 0,
+ 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,
{
cirrus_fill_t rop_func;
+ if (BLTUNSAFE(s))
+ return 0;
rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
- rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr,
+ rop_func(s, s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
s->cirrus_blt_dstpitch,
s->cirrus_blt_width, s->cirrus_blt_height);
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
{
return cirrus_bitblt_common_patterncopy(s,
- s->vram_ptr +
- (s->cirrus_blt_srcaddr & ~7));
+ s->vram_ptr + ((s->cirrus_blt_srcaddr & ~7) &
+ s->cirrus_addr_mask));
}
-static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
+static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
{
- (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
- s->vram_ptr + s->cirrus_blt_srcaddr,
+ int sx, sy;
+ int dx, dy;
+ int width, height;
+ int depth;
+ int notify = 0;
+
+ depth = s->get_bpp((VGAState *)s) / 8;
+ s->get_resolution((VGAState *)s, &width, &height);
+
+ /* extra x, y */
+ sx = (src % (width * depth)) / depth;
+ sy = (src / (width * depth));
+ dx = (dst % (width *depth)) / depth;
+ dy = (dst / (width * depth));
+
+ /* normalize width */
+ w /= depth;
+
+ /* if we're doing a backward copy, we have to adjust
+ our x/y to be the upper left corner (instead of the lower
+ right corner) */
+ if (s->cirrus_blt_dstpitch < 0) {
+ sx -= (s->cirrus_blt_width / depth) - 1;
+ dx -= (s->cirrus_blt_width / depth) - 1;
+ sy -= s->cirrus_blt_height - 1;
+ dy -= s->cirrus_blt_height - 1;
+ }
+
+ /* are we in the visible portion of memory? */
+ if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
+ (sx + w) <= width && (sy + h) <= height &&
+ (dx + w) <= width && (dy + h) <= height) {
+ notify = 1;
+ }
+
+ /* make to sure only copy if it's a plain copy ROP */
+ if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src &&
+ *s->cirrus_rop != cirrus_bitblt_rop_bkwd_src)
+ notify = 0;
+
+ /* we have to flush all pending changes so that the copy
+ is generated at the appropriate moment in time */
+ if (notify)
+ vga_hw_update();
+
+ (*s->cirrus_rop) (s, s->vram_ptr +
+ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
+ s->vram_ptr +
+ (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
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);
+
+ if (notify)
+ qemu_console_copy(s->console,
+ sx, sy, dx, dy,
+ s->cirrus_blt_width / depth,
+ s->cirrus_blt_height);
+
+ /* we don't have to notify the display that this portion has
+ changed since qemu_console_copy implies this */
+
+ if (!notify)
+ cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+ s->cirrus_blt_dstpitch, s->cirrus_blt_width,
+ s->cirrus_blt_height);
+}
+
+static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
+{
+ if (BLTUNSAFE(s))
+ return 0;
+
+ if (s->ds->dpy_copy) {
+ cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
+ s->cirrus_blt_srcaddr - s->start_addr,
+ s->cirrus_blt_width, s->cirrus_blt_height);
+ } else {
+ (*s->cirrus_rop) (s, s->vram_ptr +
+ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
+ s->vram_ptr +
+ (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
+ s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
+ 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);
+ }
+
return 1;
}
{
int copy_count;
uint8_t *end_ptr;
-
+
if (s->cirrus_srccounter > 0) {
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf);
} else {
/* at least one scan line */
do {
- (*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr,
- s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
+ (*s->cirrus_rop)(s, s->vram_ptr +
+ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
+ s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
s->cirrus_blt_width, 1);
s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
} else {
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth;
- if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)
+ if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)
s->cirrus_blt_srcpitch = ((w + 31) >> 5);
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;
}
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",
- blt_rop,
+ 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_width,
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) {
}
if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
- (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST |
+ (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST |
CIRRUS_BLTMODE_TRANSPARENTCOMP |
- CIRRUS_BLTMODE_PATTERNCOPY |
- CIRRUS_BLTMODE_COLOREXPAND)) ==
+ CIRRUS_BLTMODE_PATTERNCOPY |
+ CIRRUS_BLTMODE_COLOREXPAND)) ==
(CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
cirrus_bitblt_fgcol(s);
cirrus_bitblt_solidfill(s, blt_rop);
} else {
- if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND |
- CIRRUS_BLTMODE_PATTERNCOPY)) ==
+ if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND |
+ CIRRUS_BLTMODE_PATTERNCOPY)) ==
CIRRUS_BLTMODE_COLOREXPAND) {
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
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;
- s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
- s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]];
- } else {
- s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]];
- }
- }
-
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
+ if (s->cirrus_blt_pixelwidth > 2) {
+ printf("src transparent without colorexpand must be 8bpp or 16bpp\n");
+ 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_bkwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+ } else {
+ s->cirrus_rop = cirrus_fwd_transp_rop[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;
+ s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
+ s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]];
+ } else {
+ s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]];
+ }
+ }
+ }
// setup bitblt engine.
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
if (!cirrus_bitblt_cputovideo(s))
*
***************************************/
-static void cirrus_get_offsets(VGAState *s1,
- uint32_t *pline_offset,
- uint32_t *pstart_addr)
+static void cirrus_get_offsets(VGAState *s1,
+ uint32_t *pline_offset,
+ uint32_t *pstart_addr,
+ uint32_t *pline_compare)
{
CirrusVGAState * s = (CirrusVGAState *)s1;
- uint32_t start_addr;
- uint32_t line_offset;
+ uint32_t start_addr, line_offset, line_compare;
line_offset = s->cr[0x13]
| ((s->cr[0x1b] & 0x10) << 4);
| ((s->cr[0x1b] & 0x0c) << 15)
| ((s->cr[0x1d] & 0x80) << 12);
*pstart_addr = start_addr;
+
+ line_compare = s->cr[0x18] |
+ ((s->cr[0x07] & 0x10) << 4) |
+ ((s->cr[0x09] & 0x40) << 3);
+ *pline_compare = line_compare;
}
static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
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) |
+ height = s->cr[0x12] |
+ ((s->cr[0x07] & 0x02) << 7) |
((s->cr[0x07] & 0x40) << 3);
height = (height + 1);
/* interlace support */
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) {
}
if (limit > 0) {
+ /* Thinking about changing bank base? First, drop the dirty bitmap information
+ * on the current location, otherwise we lose this pointer forever */
+ if (s->lfb_vram_mapped) {
+ target_phys_addr_t base_addr = isa_mem_base + 0xa0000 + bank_index * 0x8000;
+ cpu_physical_sync_dirty_bitmap(base_addr, base_addr + 0x8000);
+ }
s->cirrus_bank_base[bank_index] = offset;
s->cirrus_bank_limit[bank_index] = limit;
} else {
s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5);
break;
case 0x07: // Extended Sequencer Mode
+ cirrus_update_memory_access(s);
case 0x08: // EEPROM Control
case 0x09: // Scratch Register 0
case 0x0a: // Scratch Register 1
#endif
break;
case 0x17: // Configuration Readback and Extended Control
- s->sr[reg_index] = reg_value;
+ s->sr[reg_index] = (s->sr[reg_index] & 0x38) | (reg_value & 0xc7);
cirrus_update_memory_access(s);
break;
default:
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 0x0B:
s->gr[reg_index] = reg_value;
case 0x17: // Standard VGA
case 0x18: // Standard VGA
return CIRRUS_HOOK_NOT_HANDLED;
+ case 0x24: // Attribute Controller Toggle Readback (R)
+ *reg_value = (s->ar_flip_flop << 7);
+ break;
case 0x19: // Interlace End
case 0x1a: // Miscellaneous Control
case 0x1b: // Extended Display Control
case 0x1c: // Sync Adjust and Genlock
case 0x1d: // Overlay Extended Control
case 0x22: // Graphics Data Latches Readback (R)
- case 0x24: // Attribute Controller Toggle Readback (R)
case 0x25: // Part Status
case 0x27: // Part ID (R)
*reg_value = s->cr[reg_index];
unsigned val = mem_value;
uint8_t *dst;
- dst = s->vram_ptr + offset;
+ dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
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);
unsigned val = mem_value;
uint8_t *dst;
- dst = s->vram_ptr + offset;
+ dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
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);
return v;
}
-static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
+static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
uint32_t mem_value)
{
CirrusVGAState *s = opaque;
static inline void invalidate_cursor1(CirrusVGAState *s)
{
if (s->last_hw_cursor_size) {
- vga_invalidate_scanlines((VGAState *)s,
+ vga_invalidate_scanlines((VGAState *)s,
s->last_hw_cursor_y + s->last_hw_cursor_y_start,
s->last_hw_cursor_y + s->last_hw_cursor_y_end);
}
s->last_hw_cursor_y != s->hw_cursor_y) {
invalidate_cursor1(s);
-
+
s->last_hw_cursor_size = size;
s->last_hw_cursor_x = s->hw_cursor_x;
s->last_hw_cursor_y = s->hw_cursor_y;
unsigned int color0, color1;
const uint8_t *palette, *src;
uint32_t content;
-
- if (!(s->sr[0x12] & CIRRUS_CURSOR_SHOW))
+
+ if (!(s->sr[0x12] & CIRRUS_CURSOR_SHOW))
return;
/* fast test to see if the cursor intersects with the scan line */
if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
if (scr_y < s->hw_cursor_y ||
scr_y >= (s->hw_cursor_y + h))
return;
-
+
src = s->vram_ptr + s->real_vram_size - 16 * 1024;
if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
src += (s->sr[0x13] & 0x3c) * 256;
x2 = s->last_scr_width;
w = x2 - x1;
palette = s->cirrus_hidden_palette;
- color0 = s->rgb_to_pixel(c6_to_8(palette[0x0 * 3]),
- c6_to_8(palette[0x0 * 3 + 1]),
+ color0 = s->rgb_to_pixel(c6_to_8(palette[0x0 * 3]),
+ c6_to_8(palette[0x0 * 3 + 1]),
c6_to_8(palette[0x0 * 3 + 2]));
- color1 = s->rgb_to_pixel(c6_to_8(palette[0xf * 3]),
- c6_to_8(palette[0xf * 3 + 1]),
+ color1 = s->rgb_to_pixel(c6_to_8(palette[0xf * 3]),
+ c6_to_8(palette[0xf * 3 + 1]),
c6_to_8(palette[0xf * 3 + 2]));
- bpp = ((s->ds->depth + 7) >> 3);
+ bpp = ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
d1 += x1 * bpp;
- switch(s->ds->depth) {
+ switch(ds_get_bits_per_pixel(s->ds)) {
default:
break;
case 8:
addr &= s->cirrus_addr_mask;
- if (((s->sr[0x17] & 0x44) == 0x44) &&
+ 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);
unsigned mode;
addr &= s->cirrus_addr_mask;
-
- if (((s->sr[0x17] & 0x44) == 0x44) &&
+
+ 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);
cirrus_linear_bitblt_writel,
};
+static void map_linear_vram(CirrusVGAState *s)
+{
+
+ if (!s->map_addr && s->lfb_addr && s->lfb_end) {
+ s->map_addr = s->lfb_addr;
+ s->map_end = s->lfb_end;
+ cpu_register_physical_memory(s->map_addr, s->map_end - s->map_addr, s->vram_offset);
+ vga_dirty_log_start((VGAState *)s);
+ }
+
+ if (!s->map_addr)
+ return;
+
+ s->lfb_vram_mapped = 0;
+
+ if (!(s->cirrus_srcptr != s->cirrus_srcptr_end)
+ && !((s->sr[0x07] & 0x01) == 0)
+ && !((s->gr[0x0B] & 0x14) == 0x14)
+ && !(s->gr[0x0B] & 0x02)) {
+
+ cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000,
+ (s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM);
+ cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000,
+ (s->vram_offset + s->cirrus_bank_base[1]) | IO_MEM_RAM);
+
+ s->lfb_vram_mapped = 1;
+ vga_dirty_log_start((VGAState *)s);
+ }
+ else {
+ cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000, s->vga_io_memory);
+ cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000, s->vga_io_memory);
+ }
+
+}
+
+static void unmap_linear_vram(CirrusVGAState *s)
+{
+ if (s->map_addr && s->lfb_addr && s->lfb_end) {
+ vga_dirty_log_stop((VGAState *)s);
+ s->map_addr = s->map_end = 0;
+ }
+
+ cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
+ s->vga_io_memory);
+}
+
/* Compute the memory access functions */
static void cirrus_update_memory_access(CirrusVGAState *s)
{
} else if (s->gr[0x0B] & 0x02) {
goto generic_io;
}
-
+
mode = s->gr[0x05] & 0x7;
if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
+ map_linear_vram(s);
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:
+ unmap_linear_vram(s);
s->cirrus_linear_write[0] = cirrus_linear_writeb;
s->cirrus_linear_write[1] = cirrus_linear_writew;
s->cirrus_linear_write[2] = cirrus_linear_writel;
case 0x3ba:
case 0x3da:
/* just toggle to fool polling */
- s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
- val = s->st01;
+ val = s->st01 = s->retrace((VGAState *) s);
s->ar_flip_flop = 0;
break;
default:
break;
case 0x3c2:
s->msr = val & ~0x10;
+ s->update_retrace_info((VGAState *) s);
break;
case 0x3c4:
s->sr_index = val;
printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
#endif
s->sr[s->sr_index] = val & sr_mask[s->sr_index];
+ if (s->sr_index == 1) s->update_retrace_info((VGAState *) s);
break;
case 0x3c6:
cirrus_write_hidden_dac(s, 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);
case 0x09:
case 0x0c:
case 0x0d:
- case 0x12: /* veritcal display end */
+ case 0x12: /* vertical display end */
s->cr[s->cr_index] = val;
break;
s->cr[s->cr_index] = val;
break;
}
+
+ switch(s->cr_index) {
+ case 0x00:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x11:
+ case 0x17:
+ s->update_retrace_info((VGAState *) s);
+ break;
+ }
break;
case 0x3ba:
case 0x3da:
{
CirrusVGAState *s = opaque;
+ if (s->pci_dev)
+ pci_device_save(s->pci_dev, f);
+
qemu_put_be32s(f, &s->latch);
qemu_put_8s(f, &s->sr_index);
qemu_put_buffer(f, s->sr, 256);
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_be32(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_buffer(f, s->dac_cache, 3);
qemu_put_buffer(f, s->palette, 768);
- qemu_put_be32s(f, &s->bank_offset);
+ qemu_put_be32(f, s->bank_offset);
qemu_put_8s(f, &s->cirrus_hidden_dac_lockindex);
qemu_put_8s(f, &s->cirrus_hidden_dac_data);
static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
{
CirrusVGAState *s = opaque;
+ int ret;
- if (version_id != 1)
+ if (version_id > 2)
return -EINVAL;
+ if (s->pci_dev && version_id >= 2) {
+ ret = pci_device_load(s->pci_dev, f);
+ if (ret < 0)
+ return ret;
+ }
+
qemu_get_be32s(f, &s->latch);
qemu_get_8s(f, &s->sr_index);
qemu_get_buffer(f, s->sr, 256);
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);
+ s->ar_flip_flop=qemu_get_be32(f);
qemu_get_8s(f, &s->cr_index);
qemu_get_buffer(f, s->cr, 256);
qemu_get_8s(f, &s->msr);
qemu_get_buffer(f, s->dac_cache, 3);
qemu_get_buffer(f, s->palette, 768);
- qemu_get_be32s(f, &s->bank_offset);
+ s->bank_offset=qemu_get_be32(f);
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);
+ cirrus_update_memory_access(s);
/* force refresh */
s->graphic_mode = -1;
cirrus_update_bank_ptr(s, 0);
static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
{
- int vga_io_memory, i;
+ int i;
static int inited;
if (!inited) {
register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
- vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read,
+ s->vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read,
cirrus_vga_mem_write, s);
- cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
- vga_io_memory);
+ cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
+ s->vga_io_memory);
s->sr[0x06] = 0x0f;
if (device_id == CIRRUS_ID_CLGD5446) {
} else {
s->sr[0x1F] = 0x22; // MemClock
s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
- if (is_pci)
+ if (is_pci)
s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
else
s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
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);
+ register_savevm("cirrus_vga", 0, 2, cirrus_vga_save, cirrus_vga_load, s);
}
/***************************************
*
***************************************/
-void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
- unsigned long vga_ram_offset, int vga_ram_size)
+void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
+ ram_addr_t vga_ram_offset, int vga_ram_size)
{
CirrusVGAState *s;
s = qemu_mallocz(sizeof(CirrusVGAState));
-
- vga_common_init((VGAState *)s,
+
+ vga_common_init((VGAState *)s,
ds, vga_ram_base, vga_ram_offset, vga_ram_size);
cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0);
+ s->console = graphic_console_init(s->ds, s->update, s->invalidate,
+ s->screen_dump, s->text_update, s);
/* XXX ISA-LFB support */
}
s->cirrus_linear_io_addr);
cpu_register_physical_memory(addr + 0x1000000, 0x400000,
s->cirrus_linear_bitblt_io_addr);
+
+ s->map_addr = s->map_end = 0;
+ s->lfb_addr = addr & TARGET_PAGE_MASK;
+ s->lfb_end = ((addr + VGA_RAM_SIZE) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
+ /* account for overflow */
+ if (s->lfb_end < addr + VGA_RAM_SIZE)
+ s->lfb_end = addr + VGA_RAM_SIZE;
}
static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
s->cirrus_mmio_io_addr);
}
-void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
- unsigned long vga_ram_offset, int vga_ram_size)
+void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
+ ram_addr_t vga_ram_offset, int vga_ram_size)
{
PCICirrusVGAState *d;
uint8_t *pci_conf;
CirrusVGAState *s;
int device_id;
-
+
device_id = CIRRUS_ID_CLGD5446;
/* setup PCI configuration registers */
- d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA",
- sizeof(PCICirrusVGAState),
+ d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA",
+ sizeof(PCICirrusVGAState),
-1, NULL, NULL);
pci_conf = d->dev.config;
pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
/* setup VGA */
s = &d->cirrus_vga;
- vga_common_init((VGAState *)s,
+ vga_common_init((VGAState *)s,
ds, vga_ram_base, vga_ram_offset, vga_ram_size);
cirrus_init_common(s, device_id, 1);
+ s->console = graphic_console_init(s->ds, s->update, s->invalidate,
+ s->screen_dump, s->text_update, s);
+
+ s->pci_dev = (PCIDevice *)d;
+
/* setup memory space */
/* memory #0 LFB */
/* memory #1 memory-mapped I/O */