X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/487414f1cbd638beb0227c7da71fe7b8a821e155..609c1daced7f444f9f6569bba72d6a56a697ac95:/hw/vga.c diff --git a/hw/vga.c b/hw/vga.c index 98c2234f6b..6a1a0597d5 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -38,33 +38,33 @@ /* force some bits to zero */ const uint8_t sr_mask[8] = { - (uint8_t)~0xfc, - (uint8_t)~0xc2, - (uint8_t)~0xf0, - (uint8_t)~0xc0, - (uint8_t)~0xf1, - (uint8_t)~0xff, - (uint8_t)~0xff, - (uint8_t)~0x00, + 0x03, + 0x3d, + 0x0f, + 0x3f, + 0x0e, + 0x00, + 0x00, + 0xff, }; const uint8_t gr_mask[16] = { - (uint8_t)~0xf0, /* 0x00 */ - (uint8_t)~0xf0, /* 0x01 */ - (uint8_t)~0xf0, /* 0x02 */ - (uint8_t)~0xe0, /* 0x03 */ - (uint8_t)~0xfc, /* 0x04 */ - (uint8_t)~0x84, /* 0x05 */ - (uint8_t)~0xf0, /* 0x06 */ - (uint8_t)~0xf0, /* 0x07 */ - (uint8_t)~0x00, /* 0x08 */ - (uint8_t)~0xff, /* 0x09 */ - (uint8_t)~0xff, /* 0x0a */ - (uint8_t)~0xff, /* 0x0b */ - (uint8_t)~0xff, /* 0x0c */ - (uint8_t)~0xff, /* 0x0d */ - (uint8_t)~0xff, /* 0x0e */ - (uint8_t)~0xff, /* 0x0f */ + 0x0f, /* 0x00 */ + 0x0f, /* 0x01 */ + 0x0f, /* 0x02 */ + 0x1f, /* 0x03 */ + 0x03, /* 0x04 */ + 0x7b, /* 0x05 */ + 0x0f, /* 0x06 */ + 0x0f, /* 0x07 */ + 0xff, /* 0x08 */ + 0x00, /* 0x09 */ + 0x00, /* 0x0a */ + 0x00, /* 0x0b */ + 0x00, /* 0x0c */ + 0x00, /* 0x0d */ + 0x00, /* 0x0e */ + 0x00, /* 0x0f */ }; #define cbswap_32(__x) \ @@ -74,19 +74,19 @@ const uint8_t gr_mask[16] = { (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )) -#ifdef WORDS_BIGENDIAN +#ifdef HOST_WORDS_BIGENDIAN #define PAT(x) cbswap_32(x) #else #define PAT(x) (x) #endif -#ifdef WORDS_BIGENDIAN +#ifdef HOST_WORDS_BIGENDIAN #define BIG 1 #else #define BIG 0 #endif -#ifdef WORDS_BIGENDIAN +#ifdef HOST_WORDS_BIGENDIAN #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff) #else #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff) @@ -113,7 +113,7 @@ static const uint32_t mask16[16] = { #undef PAT -#ifdef WORDS_BIGENDIAN +#ifdef HOST_WORDS_BIGENDIAN #define PAT(x) (x) #else #define PAT(x) cbswap_32(x) @@ -150,13 +150,15 @@ static uint16_t expand2[256]; static uint8_t expand4to8[16]; 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; @@ -201,9 +203,9 @@ static void vga_precise_update_retrace_info(VGAState *s) 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; @@ -229,7 +231,7 @@ static void vga_precise_update_retrace_info(VGAState *s) "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, @@ -247,7 +249,7 @@ static void vga_precise_update_retrace_info(VGAState *s) #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); @@ -276,19 +278,28 @@ static uint8_t vga_precise_retrace(VGAState *s) } } -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); } -static uint32_t vga_ioport_read(void *opaque, uint32_t addr) +int vga_ioport_invalid(VGACommonState *s, uint32_t addr) { - VGAState *s = opaque; + if (s->msr & MSR_COLOR_EMULATION) { + /* Color */ + return (addr >= 0x3b0 && addr <= 0x3bf); + } else { + /* Monochrome */ + return (addr >= 0x3d0 && addr <= 0x3df); + } +} + +uint32_t vga_ioport_read(void *opaque, uint32_t addr) +{ + VGACommonState *s = opaque; int val, index; - /* check port range access depending on color/monochrome mode */ - if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) || - (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) { + if (vga_ioport_invalid(s, addr)) { val = 0xff; } else { switch(addr) { @@ -321,9 +332,9 @@ static uint32_t vga_ioport_read(void *opaque, uint32_t addr) case 0x3c7: val = s->dac_state; break; - case 0x3c8: - val = s->dac_write_index; - break; + case 0x3c8: + val = s->dac_write_index; + break; case 0x3c9: val = s->palette[s->dac_read_index * 3 + s->dac_sub_index]; if (++s->dac_sub_index == 3) { @@ -374,16 +385,15 @@ static uint32_t vga_ioport_read(void *opaque, uint32_t addr) return val; } -static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) +void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) { - VGAState *s = opaque; + VGACommonState *s = opaque; int index; /* check port range access depending on color/monochrome mode */ - if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) || - (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) + if (vga_ioport_invalid(s, addr)) { return; - + } #ifdef DEBUG_VGA printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val); #endif @@ -477,19 +487,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); return; } - switch(s->cr_index) { - case 0x01: /* horizontal display end */ - case 0x07: - case 0x09: - case 0x0c: - case 0x0d: - case 0x12: /* vertical display end */ - s->cr[s->cr_index] = val; - break; - default: - s->cr[s->cr_index] = val; - break; - } + s->cr[s->cr_index] = val; switch(s->cr_index) { case 0x00: @@ -513,7 +511,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) #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; @@ -521,7 +519,7 @@ static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr) 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) { @@ -555,13 +553,13 @@ static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr) 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 @@ -707,7 +705,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) /* 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; @@ -794,12 +792,12 @@ static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr) /* 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; #ifdef DEBUG_VGA_MEM - printf("vga: [0x%x] = 0x%02x\n", addr, val); + printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val); #endif /* convert to VGA memory offset */ memory_map_mode = (s->gr[6] >> 2) & 3; @@ -832,7 +830,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) if (s->sr[2] & mask) { s->vram_ptr[addr] = val; #ifdef DEBUG_VGA_MEM - printf("vga: chain4: [0x%x]\n", addr); + printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr); #endif s->plane_updated |= mask; /* only used to detect font change */ cpu_physical_memory_set_dirty(s->vram_offset + addr); @@ -845,7 +843,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) addr = ((addr & ~1) << 1) | plane; s->vram_ptr[addr] = val; #ifdef DEBUG_VGA_MEM - printf("vga: odd/even: [0x%x]\n", addr); + printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr); #endif s->plane_updated |= mask; /* only used to detect font change */ cpu_physical_memory_set_dirty(s->vram_offset + addr); @@ -919,10 +917,10 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | (val & write_mask); #ifdef DEBUG_VGA_MEM - printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", - addr * 4, write_mask, val); + printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n", + addr * 4, write_mask, val); #endif - cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2)); + cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2)); } } @@ -958,7 +956,7 @@ typedef void vga_draw_glyph8_func(uint8_t *d, int linesize, 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 @@ -1043,7 +1041,7 @@ static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsign } /* 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; @@ -1069,7 +1067,7 @@ static int update_palette16(VGAState *s) } /* 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; @@ -1096,7 +1094,7 @@ static int update_palette256(VGAState *s) 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) @@ -1128,7 +1126,7 @@ static void vga_get_offsets(VGAState *s, } /* 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; @@ -1161,7 +1159,10 @@ static inline int get_depth_index(DisplayState *s) case 16: return 2; case 32: - return 3; + if (is_surface_bgr(s->surface)) + return 4; + else + return 3; } } @@ -1214,7 +1215,7 @@ static const uint8_t cursor_glyph[32 * 4] = { 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; @@ -1263,12 +1264,12 @@ static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = { * - 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; @@ -1276,8 +1277,6 @@ static void vga_draw_text(VGAState *s, int full_update) vga_draw_glyph8_func *vga_draw_glyph8; vga_draw_glyph9_func *vga_draw_glyph9; - vga_dirty_log_stop(s); - /* compute font data address (in plane 2) */ v = s->sr[3]; offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2; @@ -1302,10 +1301,8 @@ static void vga_draw_text(VGAState *s, int full_update) 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; @@ -1355,9 +1352,11 @@ static void vga_draw_text(VGAState *s, int full_update) 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++) { @@ -1368,7 +1367,7 @@ static void vga_draw_text(VGAState *s, int full_update) if (cx > cx_max) cx_max = cx; *ch_attr_ptr = ch_attr; -#ifdef WORDS_BIGENDIAN +#ifdef HOST_WORDS_BIGENDIAN ch = ch_attr >> 8; cattr = ch_attr & 0xff; #else @@ -1420,7 +1419,12 @@ static void vga_draw_text(VGAState *s, int full_update) (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; } } @@ -1520,7 +1524,7 @@ static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = { vga_draw_line32_16bgr, }; -static int vga_get_bpp(VGAState *s) +static int vga_get_bpp(VGACommonState *s) { int ret; #ifdef CONFIG_BOCHS_VBE @@ -1534,7 +1538,7 @@ static int vga_get_bpp(VGAState *s) 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; @@ -1555,7 +1559,7 @@ static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight) *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) @@ -1567,7 +1571,7 @@ void vga_invalidate_scanlines(VGAState *s, int y1, int y2) } } -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); @@ -1576,16 +1580,64 @@ static void vga_sync_dirty_bitmap(VGAState *s) 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, page_min, page_max, linesize, y_start, double_scan, mask, depth; - int width, height, shift_control, line_offset, page0, page1, bwidth, bits; + int y1, y, update, linesize, y_start, double_scan, mask, depth; + int width, height, shift_control, line_offset, bwidth, bits; + ram_addr_t page0, page1, page_min, page_max; int disp_width, multi_scan, multi_run; uint8_t *d; uint32_t v, addr1, addr; @@ -1616,28 +1668,34 @@ static void vga_draw_graphic(VGAState *s, int full_update) s->double_scan = double_scan; } + if (shift_control == 0) { + if (s->sr[0x01] & 8) { + disp_width <<= 1; + } + } else if (shift_control == 1) { + if (s->sr[0x01] & 8) { + disp_width <<= 1; + } + } + depth = s->get_bpp(s); if (s->line_offset != s->last_line_offset || disp_width != s->last_width || height != s->last_height || s->last_depth != depth) { -#if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) +#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) if (depth == 16 || depth == 32) { #else if (depth == 32) { #endif - if (is_graphic_console()) { - qemu_free_displaysurface(s->ds->surface); - s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth, - s->line_offset, - s->vram_ptr + (s->start_addr * 4)); -#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) - s->ds->surface->pf = qemu_different_endianness_pixelformat(depth); + qemu_free_displaysurface(s->ds); + s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth, + s->line_offset, + s->vram_ptr + (s->start_addr * 4)); +#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) + s->ds->surface->pf = qemu_different_endianness_pixelformat(depth); #endif - dpy_resize(s->ds); - } else { - qemu_console_resize(s->ds, disp_width, height); - } + dpy_resize(s->ds); } else { qemu_console_resize(s->ds, disp_width, height); } @@ -1648,7 +1706,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) s->last_line_offset = s->line_offset; s->last_depth = depth; full_update = 1; - } else if (is_graphic_console() && is_buffer_shared(s->ds->surface) && + } else if (is_buffer_shared(s->ds->surface) && (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) { s->ds->surface->data = s->vram_ptr + (s->start_addr * 4); dpy_setdata(s->ds); @@ -1661,7 +1719,6 @@ static void vga_draw_graphic(VGAState *s, int full_update) full_update |= update_palette16(s); if (s->sr[0x01] & 8) { v = VGA_DRAW_LINE4D2; - disp_width <<= 1; } else { v = VGA_DRAW_LINE4; } @@ -1670,7 +1727,6 @@ static void vga_draw_graphic(VGAState *s, int full_update) full_update |= update_palette16(s); if (s->sr[0x01] & 8) { v = VGA_DRAW_LINE2D2; - disp_width <<= 1; } else { v = VGA_DRAW_LINE2; } @@ -1719,8 +1775,8 @@ static void vga_draw_graphic(VGAState *s, int full_update) addr1 = (s->start_addr * 4); bwidth = (width * bits + 7) / 8; y_start = -1; - page_min = 0x7fffffff; - page_max = -1; + page_min = -1; + page_max = 0; d = ds_get_data(s->ds); linesize = ds_get_linesize(s->ds); y1 = 0; @@ -1787,14 +1843,14 @@ static void vga_draw_graphic(VGAState *s, int full_update) disp_width, y - y_start); } /* reset modified pages */ - if (page_max != -1) { + if (page_max >= page_min) { cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE, VGA_DIRTY_FLAG); } 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; @@ -1803,7 +1859,6 @@ static void vga_draw_blank(VGAState *s, int full_update) return; if (s->last_scr_width <= 0 || s->last_scr_height <= 0) return; - vga_dirty_log_stop(s); s->rgb_to_pixel = rgb_to_pixel_dup_table[get_depth_index(s->ds)]; @@ -1827,7 +1882,7 @@ static void vga_draw_blank(VGAState *s, int full_update) static void vga_update_display(void *opaque) { - VGAState *s = (VGAState *)opaque; + VGACommonState *s = opaque; int full_update, graphic_mode; if (ds_get_bits_per_pixel(s->ds) == 0) { @@ -1861,16 +1916,14 @@ static void vga_update_display(void *opaque) /* force a full display refresh */ static void vga_invalidate_display(void *opaque) { - VGAState *s = (VGAState *)opaque; + VGACommonState *s = opaque; s->last_width = -1; s->last_height = -1; } -void vga_reset(void *opaque) +void vga_common_reset(VGACommonState *s) { - VGAState *s = (VGAState *) opaque; - s->lfb_addr = 0; s->lfb_end = 0; s->map_addr = 0; @@ -1936,6 +1989,12 @@ void vga_reset(void *opaque) } } +static void vga_reset(void *opaque) +{ + VGACommonState *s = opaque; + vga_common_reset(s); +} + #define TEXTMODE_X(x) ((x) % width) #define TEXTMODE_Y(x) ((x) / width) #define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \ @@ -1944,7 +2003,7 @@ void vga_reset(void *opaque) * instead of doing a full vga_update_display() */ static void vga_update_text(void *opaque, console_ch_t *chardata) { - VGAState *s = (VGAState *) 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; @@ -2102,165 +2161,70 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) dpy_update(s->ds, 0, 0, s->last_width, height); } -static CPUReadMemoryFunc *vga_mem_read[3] = { +CPUReadMemoryFunc * const vga_mem_read[3] = { vga_mem_readb, vga_mem_readw, vga_mem_readl, }; -static CPUWriteMemoryFunc *vga_mem_write[3] = { +CPUWriteMemoryFunc * const vga_mem_write[3] = { vga_mem_writeb, vga_mem_writew, vga_mem_writel, }; -static void vga_save(QEMUFile *f, void *opaque) -{ - VGAState *s = opaque; - int i; - - 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, 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 -} - -static int vga_load(QEMUFile *f, void *opaque, int version_id) +static int vga_common_post_load(void *opaque, int version_id) { - VGAState *s = opaque; - int is_vbe, i, ret; - - 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, 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 + VGACommonState *s = opaque; /* force refresh */ s->graphic_mode = -1; return 0; } -typedef struct PCIVGAState { - PCIDevice dev; - VGAState vga_state; -} PCIVGAState; - -void vga_dirty_log_start(VGAState *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); - } -} - -void vga_dirty_log_stop(VGAState *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, 0x8000); - kvm_log_stop(isa_mem_base + 0xa8000, 0x8000); - } -} - -static void vga_map(PCIDevice *pci_dev, int region_num, - uint32_t addr, uint32_t size, int type) -{ - PCIVGAState *d = (PCIVGAState *)pci_dev; - VGAState *s = &d->vga_state; - if (region_num == PCI_ROM_SLOT) { - cpu_register_physical_memory(addr, s->bios_size, s->bios_offset); - } else { - cpu_register_physical_memory(addr, s->vram_size, s->vram_offset); +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() } +}; - s->map_addr = addr; - s->map_end = addr + VGA_RAM_SIZE; - - vga_dirty_log_start(s); -} - -void vga_common_init(VGAState *s, uint8_t *vga_ram_base, - ram_addr_t vga_ram_offset, int vga_ram_size) +void vga_common_init(VGACommonState *s, int vga_ram_size) { int i, j, v, b; @@ -2287,8 +2251,13 @@ void vga_common_init(VGAState *s, uint8_t *vga_ram_base, expand4to8[i] = v; } - s->vram_ptr = vga_ram_base; - s->vram_offset = vga_ram_offset; +#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->get_bpp = vga_get_bpp; s->get_offsets = vga_get_offsets; @@ -2308,16 +2277,14 @@ void vga_common_init(VGAState *s, uint8_t *vga_ram_base, 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_reset(vga_reset, s); - register_savevm("vga", 0, 2, vga_save, vga_load, s); register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s); @@ -2357,184 +2324,31 @@ void vga_init(VGAState *s) #endif #endif /* CONFIG_BOCHS_VBE */ - vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s); + vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s); cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, vga_io_memory); qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000); } -/* Memory mapped interface */ -static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr) -{ - VGAState *s = opaque; - - return vga_ioport_read(s, addr >> s->it_shift) & 0xff; -} - -static void vga_mm_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) -{ - VGAState *s = opaque; - - vga_ioport_write(s, addr >> s->it_shift, value & 0xff); -} - -static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr) -{ - VGAState *s = opaque; - - return vga_ioport_read(s, addr >> s->it_shift) & 0xffff; -} - -static void vga_mm_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) -{ - VGAState *s = opaque; - - vga_ioport_write(s, addr >> s->it_shift, value & 0xffff); -} - -static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr) -{ - VGAState *s = opaque; - - return vga_ioport_read(s, addr >> s->it_shift); -} - -static void vga_mm_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) -{ - VGAState *s = opaque; - - vga_ioport_write(s, addr >> s->it_shift, value); -} - -static CPUReadMemoryFunc *vga_mm_read_ctrl[] = { - &vga_mm_readb, - &vga_mm_readw, - &vga_mm_readl, -}; - -static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = { - &vga_mm_writeb, - &vga_mm_writew, - &vga_mm_writel, -}; - -static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base, - target_phys_addr_t ctrl_base, int it_shift) -{ - int s_ioport_ctrl, vga_io_memory; - - s->it_shift = it_shift; - s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s); - vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s); - - register_savevm("vga", 0, 2, vga_save, vga_load, s); - - cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl); - s->bank_offset = 0; - cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory); - qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000); -} - -int isa_vga_init(uint8_t *vga_ram_base, - unsigned long vga_ram_offset, int vga_ram_size) -{ - VGAState *s; - - s = qemu_mallocz(sizeof(VGAState)); - - vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size); - vga_init(s); - - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); - -#ifdef CONFIG_BOCHS_VBE - /* XXX: use optimized standard vga accesses */ - cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, - vga_ram_size, vga_ram_offset); -#endif - return 0; -} - -int isa_vga_mm_init(uint8_t *vga_ram_base, - unsigned long vga_ram_offset, int vga_ram_size, - target_phys_addr_t vram_base, target_phys_addr_t ctrl_base, - int it_shift) +void vga_init_vbe(VGACommonState *s) { - VGAState *s; - - s = qemu_mallocz(sizeof(VGAState)); - - vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size); - vga_mm_init(s, vram_base, ctrl_base, it_shift); - - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); - #ifdef CONFIG_BOCHS_VBE /* XXX: use optimized standard vga accesses */ cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, - vga_ram_size, vga_ram_offset); -#endif - return 0; -} - -int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base, - unsigned long vga_ram_offset, int vga_ram_size, - unsigned long vga_bios_offset, int vga_bios_size) -{ - PCIVGAState *d; - VGAState *s; - uint8_t *pci_conf; - - d = (PCIVGAState *)pci_register_device(bus, "VGA", - sizeof(PCIVGAState), - -1, NULL, NULL); - if (!d) - return -1; - s = &d->vga_state; - - vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size); - vga_init(s); - - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); - - s->pci_dev = &d->dev; - - pci_conf = d->dev.config; - // dummy VGA (same as Bochs ID) - pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU); - pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA); - pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA); - pci_conf[0x0e] = 0x00; // header_type - - /* XXX: vga_ram_size must be a power of two */ - pci_register_io_region(&d->dev, 0, vga_ram_size, - PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map); - if (vga_bios_size != 0) { - unsigned int bios_total_size; - s->bios_offset = vga_bios_offset; - s->bios_size = vga_bios_size; - /* must be a power of two */ - bios_total_size = 1; - while (bios_total_size < vga_bios_size) - bios_total_size <<= 1; - pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size, - PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map); - } - return 0; + VGA_RAM_SIZE, s->vram_offset); + s->vbe_mapped = 1; +#endif } - /********************************************************/ /* vga screen dump */ -static void vga_save_dpy_update(DisplayState *s, +static void vga_save_dpy_update(DisplayState *ds, int x, int y, int w, int h) { + if (screen_dump_filename) { + ppm_save(screen_dump_filename, ds->surface); + screen_dump_filename = NULL; + } } static void vga_save_dpy_resize(DisplayState *s) @@ -2583,80 +2397,29 @@ int ppm_save(const char *filename, struct DisplaySurface *ds) return 0; } -static void vga_screen_dump_blank(VGAState *s, const char *filename) -{ - FILE *f; - unsigned int y, x, w, h; - - w = s->last_scr_width * sizeof(uint32_t); - h = s->last_scr_height; - - f = fopen(filename, "wb"); - if (!f) - return; - fprintf(f, "P6\n%d %d\n%d\n", w, h, 255); - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - fputc(0, f); - } - } - fclose(f); -} - -static void vga_screen_dump_common(VGAState *s, const char *filename, - int w, int h) -{ - DisplayState *saved_ds, ds1, *ds = &ds1; - DisplayChangeListener dcl; - - /* XXX: this is a little hackish */ - vga_invalidate_display(s); - saved_ds = s->ds; - - memset(ds, 0, sizeof(DisplayState)); - memset(&dcl, 0, sizeof(DisplayChangeListener)); - dcl.dpy_update = vga_save_dpy_update; - dcl.dpy_resize = vga_save_dpy_resize; - dcl.dpy_refresh = vga_save_dpy_refresh; - register_displaychangelistener(ds, &dcl); - ds->surface = qemu_create_displaysurface(w, h, 32, 4 * w); - - s->ds = ds; - s->graphic_mode = -1; - vga_update_display(s); - - ppm_save(filename, ds->surface); - - qemu_free_displaysurface(ds->surface); - s->ds = saved_ds; -} - -static void vga_screen_dump_graphic(VGAState *s, const char *filename) +static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds) { - int w, h; + DisplayChangeListener *dcl; - s->get_resolution(s, &w, &h); - vga_screen_dump_common(s, filename, w, h); -} - -static void vga_screen_dump_text(VGAState *s, const char *filename) -{ - int w, h, cwidth, cheight; - - vga_get_text_resolution(s, &w, &h, &cwidth, &cheight); - vga_screen_dump_common(s, filename, w * cwidth, h * cheight); + dcl = qemu_mallocz(sizeof(DisplayChangeListener)); + dcl->dpy_update = vga_save_dpy_update; + dcl->dpy_resize = vga_save_dpy_resize; + dcl->dpy_refresh = vga_save_dpy_refresh; + register_displaychangelistener(ds, dcl); + return dcl; } /* save the vga display in a PPM image even if no display is available */ static void vga_screen_dump(void *opaque, const char *filename) { - VGAState *s = (VGAState *)opaque; + VGACommonState *s = opaque; - if (!(s->ar_index & 0x20)) - vga_screen_dump_blank(s, filename); - else if (s->gr[6] & 1) - vga_screen_dump_graphic(s, filename); - else - vga_screen_dump_text(s, filename); + if (!screen_dump_dcl) + screen_dump_dcl = vga_screen_dump_init(s->ds); + + screen_dump_filename = (char *)filename; + vga_invalidate_display(s); + vga_hw_update(); } +