#include "vga_int.h"
#include "pixel_ops.h"
#include "qemu-timer.h"
+#include "kvm.h"
//#define DEBUG_VGA
//#define DEBUG_VGA_MEM
static uint16_t expand2[256];
static uint8_t expand4to8[16];
-typedef VGACommonState VGAState;
-
static void vga_screen_dump(void *opaque, const char *filename);
static char *screen_dump_filename;
static DisplayChangeListener *screen_dump_dcl;
-static void vga_dumb_update_retrace_info(VGAState *s)
+static void vga_dumb_update_retrace_info(VGACommonState *s)
{
(void) s;
}
-static void vga_precise_update_retrace_info(VGAState *s)
+static void vga_precise_update_retrace_info(VGACommonState *s)
{
int htotal_chars;
int hretr_start_char;
r->total_chars = vtotal_lines * htotal_chars;
if (r->freq) {
- r->ticks_per_char = ticks_per_sec / (r->total_chars * r->freq);
+ r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
} else {
- r->ticks_per_char = ticks_per_sec / chars_per_sec;
+ r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
}
r->vstart = vretr_start_line;
"dots = %d\n"
"ticks/char = %lld\n"
"\n",
- (double) ticks_per_sec / (r->ticks_per_char * r->total_chars),
+ (double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
htotal_chars,
hretr_start_char,
hretr_skew_chars,
#endif
}
-static uint8_t vga_precise_retrace(VGAState *s)
+static uint8_t vga_precise_retrace(VGACommonState *s)
{
struct vga_precise_retrace *r = &s->retrace_info.precise;
uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
}
}
-static uint8_t vga_dumb_retrace(VGAState *s)
+static uint8_t vga_dumb_retrace(VGACommonState *s)
{
return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
}
#ifdef CONFIG_BOCHS_VBE
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
{
- VGAState *s = opaque;
+ VGACommonState *s = opaque;
uint32_t val;
val = s->vbe_index;
return val;
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
{
- VGAState *s = opaque;
+ VGACommonState *s = opaque;
uint32_t val;
- if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
+ if (s->vbe_index < VBE_DISPI_INDEX_NB) {
if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
switch(s->vbe_index) {
/* XXX: do not hardcode ? */
} else {
val = s->vbe_regs[s->vbe_index];
}
+ } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
+ val = s->vram_size / (64 * 1024);
} else {
val = 0;
}
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
{
- VGAState *s = opaque;
+ VGACommonState *s = opaque;
s->vbe_index = val;
}
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
{
- VGAState *s = opaque;
+ VGACommonState *s = opaque;
if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
#ifdef DEBUG_BOCHS_VBE
/* called for accesses between 0xa0000 and 0xc0000 */
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
{
- VGAState *s = opaque;
+ VGACommonState *s = opaque;
int memory_map_mode, plane;
uint32_t ret;
/* called for accesses between 0xa0000 and 0xc0000 */
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
- VGAState *s = opaque;
+ VGACommonState *s = opaque;
int memory_map_mode, plane, write_mode, b, func_select, mask;
uint32_t write_mask, bit_mask, set_mask;
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
const uint8_t *font_ptr, int h,
uint32_t fgcol, uint32_t bgcol, int dup9);
-typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
+typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
const uint8_t *s, int width);
#define DEPTH 8
}
/* return true if the palette was modified */
-static int update_palette16(VGAState *s)
+static int update_palette16(VGACommonState *s)
{
int full_update, i;
uint32_t v, col, *palette;
}
/* return true if the palette was modified */
-static int update_palette256(VGAState *s)
+static int update_palette256(VGACommonState *s)
{
int full_update, i;
uint32_t v, col, *palette;
return full_update;
}
-static void vga_get_offsets(VGAState *s,
+static void vga_get_offsets(VGACommonState *s,
uint32_t *pline_offset,
uint32_t *pstart_addr,
uint32_t *pline_compare)
}
/* update start_addr and line_offset. Return TRUE if modified */
-static int update_basic_params(VGAState *s)
+static int update_basic_params(VGACommonState *s)
{
int full_update;
uint32_t start_addr, line_offset, line_compare;
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
-static void vga_get_text_resolution(VGAState *s, int *pwidth, int *pheight,
+static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
int *pcwidth, int *pcheight)
{
int width, cwidth, height, cheight;
* - underline
* - flashing
*/
-static void vga_draw_text(VGAState *s, int full_update)
+static void vga_draw_text(VGACommonState *s, int full_update)
{
int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
- int cx_min, cx_max, linesize, x_incr;
+ int cx_min, cx_max, linesize, x_incr, line, line1;
uint32_t offset, fgcol, bgcol, v, cursor_offset;
- uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
+ uint8_t *d1, *d, *src, *dest, *cursor_ptr;
const uint8_t *font_ptr, *font_base[2];
int dup9, line_offset, depth_index;
uint32_t *palette;
full_update |= update_basic_params(s);
line_offset = s->line_offset;
- s1 = s->vram_ptr + (s->start_addr * 4);
vga_get_text_resolution(s, &width, &height, &cw, &cheight);
- x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
if ((height * width) > CH_ATTR_SIZE) {
/* better than nothing: exit if transient size is too big */
return;
dest = ds_get_data(s->ds);
linesize = ds_get_linesize(s->ds);
ch_attr_ptr = s->last_ch_attr;
+ line = 0;
+ offset = s->start_addr * 4;
for(cy = 0; cy < height; cy++) {
d1 = dest;
- src = s1;
+ src = s->vram_ptr + offset;
cx_min = width;
cx_max = -1;
for(cx = 0; cx < width; cx++) {
(cx_max - cx_min + 1) * cw, cheight);
}
dest += linesize * cheight;
- s1 += line_offset;
+ line1 = line + cheight;
+ offset += line_offset;
+ if (line < s->line_compare && line1 >= s->line_compare) {
+ offset = 0;
+ }
+ line = line1;
}
}
vga_draw_line32_16bgr,
};
-static int vga_get_bpp(VGAState *s)
+static int vga_get_bpp(VGACommonState *s)
{
int ret;
#ifdef CONFIG_BOCHS_VBE
return ret;
}
-static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
+static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
{
int width, height;
*pheight = height;
}
-void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
+void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
{
int y;
if (y1 >= VGA_MAX_HEIGHT)
}
}
-static void vga_sync_dirty_bitmap(VGAState *s)
+static void vga_sync_dirty_bitmap(VGACommonState *s)
{
if (s->map_addr)
cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
}
+
+#ifdef CONFIG_BOCHS_VBE
+ if (s->vbe_mapped) {
+ cpu_physical_sync_dirty_bitmap(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
+ VBE_DISPI_LFB_PHYSICAL_ADDRESS + s->vram_size);
+ }
+#endif
+
+}
+
+void vga_dirty_log_start(VGACommonState *s)
+{
+ if (kvm_enabled() && s->map_addr)
+ kvm_log_start(s->map_addr, s->map_end - s->map_addr);
+
+ if (kvm_enabled() && s->lfb_vram_mapped) {
+ kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
+ kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
+ }
+
+#ifdef CONFIG_BOCHS_VBE
+ if (kvm_enabled() && s->vbe_mapped) {
+ kvm_log_start(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
+ }
+#endif
+}
+
+void vga_dirty_log_stop(VGACommonState *s)
+{
+ if (kvm_enabled() && s->map_addr)
+ kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
+
+ if (kvm_enabled() && s->lfb_vram_mapped) {
+ kvm_log_stop(isa_mem_base + 0xa0000, 0x80000);
+ kvm_log_stop(isa_mem_base + 0xa8000, 0x80000);
+ }
+
+#ifdef CONFIG_BOCHS_VBE
+ if (kvm_enabled() && s->vbe_mapped) {
+ kvm_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
+ }
+#endif
+}
+
+void vga_dirty_log_restart(VGACommonState *s)
+{
+ vga_dirty_log_stop(s);
+ vga_dirty_log_start(s);
}
/*
* graphic modes
*/
-static void vga_draw_graphic(VGAState *s, int full_update)
+static void vga_draw_graphic(VGACommonState *s, int full_update)
{
int y1, y, update, linesize, y_start, double_scan, mask, depth;
int width, height, shift_control, line_offset, bwidth, bits;
memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
}
-static void vga_draw_blank(VGAState *s, int full_update)
+static void vga_draw_blank(VGACommonState *s, int full_update)
{
int i, w, val;
uint8_t *d;
static void vga_update_display(void *opaque)
{
- VGAState *s = opaque;
+ VGACommonState *s = opaque;
int full_update, graphic_mode;
if (ds_get_bits_per_pixel(s->ds) == 0) {
/* nothing to do */
} else {
- full_update = s->full_update;
- s->full_update = 0;
+ full_update = 0;
if (!(s->ar_index & 0x20)) {
graphic_mode = GMODE_BLANK;
} else {
/* force a full display refresh */
static void vga_invalidate_display(void *opaque)
{
- VGAState *s = opaque;
+ VGACommonState *s = opaque;
- s->full_update = 1;
+ s->last_width = -1;
+ s->last_height = -1;
}
void vga_common_reset(VGACommonState *s)
#ifdef CONFIG_BOCHS_VBE
s->vbe_index = 0;
memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
- s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
+ s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
s->vbe_start_addr = 0;
s->vbe_line_offset = 0;
s->vbe_bank_mask = (s->vram_size >> 16) - 1;
static void vga_reset(void *opaque)
{
- VGAState *s = opaque;
+ VGACommonState *s = opaque;
vga_common_reset(s);
}
* instead of doing a full vga_update_display() */
static void vga_update_text(void *opaque, console_ch_t *chardata)
{
- VGAState *s = opaque;
+ VGACommonState *s = opaque;
int graphic_mode, i, cursor_offset, cursor_visible;
int cw, cheight, width, height, size, c_min, c_max;
uint32_t *src;
vga_mem_writel,
};
-void vga_common_save(QEMUFile *f, void *opaque)
-{
- VGACommonState *s = opaque;
- int i;
-
- qemu_put_be32s(f, &s->latch);
- qemu_put_8s(f, &s->sr_index);
- qemu_put_buffer(f, s->sr, 8);
- qemu_put_8s(f, &s->gr_index);
- qemu_put_buffer(f, s->gr, 16);
- qemu_put_8s(f, &s->ar_index);
- qemu_put_buffer(f, s->ar, 21);
- 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_8s(f, &s->fcr);
- qemu_put_byte(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_be32(f, s->bank_offset);
-#ifdef CONFIG_BOCHS_VBE
- qemu_put_byte(f, 1);
- qemu_put_be16s(f, &s->vbe_index);
- for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
- qemu_put_be16s(f, &s->vbe_regs[i]);
- qemu_put_be32s(f, &s->vbe_start_addr);
- qemu_put_be32s(f, &s->vbe_line_offset);
- qemu_put_be32s(f, &s->vbe_bank_mask);
-#else
- qemu_put_byte(f, 0);
-#endif
-}
-
-int vga_common_load(QEMUFile *f, void *opaque, int version_id)
+static int vga_common_post_load(void *opaque, int version_id)
{
VGACommonState *s = opaque;
- int is_vbe, i;
-
- if (version_id > 2)
- return -EINVAL;
-
- qemu_get_be32s(f, &s->latch);
- qemu_get_8s(f, &s->sr_index);
- qemu_get_buffer(f, s->sr, 8);
- qemu_get_8s(f, &s->gr_index);
- qemu_get_buffer(f, s->gr, 16);
- qemu_get_8s(f, &s->ar_index);
- qemu_get_buffer(f, s->ar, 21);
- 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_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);
-
- s->bank_offset=qemu_get_be32(f);
- is_vbe = qemu_get_byte(f);
-#ifdef CONFIG_BOCHS_VBE
- if (!is_vbe)
- return -EINVAL;
- qemu_get_be16s(f, &s->vbe_index);
- for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
- qemu_get_be16s(f, &s->vbe_regs[i]);
- qemu_get_be32s(f, &s->vbe_start_addr);
- qemu_get_be32s(f, &s->vbe_line_offset);
- qemu_get_be32s(f, &s->vbe_bank_mask);
-#else
- if (is_vbe)
- return -EINVAL;
-#endif
/* force refresh */
s->graphic_mode = -1;
return 0;
}
+const VMStateDescription vmstate_vga_common = {
+ .name = "vga",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
+ .post_load = vga_common_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(latch, VGACommonState),
+ VMSTATE_UINT8(sr_index, VGACommonState),
+ VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
+ VMSTATE_UINT8(gr_index, VGACommonState),
+ VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
+ VMSTATE_UINT8(ar_index, VGACommonState),
+ VMSTATE_BUFFER(ar, VGACommonState),
+ VMSTATE_INT32(ar_flip_flop, VGACommonState),
+ VMSTATE_UINT8(cr_index, VGACommonState),
+ VMSTATE_BUFFER(cr, VGACommonState),
+ VMSTATE_UINT8(msr, VGACommonState),
+ VMSTATE_UINT8(fcr, VGACommonState),
+ VMSTATE_UINT8(st00, VGACommonState),
+ VMSTATE_UINT8(st01, VGACommonState),
+
+ VMSTATE_UINT8(dac_state, VGACommonState),
+ VMSTATE_UINT8(dac_sub_index, VGACommonState),
+ VMSTATE_UINT8(dac_read_index, VGACommonState),
+ VMSTATE_UINT8(dac_write_index, VGACommonState),
+ VMSTATE_BUFFER(dac_cache, VGACommonState),
+ VMSTATE_BUFFER(palette, VGACommonState),
+
+ VMSTATE_INT32(bank_offset, VGACommonState),
+ VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
+#ifdef CONFIG_BOCHS_VBE
+ VMSTATE_UINT16(vbe_index, VGACommonState),
+ VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
+ VMSTATE_UINT32(vbe_start_addr, VGACommonState),
+ VMSTATE_UINT32(vbe_line_offset, VGACommonState),
+ VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
+#endif
+ VMSTATE_END_OF_LIST()
+ }
+};
+
void vga_common_init(VGACommonState *s, int vga_ram_size)
{
int i, j, v, b;
expand4to8[i] = v;
}
+#ifdef CONFIG_BOCHS_VBE
+ s->is_vbe_vmstate = 1;
+#else
+ s->is_vbe_vmstate = 0;
+#endif
s->vram_offset = qemu_ram_alloc(vga_ram_size);
s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
s->vram_size = vga_ram_size;
s->update_retrace_info = vga_precise_update_retrace_info;
break;
}
- vga_reset(s);
}
/* used by both ISA and PCI */
-void vga_init(VGAState *s)
+void vga_init(VGACommonState *s)
{
int vga_io_memory;
qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
}
+void vga_init_vbe(VGACommonState *s)
+{
+#ifdef CONFIG_BOCHS_VBE
+ /* XXX: use optimized standard vga accesses */
+ cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
+ VGA_RAM_SIZE, s->vram_offset);
+ s->vbe_mapped = 1;
+#endif
+}
/********************************************************/
/* vga screen dump */
available */
static void vga_screen_dump(void *opaque, const char *filename)
{
- VGAState *s = opaque;
+ VGACommonState *s = opaque;
if (!screen_dump_dcl)
screen_dump_dcl = vga_screen_dump_init(s->ds);