From 49a8bfb7ce3530b2616818db29d709f47e057feb Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Fri, 23 May 2008 18:20:55 +0100 Subject: [PATCH] Merge changes from xen-unstable 17647 with relevant upstream changes. Now we consider ourselves up to date with (a) upstream as recorded by git (b) xen-unstable 17647:f12724194ec6 This was achieved by copying these files console.c console.h hw/cirrus_vga.c hw/cirrus_vga_rop.h hw/cirrus_vga_rop2.h hw/vga.c hw/vga_int.h verbatim from the crazy branch vga-reverse-merge, current head commit cc011fdf74a616fec9ab6841026c5e7121c0dce3. We have effectively overwritten these files from qemu with those from xen-unstable and then cherry-picked changes from qemu mainline. --- console.c | 211 +++--------- console.h | 28 -- hw/cirrus_vga.c | 201 ++++++++++- hw/cirrus_vga_rop.h | 35 +- hw/cirrus_vga_rop2.h | 102 ++++-- hw/vga.c | 803 ++++++++++++++++++++++++------------------- hw/vga_int.h | 16 +- 7 files changed, 790 insertions(+), 606 deletions(-) diff --git a/console.c b/console.c index 880ac831a..01636c4b3 100644 --- a/console.c +++ b/console.c @@ -61,7 +61,7 @@ typedef struct QEMUFIFO { int count, wptr, rptr; } QEMUFIFO; -static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1) +int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1) { int l, len; @@ -84,7 +84,7 @@ static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1) return len1; } -static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1) +int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1) { int l, len; @@ -106,22 +106,15 @@ static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1) return len1; } -typedef enum { - GRAPHIC_CONSOLE, - TEXT_CONSOLE, - TEXT_CONSOLE_FIXED_SIZE -} console_type_t; - /* ??? This is mis-named. It is used for both text and graphical consoles. */ struct TextConsole { - console_type_t console_type; + int text_console; /* true if text console */ DisplayState *ds; /* Graphic console state. */ vga_hw_update_ptr hw_update; vga_hw_invalidate_ptr hw_invalidate; vga_hw_screen_dump_ptr hw_screen_dump; - vga_hw_text_update_ptr hw_text_update; void *hw; int g_width, g_height; @@ -136,7 +129,6 @@ struct TextConsole { TextAttributes t_attrib_default; /* default text attributes */ TextAttributes t_attrib; /* currently active text attributes */ TextCell *cells; - int text_x[2], text_y[2], cursor_invalidate; enum TTYState state; int esc_params[MAX_ESC_PARAMS]; @@ -173,28 +165,18 @@ void vga_hw_screen_dump(const char *filename) consoles[0]->hw_screen_dump(consoles[0]->hw, filename); } -void vga_hw_text_update(console_ch_t *chardata) -{ - if (active_console && active_console->hw_text_update) - active_console->hw_text_update(active_console->hw, chardata); -} - /* convert a RGBA color to a color index usable in graphic primitives */ static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba) { unsigned int r, g, b, color; switch(ds->depth) { -#if 0 case 8: r = (rgba >> 16) & 0xff; g = (rgba >> 8) & 0xff; b = (rgba) & 0xff; - color = (rgb_to_index[r] * 6 * 6) + - (rgb_to_index[g] * 6) + - (rgb_to_index[b]); + color = ((r >> 5) << 5 | (g >> 5) << 2 | (b >> 6)); break; -#endif case 15: r = (rgba >> 16) & 0xff; g = (rgba >> 8) & 0xff; @@ -523,25 +505,12 @@ static void text_console_resize(TextConsole *s) s->cells = cells; } -static inline void text_update_xy(TextConsole *s, int x, int y) -{ - s->text_x[0] = MIN(s->text_x[0], x); - s->text_x[1] = MAX(s->text_x[1], x); - s->text_y[0] = MIN(s->text_y[0], y); - s->text_y[1] = MAX(s->text_y[1], y); -} - static void update_xy(TextConsole *s, int x, int y) { TextCell *c; int y1, y2; if (s == active_console) { - if (!s->ds->depth) { - text_update_xy(s, x, y); - return; - } - y1 = (s->y_base + y) % s->total_height; y2 = y1 - s->y_displayed; if (y2 < 0) @@ -562,30 +531,21 @@ static void console_show_cursor(TextConsole *s, int show) int y, y1; if (s == active_console) { - int x = s->x; - - if (!s->ds->depth) { - s->cursor_invalidate = 1; - return; - } - - if (x >= s->width) { - x = s->width - 1; - } y1 = (s->y_base + s->y) % s->total_height; y = y1 - s->y_displayed; if (y < 0) y += s->total_height; if (y < s->height) { - c = &s->cells[y1 * s->width + x]; + c = &s->cells[y1 * s->width + s->x]; if (show) { TextAttributes t_attrib = s->t_attrib_default; t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */ - vga_putcharxy(s->ds, x, y, c->ch, &t_attrib); + vga_putcharxy(s->ds, s->x, y, c->ch, &t_attrib); } else { - vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib)); + vga_putcharxy(s->ds, s->x, y, c->ch, + &(c->t_attrib)); } - dpy_update(s->ds, x * FONT_WIDTH, y * FONT_HEIGHT, + dpy_update(s->ds, s->x * FONT_WIDTH, y * FONT_HEIGHT, FONT_WIDTH, FONT_HEIGHT); } } @@ -598,14 +558,6 @@ static void console_refresh(TextConsole *s) if (s != active_console) return; - if (!s->ds->depth) { - s->text_x[0] = 0; - s->text_y[0] = 0; - s->text_x[1] = s->width - 1; - s->text_y[1] = s->height - 1; - s->cursor_invalidate = 1; - return; - } vga_fill_rect(s->ds, 0, 0, s->ds->width, s->ds->height, color_table[0][COLOR_BLACK]); @@ -630,7 +582,7 @@ static void console_scroll(int ydelta) int i, y1; s = active_console; - if (!s || (s->console_type == GRAPHIC_CONSOLE)) + if (!s || !s->text_console) return; if (ydelta > 0) { @@ -683,14 +635,6 @@ static void console_put_lf(TextConsole *s) c++; } if (s == active_console && s->y_displayed == s->y_base) { - if (!s->ds->depth) { - s->text_x[0] = 0; - s->text_y[0] = 0; - s->text_x[1] = s->width - 1; - s->text_y[1] = s->height - 1; - return; - } - vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0, s->width * FONT_WIDTH, (s->height - 1) * FONT_HEIGHT); @@ -850,10 +794,8 @@ static void console_putchar(TextConsole *s, int ch) s->state = TTY_STATE_ESC; break; default: - if (s->x >= s->width) { - /* line wrap */ - s->x = 0; - console_put_lf(s); + if (s->x >= s->width - 1) { + break; } y1 = (s->y_base + s->y) % s->total_height; c = &s->cells[y1 * s->width + s->x]; @@ -861,6 +803,12 @@ static void console_putchar(TextConsole *s, int ch) c->t_attrib = s->t_attrib; update_xy(s, s->x, s->y); s->x++; +#if 0 /* line wrap disabled */ + if (s->x >= s->width) { + s->x = 0; + console_put_lf(s); + } +#endif break; } break; @@ -1041,7 +989,17 @@ void console_select(unsigned int index) s = consoles[index]; if (s) { active_console = s; - vga_hw_invalidate(); + if (s->text_console) { + if (s->g_width != s->ds->width || + s->g_height != s->ds->height) { + s->g_width = s->ds->width; + s->g_height = s->ds->height; + text_console_resize(s); + } + console_refresh(s); + } else { + vga_hw_invalidate(); + } } } @@ -1103,7 +1061,7 @@ void kbd_put_keysym(int keysym) int c; s = active_console; - if (!s || (s->console_type == GRAPHIC_CONSOLE)) + if (!s || !s->text_console) return; switch(keysym) { @@ -1145,53 +1103,7 @@ void kbd_put_keysym(int keysym) } } -static void text_console_invalidate(void *opaque) -{ - TextConsole *s = (TextConsole *) opaque; - - if (s->console_type != GRAPHIC_CONSOLE) { - if (s->g_width != s->ds->width || - s->g_height != s->ds->height) { - if (s->console_type == TEXT_CONSOLE_FIXED_SIZE) - dpy_resize(s->ds, s->g_width, s->g_height); - else { - s->g_width = s->ds->width; - s->g_height = s->ds->height; - text_console_resize(s); - } - } - } - console_refresh(s); -} - -static void text_console_update(void *opaque, console_ch_t *chardata) -{ - TextConsole *s = (TextConsole *) opaque; - int i, j, src; - - if (s->text_x[0] <= s->text_x[1]) { - src = (s->y_base + s->text_y[0]) * s->width; - chardata += s->text_y[0] * s->width; - for (i = s->text_y[0]; i <= s->text_y[1]; i ++) - for (j = 0; j < s->width; j ++, src ++) - console_write_ch(chardata ++, s->cells[src].ch | - (s->cells[src].t_attrib.fgcol << 12) | - (s->cells[src].t_attrib.bgcol << 8) | - (s->cells[src].t_attrib.bold << 21)); - dpy_update(s->ds, s->text_x[0], s->text_y[0], - s->text_x[1] - s->text_x[0], i - s->text_y[0]); - s->text_x[0] = s->width; - s->text_y[0] = s->height; - s->text_x[1] = 0; - s->text_y[1] = 0; - } - if (s->cursor_invalidate) { - dpy_cursor(s->ds, s->x, s->y); - s->cursor_invalidate = 0; - } -} - -static TextConsole *new_console(DisplayState *ds, console_type_t console_type) +static TextConsole *new_console(DisplayState *ds, int text) { TextConsole *s; int i; @@ -1202,18 +1114,16 @@ static TextConsole *new_console(DisplayState *ds, console_type_t console_type) if (!s) { return NULL; } - if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) && - (console_type == GRAPHIC_CONSOLE))) { + if (!active_console || (active_console->text_console && !text)) active_console = s; - } s->ds = ds; - s->console_type = console_type; - if (console_type != GRAPHIC_CONSOLE) { + s->text_console = text; + if (text) { consoles[nb_consoles++] = s; } else { /* HACK: Put graphical consoles before text consoles. */ for (i = nb_consoles; i > 0; i--) { - if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE) + if (!consoles[i - 1]->text_console) break; consoles[i] = consoles[i - 1]; } @@ -1225,50 +1135,46 @@ static TextConsole *new_console(DisplayState *ds, console_type_t console_type) TextConsole *graphic_console_init(DisplayState *ds, vga_hw_update_ptr update, vga_hw_invalidate_ptr invalidate, vga_hw_screen_dump_ptr screen_dump, - vga_hw_text_update_ptr text_update, void *opaque) { TextConsole *s; - s = new_console(ds, GRAPHIC_CONSOLE); + s = new_console(ds, 0); if (!s) return NULL; s->hw_update = update; s->hw_invalidate = invalidate; s->hw_screen_dump = screen_dump; - s->hw_text_update = text_update; s->hw = opaque; return s; } int is_graphic_console(void) { - return active_console && active_console->console_type == GRAPHIC_CONSOLE; + return !active_console->text_console; } -void console_color_init(DisplayState *ds) +void set_color_table(DisplayState *ds) { int i, j; - for (j = 0; j < 2; j++) { - for (i = 0; i < 8; i++) { - color_table[j][i] = col_expand(ds, - vga_get_color(ds, color_table_rgb[j][i])); - } + for(j = 0; j < 2; j++) { + for(i = 0; i < 8; i++) { + color_table[j][i] = + col_expand(ds, vga_get_color(ds, color_table_rgb[j][i])); + } } } -CharDriverState *text_console_init(DisplayState *ds, const char *p) +CharDriverState *text_console_init(DisplayState *ds) { CharDriverState *chr; TextConsole *s; - unsigned width; - unsigned height; static int color_inited; chr = qemu_mallocz(sizeof(CharDriverState)); if (!chr) return NULL; - s = new_console(ds, (p == 0) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE); + s = new_console(ds, 1); if (!s) { free(chr); return NULL; @@ -1284,36 +1190,15 @@ CharDriverState *text_console_init(DisplayState *ds, const char *p) if (!color_inited) { color_inited = 1; - console_color_init(s->ds); + set_color_table(ds); } s->y_displayed = 0; s->y_base = 0; s->total_height = DEFAULT_BACKSCROLL; s->x = 0; s->y = 0; - width = s->ds->width; - height = s->ds->height; - if (p != 0) { - width = strtoul(p, (char **)&p, 10); - if (*p == 'C') { - p++; - width *= FONT_WIDTH; - } - if (*p == 'x') { - p++; - height = strtoul(p, (char **)&p, 10); - if (*p == 'C') { - p++; - height *= FONT_HEIGHT; - } - } - } - s->g_width = width; - s->g_height = height; - - s->hw_invalidate = text_console_invalidate; - s->hw_text_update = text_console_update; - s->hw = s; + s->g_width = s->ds->width; + s->g_height = s->ds->height; /* Set text attribute defaults */ s->t_attrib_default.bold = 0; diff --git a/console.h b/console.h index c7f29f507..1ac74fad3 100644 --- a/console.h +++ b/console.h @@ -32,14 +32,6 @@ void kbd_put_keycode(int keycode); void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); int kbd_mouse_is_absolute(void); -struct mouse_transform_info_s { - /* Touchscreen resolution */ - int x; - int y; - /* Calibration values as used/generated by tslib */ - int a[7]; -}; - void do_info_mice(void); void do_mouse_set(int index); @@ -79,7 +71,6 @@ struct DisplayState { int height; void *opaque; struct QEMUTimer *gui_timer; - uint64_t gui_timer_interval; void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h); void (*dpy_resize)(struct DisplayState *s, int w, int h); @@ -88,7 +79,6 @@ struct DisplayState { int dst_x, int dst_y, int w, int h); void (*dpy_fill)(struct DisplayState *s, int x, int y, int w, int h, uint32_t c); - void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); void (*mouse_set)(int x, int y, int on); void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y, uint8_t *image, uint8_t *mask); @@ -104,32 +94,17 @@ static inline void dpy_resize(DisplayState *s, int w, int h) s->dpy_resize(s, w, h); } -static inline void dpy_cursor(DisplayState *s, int x, int y) -{ - if (s->dpy_text_cursor) - s->dpy_text_cursor(s, x, y); -} - -typedef unsigned long console_ch_t; -static inline void console_write_ch(console_ch_t *dest, uint32_t ch) -{ - cpu_to_le32wu((uint32_t *) dest, ch); -} - typedef void (*vga_hw_update_ptr)(void *); typedef void (*vga_hw_invalidate_ptr)(void *); typedef void (*vga_hw_screen_dump_ptr)(void *, const char *); -typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *); TextConsole *graphic_console_init(DisplayState *ds, vga_hw_update_ptr update, vga_hw_invalidate_ptr invalidate, vga_hw_screen_dump_ptr screen_dump, - vga_hw_text_update_ptr text_update, void *opaque); void vga_hw_update(void); void vga_hw_invalidate(void); void vga_hw_screen_dump(const char *filename); -void vga_hw_text_update(console_ch_t *chardata); int is_graphic_console(void); CharDriverState *text_console_init(DisplayState *ds, const char *p); @@ -149,9 +124,6 @@ int vnc_display_open(DisplayState *ds, const char *display); int vnc_display_password(DisplayState *ds, const char *password); void do_info_vnc(void); -/* curses.c */ -void curses_display_init(DisplayState *ds, int full_screen); - /* x_keymap.c */ extern uint8_t _translate_keycode(const int key); diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 4e9f98d37..c23fc8923 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -31,6 +31,9 @@ #include "pci.h" #include "console.h" #include "vga_int.h" +#ifndef _WIN32 +#include +#endif /* * TODO: @@ -284,6 +287,8 @@ typedef struct CirrusVGAState { int last_hw_cursor_y_end; int real_vram_size; /* XXX: suppress that */ CPUWriteMemoryFunc **cirrus_linear_write; + unsigned long map_addr; + unsigned long map_end; } CirrusVGAState; typedef struct PCICirrusVGAState { @@ -293,6 +298,8 @@ typedef struct PCICirrusVGAState { static uint8_t rop_to_index[256]; +void *shared_vram; + /*************************************** * * prototypes. @@ -302,6 +309,7 @@ static uint8_t rop_to_index[256]; static void cirrus_bitblt_reset(CirrusVGAState *s); static void cirrus_update_memory_access(CirrusVGAState *s); +static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val); /*************************************** * @@ -656,7 +664,8 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, 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); + cpu_physical_memory_set_dirty(s->vram_offset + + (off_cur & s->cirrus_addr_mask)); off_cur += TARGET_PAGE_SIZE; } off_begin += off_pitch; @@ -1579,6 +1588,17 @@ cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) case 0x31: // BLT STATUS/START cirrus_write_bitblt(s, reg_value); break; + + // Extension to allow BIOS to clear 16K VRAM bank in one operation + case 0xFE: + s->gr[reg_index] = reg_value; // Lower byte of value to be written + break; + case 0xFF: { + target_phys_addr_t addr; + for (addr = 0xa0000; addr < 0xa4000; addr += 2) + cirrus_vga_mem_writew(s, addr, (reg_value << 8) | s->gr[0xFE]); + } + break; default: #ifdef DEBUG_CIRRUS printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index, @@ -2619,6 +2639,98 @@ static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = { cirrus_linear_bitblt_writel, }; +static void *set_vram_mapping(unsigned long begin, unsigned long end) +{ + xen_pfn_t *extent_start = NULL; + unsigned long nr_extents; + void *vram_pointer = NULL; + int i; + + /* align begin and end address */ + begin = begin & TARGET_PAGE_MASK; + end = begin + VGA_RAM_SIZE; + end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK; + nr_extents = (end - begin) >> TARGET_PAGE_BITS; + + extent_start = malloc(sizeof(xen_pfn_t) * nr_extents); + if (extent_start == NULL) { + fprintf(stderr, "Failed malloc on set_vram_mapping\n"); + return NULL; + } + + memset(extent_start, 0, sizeof(xen_pfn_t) * nr_extents); + + for (i = 0; i < nr_extents; i++) + extent_start[i] = (begin + i * TARGET_PAGE_SIZE) >> TARGET_PAGE_BITS; + + if (set_mm_mapping(xc_handle, domid, nr_extents, 0, extent_start) < 0) { + fprintf(logfile, "Failed set_mm_mapping\n"); + free(extent_start); + return NULL; + } + + (void)xc_domain_pin_memory_cacheattr( + xc_handle, domid, + begin >> TARGET_PAGE_BITS, + end >> TARGET_PAGE_BITS, + XEN_DOMCTL_MEM_CACHEATTR_WB); + + vram_pointer = xc_map_foreign_pages(xc_handle, domid, + PROT_READ|PROT_WRITE, + extent_start, nr_extents); + if (vram_pointer == NULL) { + fprintf(logfile, "xc_map_foreign_batch vgaram returned error %d\n", + errno); + free(extent_start); + return NULL; + } + + memset(vram_pointer, 0, nr_extents * TARGET_PAGE_SIZE); + +#ifdef CONFIG_STUBDOM + xenfb_pv_display_start(vram_pointer); +#endif + + free(extent_start); + + return vram_pointer; +} + +static int unset_vram_mapping(unsigned long begin, unsigned long end, + void *mapping) +{ + xen_pfn_t *extent_start = NULL; + unsigned long nr_extents; + int i; + + /* align begin and end address */ + + end = begin + VGA_RAM_SIZE; + begin = begin & TARGET_PAGE_MASK; + end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK; + nr_extents = (end - begin) >> TARGET_PAGE_BITS; + + extent_start = malloc(sizeof(xen_pfn_t) * nr_extents); + + if (extent_start == NULL) { + fprintf(stderr, "Failed malloc on set_mm_mapping\n"); + return -1; + } + + /* Drop our own references to the vram pages */ + munmap(mapping, nr_extents * TARGET_PAGE_SIZE); + + /* Now drop the guest's mappings */ + memset(extent_start, 0, sizeof(xen_pfn_t) * nr_extents); + for (i = 0; i < nr_extents; i++) + extent_start[i] = (begin + (i * TARGET_PAGE_SIZE)) >> TARGET_PAGE_BITS; + unset_mm_mapping(xc_handle, domid, nr_extents, 0, extent_start); + + free(extent_start); + + return 0; +} + /* Compute the memory access functions */ static void cirrus_update_memory_access(CirrusVGAState *s) { @@ -2637,11 +2749,37 @@ static void cirrus_update_memory_access(CirrusVGAState *s) mode = s->gr[0x05] & 0x7; if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { + if (s->lfb_addr && s->lfb_end && !s->map_addr) { + void *vram_pointer, *old_vram; + + vram_pointer = set_vram_mapping(s->lfb_addr, + s->lfb_end); + if (!vram_pointer) + fprintf(stderr, "NULL vram_pointer\n"); + else { + old_vram = vga_update_vram((VGAState *)s, vram_pointer, + VGA_RAM_SIZE); + qemu_free(old_vram); + } + s->map_addr = s->lfb_addr; + s->map_end = s->lfb_end; + } 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: + if (s->lfb_addr && s->lfb_end && s->map_addr) { + void *old_vram; + + old_vram = vga_update_vram((VGAState *)s, NULL, VGA_RAM_SIZE); + + unset_vram_mapping(s->lfb_addr, + s->lfb_end, + old_vram); + + s->map_addr = s->map_end = 0; + } s->cirrus_linear_write[0] = cirrus_linear_writeb; s->cirrus_linear_write[1] = cirrus_linear_writew; s->cirrus_linear_write[2] = cirrus_linear_writel; @@ -2998,11 +3136,42 @@ static CPUWriteMemoryFunc *cirrus_mmio_write[3] = { cirrus_mmio_writel, }; +void cirrus_stop_acc(CirrusVGAState *s) +{ + if (s->map_addr){ + int error; + s->map_addr = 0; + error = unset_vram_mapping(s->lfb_addr, + s->lfb_end, s->vram_ptr); + fprintf(stderr, "cirrus_stop_acc:unset_vram_mapping.\n"); + } +} + +void cirrus_restart_acc(CirrusVGAState *s) +{ + if (s->lfb_addr && s->lfb_end) { + void *vram_pointer, *old_vram; + fprintf(stderr, "cirrus_vga_load:re-enable vga acc.lfb_addr=0x%lx, lfb_end=0x%lx.\n", + s->lfb_addr, s->lfb_end); + vram_pointer = set_vram_mapping(s->lfb_addr ,s->lfb_end); + if (!vram_pointer){ + fprintf(stderr, "cirrus_vga_load:NULL vram_pointer\n"); + } else { + old_vram = vga_update_vram((VGAState *)s, vram_pointer, + VGA_RAM_SIZE); + qemu_free(old_vram); + s->map_addr = s->lfb_addr; + s->map_end = s->lfb_end; + } + } +} + /* load/save state */ static void cirrus_vga_save(QEMUFile *f, void *opaque) { CirrusVGAState *s = opaque; + uint8_t vga_acc; if (s->pci_dev) pci_device_save(s->pci_dev, f); @@ -3040,11 +3209,18 @@ static void cirrus_vga_save(QEMUFile *f, void *opaque) 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 */ + + vga_acc = (!!s->map_addr); + qemu_put_8s(f, &vga_acc); + qemu_put_be64s(f, (uint64_t*)&s->lfb_addr); + qemu_put_be64s(f, (uint64_t*)&s->lfb_end); + qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE); } static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) { CirrusVGAState *s = opaque; + uint8_t vga_acc = 0; int ret; if (version_id > 2) @@ -3090,6 +3266,14 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) qemu_get_be32s(f, &s->hw_cursor_x); qemu_get_be32s(f, &s->hw_cursor_y); + qemu_get_8s(f, &vga_acc); + qemu_get_be64s(f, (uint64_t*)&s->lfb_addr); + qemu_get_be64s(f, (uint64_t*)&s->lfb_end); + qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE); + if (vga_acc){ + cirrus_restart_acc(s); + } + /* force refresh */ s->graphic_mode = -1; cirrus_update_bank_ptr(s, 0); @@ -3245,6 +3429,13 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num, /* XXX: add byte swapping apertures */ cpu_register_physical_memory(addr, s->vram_size, s->cirrus_linear_io_addr); + s->lfb_addr = addr; + s->lfb_end = addr + VGA_RAM_SIZE; + + if (s->map_addr && (s->lfb_addr != s->map_addr) && + (s->lfb_end != s->map_end)) + fprintf(logfile, "cirrus vga map change while on lfb mode\n"); + cpu_register_physical_memory(addr + 0x1000000, 0x400000, s->cirrus_linear_bitblt_io_addr); } @@ -3281,16 +3472,16 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, pci_conf[0x0a] = PCI_CLASS_SUB_VGA; pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY; pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h; + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; /* setup VGA */ 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, 1); - - graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, - s->text_update, s); - s->pci_dev = (PCIDevice *)d; /* setup memory space */ diff --git a/hw/cirrus_vga_rop.h b/hw/cirrus_vga_rop.h index 0079d1270..15e7fe41c 100644 --- a/hw/cirrus_vga_rop.h +++ b/hw/cirrus_vga_rop.h @@ -22,13 +22,31 @@ * THE SOFTWARE. */ +#define get_base(p, s, b) do { \ + if ((p) >= (s)->vram_ptr && (p) < (s)->vram_ptr + (s)->vram_size) \ + (b) = (s)->vram_ptr; \ + else if ((p) >= &(s)->cirrus_bltbuf[0] && \ + (p) < &(s)->cirrus_bltbuf[CIRRUS_BLTBUFSIZE]) \ + (b) = &(s)->cirrus_bltbuf[0]; \ + else \ + return; \ +} while(0) + +#define m(x) ((x) & s->cirrus_addr_mask) + static void glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, + uint8_t *dst_,const uint8_t *src_, int dstpitch,int srcpitch, int bltwidth,int bltheight) { int x,y; + uint32_t dst, src; + uint8_t *dst_base, *src_base; + get_base(dst_, s, dst_base); + get_base(src_, s, src_base); + dst = dst_ - dst_base; + src = src_ - src_base; dstpitch -= bltwidth; srcpitch -= bltwidth; @@ -39,7 +57,7 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - ROP_OP(*dst, *src); + ROP_OP(*(dst_base + m(dst)), *(src_base + m(src))); dst++; src++; } @@ -50,16 +68,22 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, static void glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, + uint8_t *dst_,const uint8_t *src_, int dstpitch,int srcpitch, int bltwidth,int bltheight) { int x,y; + uint32_t dst, src; + uint8_t *dst_base, *src_base; + get_base(dst_, s, dst_base); + get_base(src_, s, src_base); + dst = dst_ - dst_base; + src = src_ - src_base; dstpitch += bltwidth; srcpitch += bltwidth; for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - ROP_OP(*dst, *src); + ROP_OP(*(dst_base + m(dst)), *(src_base + m(src))); dst--; src--; } @@ -184,3 +208,6 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, #undef ROP_NAME #undef ROP_OP + +#undef get_base +#undef m diff --git a/hw/cirrus_vga_rop2.h b/hw/cirrus_vga_rop2.h index 137681ed1..47bbf70c0 100644 --- a/hw/cirrus_vga_rop2.h +++ b/hw/cirrus_vga_rop2.h @@ -23,36 +23,42 @@ */ #if DEPTH == 8 -#define PUTPIXEL() ROP_OP(d[0], col) +#define PUTPIXEL() ROP_OP((dst_base + m(d))[0], col) #elif DEPTH == 16 -#define PUTPIXEL() ROP_OP(((uint16_t *)d)[0], col); +#define PUTPIXEL() ROP_OP(((uint16_t *)(dst_base + m(d)))[0], col); #elif DEPTH == 24 -#define PUTPIXEL() ROP_OP(d[0], col); \ - ROP_OP(d[1], (col >> 8)); \ - ROP_OP(d[2], (col >> 16)) +#define PUTPIXEL() ROP_OP((dst_base + m(d))[0], col); \ + ROP_OP((dst_base + m(d))[1], (col >> 8)); \ + ROP_OP((dst_base + m(d))[2], (col >> 16)) #elif DEPTH == 32 -#define PUTPIXEL() ROP_OP(((uint32_t *)d)[0], col) +#define PUTPIXEL() ROP_OP(((uint32_t *)(dst_base + m(d)))[0], col) #else #error unsupported DEPTH #endif static void glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState * s, uint8_t * dst_, + const uint8_t * src_, int dstpitch, int srcpitch, int bltwidth, int bltheight) { - uint8_t *d; + uint8_t *dst_base, *src_base; + uint32_t src, dst; + uint32_t d; int x, y, pattern_y, pattern_pitch, pattern_x; unsigned int col; - const uint8_t *src1; + uint32_t src1; #if DEPTH == 24 int skipleft = s->gr[0x2f] & 0x1f; #else int skipleft = (s->gr[0x2f] & 0x07) * (DEPTH / 8); #endif + get_base(dst_, s, dst_base); + get_base(src_, s, src_base); + dst = dst_ - dst_base; + src = src_ - src_base; #if DEPTH == 8 pattern_pitch = 8; #elif DEPTH == 16 @@ -67,19 +73,19 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) src1 = src + pattern_y * pattern_pitch; for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { #if DEPTH == 8 - col = src1[pattern_x]; + col = *(src_base + m(src1 + pattern_x)); pattern_x = (pattern_x + 1) & 7; #elif DEPTH == 16 - col = ((uint16_t *)(src1 + pattern_x))[0]; + col = *(uint16_t *)(src_base + m(src1 + pattern_x)); pattern_x = (pattern_x + 2) & 15; #elif DEPTH == 24 { - const uint8_t *src2 = src1 + pattern_x * 3; + const uint8_t *src2 = src_base + m(src1 + pattern_x * 3); col = src2[0] | (src2[1] << 8) | (src2[2] << 16); pattern_x = (pattern_x + 1) & 7; } #else - col = ((uint32_t *)(src1 + pattern_x))[0]; + col = *(uint32_t *)(src_base + m(src1 + pattern_x)); pattern_x = (pattern_x + 4) & 31; #endif PUTPIXEL(); @@ -93,12 +99,14 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) /* NOTE: srcpitch is ignored */ static void glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState * s, uint8_t * dst_, + const uint8_t * src_, int dstpitch, int srcpitch, int bltwidth, int bltheight) { - uint8_t *d; + uint8_t *dst_base, *src_base; + uint32_t src, dst; + uint32_t d; int x, y; unsigned bits, bits_xor; unsigned int col; @@ -112,6 +120,10 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) int dstskipleft = srcskipleft * (DEPTH / 8); #endif + get_base(dst_, s, dst_base); + get_base(src_, s, src_base); + dst = dst_ - dst_base; + src = src_ - src_base; if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { bits_xor = 0xff; col = s->cirrus_blt_bgcol; @@ -122,12 +134,12 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) for(y = 0; y < bltheight; y++) { bitmask = 0x80 >> srcskipleft; - bits = *src++ ^ bits_xor; + bits = *(src_base + m(src++)) ^ bits_xor; d = dst + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; - bits = *src++ ^ bits_xor; + bits = *(src_base + m(src++)) ^ bits_xor; } index = (bits & bitmask); if (index) { @@ -142,13 +154,15 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) static void glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState * s, uint8_t * dst_, + const uint8_t * src_, int dstpitch, int srcpitch, int bltwidth, int bltheight) { + uint8_t *dst_base, *src_base; + uint32_t src, dst; uint32_t colors[2]; - uint8_t *d; + uint32_t d; int x, y; unsigned bits; unsigned int col; @@ -156,16 +170,20 @@ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) int srcskipleft = s->gr[0x2f] & 0x07; int dstskipleft = srcskipleft * (DEPTH / 8); + get_base(dst_, s, dst_base); + get_base(src_, s, src_base); + dst = dst_ - dst_base; + src = src_ - src_base; colors[0] = s->cirrus_blt_bgcol; colors[1] = s->cirrus_blt_fgcol; for(y = 0; y < bltheight; y++) { bitmask = 0x80 >> srcskipleft; - bits = *src++; + bits = *(src_base + m(src++)); d = dst + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; - bits = *src++; + bits = *(src_base + m(src++)); } col = colors[!!(bits & bitmask)]; PUTPIXEL(); @@ -178,12 +196,14 @@ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) static void glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState * s, uint8_t * dst_, + const uint8_t * src_, int dstpitch, int srcpitch, int bltwidth, int bltheight) { - uint8_t *d; + uint8_t *dst_base, *src_base; + uint32_t src, dst; + uint32_t d; int x, y, bitpos, pattern_y; unsigned int bits, bits_xor; unsigned int col; @@ -195,6 +215,10 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) int dstskipleft = srcskipleft * (DEPTH / 8); #endif + get_base(dst_, s, dst_base); + get_base(src_, s, src_base); + dst = dst_ - dst_base; + src = src_ - src_base; if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { bits_xor = 0xff; col = s->cirrus_blt_bgcol; @@ -205,7 +229,7 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) pattern_y = s->cirrus_blt_srcaddr & 7; for(y = 0; y < bltheight; y++) { - bits = src[pattern_y] ^ bits_xor; + bits = *(src_base + m(src + pattern_y)) ^ bits_xor; bitpos = 7 - srcskipleft; d = dst + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { @@ -222,25 +246,31 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) static void glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState * s, uint8_t * dst_, + const uint8_t * src_, int dstpitch, int srcpitch, int bltwidth, int bltheight) { + uint8_t *dst_base, *src_base; + uint32_t src, dst; uint32_t colors[2]; - uint8_t *d; + uint32_t d; int x, y, bitpos, pattern_y; unsigned int bits; unsigned int col; int srcskipleft = s->gr[0x2f] & 0x07; int dstskipleft = srcskipleft * (DEPTH / 8); + get_base(dst_, s, dst_base); + get_base(src_, s, src_base); + dst = dst_ - dst_base; + src = src_ - src_base; colors[0] = s->cirrus_blt_bgcol; colors[1] = s->cirrus_blt_fgcol; pattern_y = s->cirrus_blt_srcaddr & 7; for(y = 0; y < bltheight; y++) { - bits = src[pattern_y]; + bits = *(src_base + m(src + pattern_y)); bitpos = 7 - srcskipleft; d = dst + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { @@ -257,13 +287,17 @@ glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) static void glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) (CirrusVGAState *s, - uint8_t *dst, int dst_pitch, + uint8_t *dst_, int dst_pitch, int width, int height) { - uint8_t *d, *d1; + uint8_t *dst_base; + uint32_t dst; + uint32_t d, d1; uint32_t col; int x, y; + get_base(dst_, s, dst_base); + dst = dst_ - dst_base; col = s->cirrus_blt_fgcol; d1 = dst; diff --git a/hw/vga.c b/hw/vga.c index 2e7de564f..73c301b8f 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -26,7 +26,6 @@ #include "pc.h" #include "pci.h" #include "vga_int.h" -#include "pixel_ops.h" //#define DEBUG_VGA //#define DEBUG_VGA_MEM @@ -816,20 +815,37 @@ typedef void vga_draw_glyph9_func(uint8_t *d, int linesize, typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, const uint8_t *s, int width); -#define DEPTH 8 -#include "vga_template.h" +static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b) +{ + return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6); +} -#define DEPTH 15 -#include "vga_template.h" +static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b) +{ + return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); +} -#define BGR_FORMAT -#define DEPTH 15 +static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b) +{ + return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); +} + +static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b) +{ + return (r << 16) | (g << 8) | b; +} + +static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, unsigned b) +{ + return (b << 16) | (g << 8) | r; +} + +#define DEPTH 8 #include "vga_template.h" -#define DEPTH 16 +#define DEPTH 15 #include "vga_template.h" -#define BGR_FORMAT #define DEPTH 16 #include "vga_template.h" @@ -857,15 +873,6 @@ static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned return col; } -static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g, - unsigned int b) -{ - unsigned int col; - col = rgb_to_pixel15bgr(r, g, b); - col |= col << 16; - return col; -} - static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b) { unsigned int col; @@ -874,15 +881,6 @@ static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned return col; } -static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g, - unsigned int b) -{ - unsigned int col; - col = rgb_to_pixel16bgr(r, g, b); - col |= col << 16; - return col; -} - static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b) { unsigned int col; @@ -1003,7 +1001,7 @@ static int update_basic_params(VGAState *s) return full_update; } -#define NB_DEPTHS 7 +#define NB_DEPTHS 5 static inline int get_depth_index(DisplayState *s) { @@ -1012,15 +1010,9 @@ static inline int get_depth_index(DisplayState *s) case 8: return 0; case 15: - if (s->bgr) - return 5; - else - return 1; + return 1; case 16: - if (s->bgr) - return 6; - else - return 2; + return 2; case 32: if (s->bgr) return 4; @@ -1035,8 +1027,6 @@ static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = { vga_draw_glyph8_16, vga_draw_glyph8_32, vga_draw_glyph8_32, - vga_draw_glyph8_16, - vga_draw_glyph8_16, }; static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = { @@ -1045,8 +1035,6 @@ static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = { vga_draw_glyph16_16, vga_draw_glyph16_32, vga_draw_glyph16_32, - vga_draw_glyph16_16, - vga_draw_glyph16_16, }; static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = { @@ -1055,8 +1043,6 @@ static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = { vga_draw_glyph9_16, vga_draw_glyph9_32, vga_draw_glyph9_32, - vga_draw_glyph9_16, - vga_draw_glyph9_16, }; static const uint8_t cursor_glyph[32 * 4] = { @@ -1078,6 +1064,10 @@ static const uint8_t cursor_glyph[32 * 4] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; +typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b); + +static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS]; + /* * Text mode update * Missing: @@ -1099,6 +1089,14 @@ static void vga_draw_text(VGAState *s, int full_update) vga_draw_glyph8_func *vga_draw_glyph8; vga_draw_glyph9_func *vga_draw_glyph9; + /* Disable dirty bit tracking */ + xc_hvm_track_dirty_vram(xc_handle, domid, 0, 0, NULL); + + if (s->ds->dpy_colourdepth != NULL && s->ds->depth != 0) + s->ds->dpy_colourdepth(s->ds, 0); + s->rgb_to_pixel = + rgb_to_pixel_dup_table[get_depth_index(s->ds)]; + full_update |= update_palette16(s); palette = s->last_palette; @@ -1155,7 +1153,7 @@ static void vga_draw_text(VGAState *s, int full_update) cw != s->last_cw || cheight != s->last_ch) { s->last_scr_width = width * cw; s->last_scr_height = height * cheight; - dpy_resize(s->ds, s->last_scr_width, s->last_scr_height); + dpy_resize(s->ds, s->last_scr_width, s->last_scr_height, s->last_scr_width * (s->ds->depth / 8)); s->last_width = width; s->last_height = height; s->last_ch = cheight; @@ -1277,92 +1275,68 @@ static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = { vga_draw_line2_16, vga_draw_line2_32, vga_draw_line2_32, - vga_draw_line2_16, - vga_draw_line2_16, vga_draw_line2d2_8, vga_draw_line2d2_16, vga_draw_line2d2_16, vga_draw_line2d2_32, vga_draw_line2d2_32, - vga_draw_line2d2_16, - vga_draw_line2d2_16, vga_draw_line4_8, vga_draw_line4_16, vga_draw_line4_16, vga_draw_line4_32, vga_draw_line4_32, - vga_draw_line4_16, - vga_draw_line4_16, vga_draw_line4d2_8, vga_draw_line4d2_16, vga_draw_line4d2_16, vga_draw_line4d2_32, vga_draw_line4d2_32, - vga_draw_line4d2_16, - vga_draw_line4d2_16, vga_draw_line8d2_8, vga_draw_line8d2_16, vga_draw_line8d2_16, vga_draw_line8d2_32, vga_draw_line8d2_32, - vga_draw_line8d2_16, - vga_draw_line8d2_16, vga_draw_line8_8, vga_draw_line8_16, vga_draw_line8_16, vga_draw_line8_32, vga_draw_line8_32, - vga_draw_line8_16, - vga_draw_line8_16, vga_draw_line15_8, vga_draw_line15_15, vga_draw_line15_16, vga_draw_line15_32, vga_draw_line15_32bgr, - vga_draw_line15_15bgr, - vga_draw_line15_16bgr, vga_draw_line16_8, vga_draw_line16_15, vga_draw_line16_16, vga_draw_line16_32, vga_draw_line16_32bgr, - vga_draw_line16_15bgr, - vga_draw_line16_16bgr, vga_draw_line24_8, vga_draw_line24_15, vga_draw_line24_16, vga_draw_line24_32, vga_draw_line24_32bgr, - vga_draw_line24_15bgr, - vga_draw_line24_16bgr, vga_draw_line32_8, vga_draw_line32_15, vga_draw_line32_16, vga_draw_line32_32, vga_draw_line32_32bgr, - vga_draw_line32_15bgr, - vga_draw_line32_16bgr, }; -typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b); - static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = { rgb_to_pixel8_dup, rgb_to_pixel15_dup, rgb_to_pixel16_dup, rgb_to_pixel32_dup, rgb_to_pixel32bgr_dup, - rgb_to_pixel15bgr_dup, - rgb_to_pixel16bgr_dup, }; static int vga_get_bpp(VGAState *s) @@ -1412,23 +1386,134 @@ void vga_invalidate_scanlines(VGAState *s, int y1, int y2) } } +static inline int cmp_vram(VGAState *s, int offset, int n) +{ + long *vp, *sp; + + if (s->vram_shadow == NULL) + return 1; + vp = (long *)(s->vram_ptr + offset); + sp = (long *)(s->vram_shadow + offset); + while ((n -= sizeof(*vp)) >= 0) { + if (*vp++ != *sp++) { + memcpy(sp - 1, vp - 1, n + sizeof(*vp)); + return 1; + } + } + return 0; +} + +#ifdef USE_SSE2 + +#include +#include +#include + +int sse2_ok = 1; + +static inline unsigned int cpuid_edx(unsigned int op) +{ + unsigned int eax, edx; + +#ifdef __x86_64__ +#define __bx "rbx" +#else +#define __bx "ebx" +#endif + __asm__("push %%"__bx"; cpuid; pop %%"__bx + : "=a" (eax), "=d" (edx) + : "0" (op) + : "cx"); +#undef __bx + + return edx; +} + +jmp_buf sse_jbuf; + +void intr(int sig) +{ + sse2_ok = 0; + longjmp(sse_jbuf, 1); +} + +void check_sse2(void) +{ + /* Check 1: What does CPUID say? */ + if ((cpuid_edx(1) & 0x4000000) == 0) { + sse2_ok = 0; + return; + } + + /* Check 2: Can we use SSE2 in anger? */ + signal(SIGILL, intr); + if (setjmp(sse_jbuf) == 0) + __asm__("xorps %xmm0,%xmm0\n"); +} + +int vram_dirty(VGAState *s, int offset, int n) +{ + __m128i *sp, *vp; + + if (s->vram_shadow == NULL) + return 1; + if (sse2_ok == 0) + return cmp_vram(s, offset, n); + vp = (__m128i *)(s->vram_ptr + offset); + sp = (__m128i *)(s->vram_shadow + offset); + while ((n -= sizeof(*vp)) >= 0) { + if (_mm_movemask_epi8(_mm_cmpeq_epi8(*sp, *vp)) != 0xffff) { + while (n >= 0) { + _mm_store_si128(sp++, _mm_load_si128(vp++)); + n -= sizeof(*vp); + } + return 1; + } + sp++; + vp++; + } + return 0; +} +#else /* !USE_SSE2 */ +int vram_dirty(VGAState *s, int offset, int n) +{ + return cmp_vram(s, offset, n); +} + +void check_sse2(void) +{ +} +#endif /* !USE_SSE2 */ + /* * graphic modes */ static void vga_draw_graphic(VGAState *s, int full_update) { - int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask; - 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, ds_depth, bits; + ram_addr_t page0, page1; int disp_width, multi_scan, multi_run; uint8_t *d; uint32_t v, addr1, addr; vga_draw_line_func *vga_draw_line; + ram_addr_t page_min, page_max; full_update |= update_basic_params(s); s->get_resolution(s, &width, &height); disp_width = width; + ds_depth = s->ds->depth; + depth = s->get_bpp(s); + if (s->ds->dpy_colourdepth != NULL && + (ds_depth != depth || !s->ds->shared_buf)) + s->ds->dpy_colourdepth(s->ds, depth); + if (ds_depth != s->ds->depth) full_update = 1; + + s->rgb_to_pixel = + rgb_to_pixel_dup_table[get_depth_index(s->ds)]; + shift_control = (s->gr[0x05] >> 5) & 3; double_scan = (s->cr[0x09] >> 7); if (shift_control != 1) { @@ -1495,18 +1580,22 @@ static void vga_draw_graphic(VGAState *s, int full_update) break; } } - vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)]; - if (disp_width != s->last_width || + vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)]; + if (s->line_offset != s->last_line_offset || + disp_width != s->last_width || height != s->last_height) { - dpy_resize(s->ds, disp_width, height); + dpy_resize(s->ds, disp_width, height, s->line_offset); s->last_scr_width = disp_width; s->last_scr_height = height; s->last_width = disp_width; s->last_height = height; + s->last_line_offset = s->line_offset; full_update = 1; } - if (s->cursor_invalidate) + if (s->ds->shared_buf && (full_update || s->ds->data != s->vram_ptr + (s->start_addr * 4))) + s->ds->dpy_setdata(s->ds, s->vram_ptr + (s->start_addr * 4)); + if (!s->ds->shared_buf && s->cursor_invalidate) s->cursor_invalidate(s); line_offset = s->line_offset; @@ -1514,11 +1603,76 @@ static void vga_draw_graphic(VGAState *s, int full_update) printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n", width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]); #endif + + y = 0; + + if (height - 1 > s->line_compare || multi_run || (s->cr[0x17] & 3) != 3 + || !s->lfb_addr) { + /* Tricky things happen, disable dirty bit tracking */ + xc_hvm_track_dirty_vram(xc_handle, domid, 0, 0, NULL); + + for ( ; y < s->vram_size; y += TARGET_PAGE_SIZE) + if (vram_dirty(s, y, TARGET_PAGE_SIZE)) + cpu_physical_memory_set_dirty(s->vram_offset + y); + } else { + /* Tricky things won't have any effect, i.e. we are in the very simple + * (and very usual) case of a linear buffer. */ + unsigned long end; + + for ( ; y < ((s->start_addr * 4) & TARGET_PAGE_MASK); y += TARGET_PAGE_SIZE) + /* We will not read that anyway. */ + cpu_physical_memory_set_dirty(s->vram_offset + y); + + if (y < (s->start_addr * 4)) { + /* start address not aligned on a page, track dirtyness by hand. */ + if (vram_dirty(s, y, TARGET_PAGE_SIZE)) + cpu_physical_memory_set_dirty(s->vram_offset + y); + y += TARGET_PAGE_SIZE; + } + + /* use page table dirty bit tracking for the inner of the LFB */ + end = s->start_addr * 4 + height * line_offset; + { + unsigned long npages = ((end & TARGET_PAGE_MASK) - y) / TARGET_PAGE_SIZE; + const int width = sizeof(unsigned long) * 8; + unsigned long bitmap[(npages + width - 1) / width]; + int err; + + if (!(err = xc_hvm_track_dirty_vram(xc_handle, domid, + (s->lfb_addr + y) / TARGET_PAGE_SIZE, npages, bitmap))) { + int i, j; + for (i = 0; i < sizeof(bitmap) / sizeof(*bitmap); i++) { + unsigned long map = bitmap[i]; + for (j = i * width; map && j < npages; map >>= 1, j++) + if (map & 1) + cpu_physical_memory_set_dirty(s->vram_offset + y + + j * TARGET_PAGE_SIZE); + } + y += npages * TARGET_PAGE_SIZE; + } else { + /* ENODATA just means we have changed mode and will succeed + * next time */ + if (err != -ENODATA) + fprintf(stderr, "track_dirty_vram(%lx, %lx) failed (%d)\n", s->lfb_addr + y, npages, err); + } + } + + for ( ; y < s->vram_size && y < end; y += TARGET_PAGE_SIZE) + /* failed or end address not aligned on a page, track dirtyness by + * hand. */ + if (vram_dirty(s, y, TARGET_PAGE_SIZE)) + cpu_physical_memory_set_dirty(s->vram_offset + y); + + for ( ; y < s->vram_size; y += TARGET_PAGE_SIZE) + /* We will not read that anyway. */ + cpu_physical_memory_set_dirty(s->vram_offset + y); + } + addr1 = (s->start_addr * 4); bwidth = (width * bits + 7) / 8; y_start = -1; - page_min = 0x7fffffff; - page_max = -1; + page_min = 0; + page_max = 0; d = s->ds->data; linesize = s->ds->linesize; y1 = 0; @@ -1548,13 +1702,15 @@ static void vga_draw_graphic(VGAState *s, int full_update) if (update) { if (y_start < 0) y_start = y; - if (page0 < page_min) + if (page_min == 0 || page0 < page_min) page_min = page0; - if (page1 > page_max) + if (page_max == 0 || page1 > page_max) page_max = page1; - vga_draw_line(s, d, s->vram_ptr + addr, width); - if (s->cursor_draw_line) - s->cursor_draw_line(s, d, y); + if (!s->ds->shared_buf) { + vga_draw_line(s, d, s->vram_ptr + addr, width); + if (s->cursor_draw_line) + s->cursor_draw_line(s, d, y); + } } else { if (y_start >= 0) { /* flush to display */ @@ -1599,6 +1755,12 @@ static void vga_draw_blank(VGAState *s, int full_update) return; if (s->last_scr_width <= 0 || s->last_scr_height <= 0) return; + + /* Disable dirty bit tracking */ + xc_hvm_track_dirty_vram(xc_handle, domid, 0, 0, NULL); + + s->rgb_to_pixel = + rgb_to_pixel_dup_table[get_depth_index(s->ds)]; if (s->ds->depth == 8) val = s->rgb_to_pixel(0, 0, 0); else @@ -1625,9 +1787,6 @@ static void vga_update_display(void *opaque) if (s->ds->depth == 0) { /* nothing to do */ } else { - s->rgb_to_pixel = - rgb_to_pixel_dup_table[get_depth_index(s->ds)]; - full_update = 0; if (!(s->ar_index & 0x20)) { graphic_mode = GMODE_BLANK; @@ -1668,166 +1827,6 @@ static void vga_reset(VGAState *s) s->graphic_mode = -1; /* force full update */ } -#define TEXTMODE_X(x) ((x) % width) -#define TEXTMODE_Y(x) ((x) / width) -#define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \ - ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1)) -/* relay text rendering to the display driver - * instead of doing a full vga_update_display() */ -static void vga_update_text(void *opaque, console_ch_t *chardata) -{ - VGAState *s = (VGAState *) opaque; - int graphic_mode, i, cursor_offset, cursor_visible; - int cw, cheight, width, height, size, c_min, c_max; - uint32_t *src; - console_ch_t *dst, val; - char msg_buffer[80]; - int full_update = 0; - - if (!(s->ar_index & 0x20)) { - graphic_mode = GMODE_BLANK; - } else { - graphic_mode = s->gr[6] & 1; - } - if (graphic_mode != s->graphic_mode) { - s->graphic_mode = graphic_mode; - full_update = 1; - } - if (s->last_width == -1) { - s->last_width = 0; - full_update = 1; - } - - switch (graphic_mode) { - case GMODE_TEXT: - /* TODO: update palette */ - full_update |= update_basic_params(s); - - /* total width & height */ - cheight = (s->cr[9] & 0x1f) + 1; - cw = 8; - if (!(s->sr[1] & 0x01)) - cw = 9; - if (s->sr[1] & 0x08) - cw = 16; /* NOTE: no 18 pixel wide */ - width = (s->cr[0x01] + 1); - if (s->cr[0x06] == 100) { - /* ugly hack for CGA 160x100x16 - explain me the logic */ - height = 100; - } else { - height = s->cr[0x12] | - ((s->cr[0x07] & 0x02) << 7) | - ((s->cr[0x07] & 0x40) << 3); - height = (height + 1) / cheight; - } - - size = (height * width); - if (size > CH_ATTR_SIZE) { - if (!full_update) - return; - - sprintf(msg_buffer, "%i x %i Text mode", width, height); - break; - } - - if (width != s->last_width || height != s->last_height || - cw != s->last_cw || cheight != s->last_ch) { - s->last_scr_width = width * cw; - s->last_scr_height = height * cheight; - dpy_resize(s->ds, width, height); - s->last_width = width; - s->last_height = height; - s->last_ch = cheight; - s->last_cw = cw; - full_update = 1; - } - - /* Update "hardware" cursor */ - cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr; - if (cursor_offset != s->cursor_offset || - s->cr[0xa] != s->cursor_start || - s->cr[0xb] != s->cursor_end || full_update) { - cursor_visible = !(s->cr[0xa] & 0x20); - if (cursor_visible && cursor_offset < size && cursor_offset >= 0) - dpy_cursor(s->ds, - TEXTMODE_X(cursor_offset), - TEXTMODE_Y(cursor_offset)); - else - dpy_cursor(s->ds, -1, -1); - s->cursor_offset = cursor_offset; - s->cursor_start = s->cr[0xa]; - s->cursor_end = s->cr[0xb]; - } - - src = (uint32_t *) s->vram_ptr + s->start_addr; - dst = chardata; - - if (full_update) { - for (i = 0; i < size; src ++, dst ++, i ++) - console_write_ch(dst, VMEM2CHTYPE(*src)); - - dpy_update(s->ds, 0, 0, width, height); - } else { - c_max = 0; - - for (i = 0; i < size; src ++, dst ++, i ++) { - console_write_ch(&val, VMEM2CHTYPE(*src)); - if (*dst != val) { - *dst = val; - c_max = i; - break; - } - } - c_min = i; - for (; i < size; src ++, dst ++, i ++) { - console_write_ch(&val, VMEM2CHTYPE(*src)); - if (*dst != val) { - *dst = val; - c_max = i; - } - } - - if (c_min <= c_max) { - i = TEXTMODE_Y(c_min); - dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1); - } - } - - return; - case GMODE_GRAPH: - if (!full_update) - return; - - s->get_resolution(s, &width, &height); - sprintf(msg_buffer, "%i x %i Graphic mode", width, height); - break; - case GMODE_BLANK: - default: - if (!full_update) - return; - - sprintf(msg_buffer, "VGA Blank mode"); - break; - } - - /* Display a message */ - s->last_width = 60; - s->last_height = height = 3; - dpy_cursor(s->ds, -1, -1); - dpy_resize(s->ds, s->last_width, height); - - for (dst = chardata, i = 0; i < s->last_width * height; i ++) - console_write_ch(dst ++, ' '); - - size = strlen(msg_buffer); - width = (s->last_width - size) / 2; - dst = chardata + s->last_width + width; - for (i = 0; i < size; i ++) - console_write_ch(dst ++, 0x00200100 | msg_buffer[i]); - - dpy_update(s->ds, 0, 0, s->last_width, height); -} - static CPUReadMemoryFunc *vga_mem_read[3] = { vga_mem_readb, vga_mem_readw, @@ -1843,7 +1842,10 @@ static CPUWriteMemoryFunc *vga_mem_write[3] = { static void vga_save(QEMUFile *f, void *opaque) { VGAState *s = opaque; + uint32_t vram_size; +#ifdef CONFIG_BOCHS_VBE int i; +#endif if (s->pci_dev) pci_device_save(s->pci_dev, f); @@ -1882,14 +1884,21 @@ static void vga_save(QEMUFile *f, void *opaque) #else qemu_put_byte(f, 0); #endif + vram_size = s->vram_size; + qemu_put_be32s(f, &vram_size); + qemu_put_buffer(f, s->vram_ptr, s->vram_size); } static int vga_load(QEMUFile *f, void *opaque, int version_id) { VGAState *s = opaque; - int is_vbe, i, ret; + int is_vbe, ret; + uint32_t vram_size; +#ifdef CONFIG_BOCHS_VBE + int i; +#endif - if (version_id > 2) + if (version_id > 3) return -EINVAL; if (s->pci_dev && version_id >= 2) { @@ -1935,6 +1944,13 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id) if (is_vbe) return -EINVAL; #endif + if (version_id >= 3) { + /* people who restore old images may be lucky ... */ + qemu_get_be32s(f, &vram_size); + if (vram_size != s->vram_size) + return -EINVAL; + qemu_get_buffer(f, s->vram_ptr, s->vram_size); + } /* force refresh */ s->graphic_mode = -1; @@ -1958,6 +1974,137 @@ static void vga_map(PCIDevice *pci_dev, int region_num, } } +/* do the same job as vgabios before vgabios get ready - yeah */ +void vga_bios_init(VGAState *s) +{ + uint8_t palette_model[192] = { + 0, 0, 0, 0, 0, 170, 0, 170, + 0, 0, 170, 170, 170, 0, 0, 170, + 0, 170, 170, 85, 0, 170, 170, 170, + 85, 85, 85, 85, 85, 255, 85, 255, + 85, 85, 255, 255, 255, 85, 85, 255, + 85, 255, 255, 255, 85, 255, 255, 255, + 0, 21, 0, 0, 21, 42, 0, 63, + 0, 0, 63, 42, 42, 21, 0, 42, + 21, 42, 42, 63, 0, 42, 63, 42, + 0, 21, 21, 0, 21, 63, 0, 63, + 21, 0, 63, 63, 42, 21, 21, 42, + 21, 63, 42, 63, 21, 42, 63, 63, + 21, 0, 0, 21, 0, 42, 21, 42, + 0, 21, 42, 42, 63, 0, 0, 63, + 0, 42, 63, 42, 0, 63, 42, 42, + 21, 0, 21, 21, 0, 63, 21, 42, + 21, 21, 42, 63, 63, 0, 21, 63, + 0, 63, 63, 42, 21, 63, 42, 63, + 21, 21, 0, 21, 21, 42, 21, 63, + 0, 21, 63, 42, 63, 21, 0, 63, + 21, 42, 63, 63, 0, 63, 63, 42, + 21, 21, 21, 21, 21, 63, 21, 63, + 21, 21, 63, 63, 63, 21, 21, 63, + 21, 63, 63, 63, 21, 63, 63, 63 + }; + + s->latch = 0; + + s->sr_index = 3; + s->sr[0] = 3; + s->sr[1] = 0; + s->sr[2] = 3; + s->sr[3] = 0; + s->sr[4] = 2; + s->sr[5] = 0; + s->sr[6] = 0; + s->sr[7] = 0; + + s->gr_index = 5; + s->gr[0] = 0; + s->gr[1] = 0; + s->gr[2] = 0; + s->gr[3] = 0; + s->gr[4] = 0; + s->gr[5] = 16; + s->gr[6] = 14; + s->gr[7] = 15; + s->gr[8] = 255; + + /* changed by out 0x03c0 */ + s->ar_index = 32; + s->ar[0] = 0; + s->ar[1] = 1; + s->ar[2] = 2; + s->ar[3] = 3; + s->ar[4] = 4; + s->ar[5] = 5; + s->ar[6] = 6; + s->ar[7] = 7; + s->ar[8] = 8; + s->ar[9] = 9; + s->ar[10] = 10; + s->ar[11] = 11; + s->ar[12] = 12; + s->ar[13] = 13; + s->ar[14] = 14; + s->ar[15] = 15; + s->ar[16] = 12; + s->ar[17] = 0; + s->ar[18] = 15; + s->ar[19] = 8; + s->ar[20] = 0; + + s->ar_flip_flop = 1; + + s->cr_index = 15; + s->cr[0] = 95; + s->cr[1] = 79; + s->cr[2] = 80; + s->cr[3] = 130; + s->cr[4] = 85; + s->cr[5] = 129; + s->cr[6] = 191; + s->cr[7] = 31; + s->cr[8] = 0; + s->cr[9] = 79; + s->cr[10] = 14; + s->cr[11] = 15; + s->cr[12] = 0; + s->cr[13] = 0; + s->cr[14] = 5; + s->cr[15] = 160; + s->cr[16] = 156; + s->cr[17] = 142; + s->cr[18] = 143; + s->cr[19] = 40; + s->cr[20] = 31; + s->cr[21] = 150; + s->cr[22] = 185; + s->cr[23] = 163; + s->cr[24] = 255; + + s->msr = 103; + s->fcr = 0; + s->st00 = 0; + s->st01 = 0; + + /* dac_* & palette will be initialized by os through out 0x03c8 & + * out 0c03c9(1:3) */ + s->dac_state = 0; + s->dac_sub_index = 0; + s->dac_read_index = 0; + s->dac_write_index = 16; + s->dac_cache[0] = 255; + s->dac_cache[1] = 255; + s->dac_cache[2] = 255; + + /* palette */ + memcpy(s->palette, palette_model, 192); + + s->bank_offset = 0; + s->graphic_mode = -1; + + /* TODO: add vbe support if enabled */ +} + +/* when used on xen environment, the vga_ram_base is not used */ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size) { @@ -1988,25 +2135,37 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, vga_reset(s); - s->vram_ptr = vga_ram_base; + check_sse2(); + s->vram_shadow = qemu_malloc(vga_ram_size+TARGET_PAGE_SIZE+1); + if (s->vram_shadow == NULL) + fprintf(stderr, "Cannot allocate %d bytes for VRAM shadow, " + "mouse will be slow\n", vga_ram_size); + s->vram_shadow = (uint8_t *)((long)(s->vram_shadow + TARGET_PAGE_SIZE - 1) + & ~(TARGET_PAGE_SIZE - 1)); + + /* Video RAM must be 128-bit aligned for SSE optimizations later */ + /* and page-aligned for PVFB memory sharing */ + s->vram_ptr = s->vram_alloc = qemu_memalign(TARGET_PAGE_SIZE, vga_ram_size); + s->vram_offset = vga_ram_offset; s->vram_size = vga_ram_size; s->ds = ds; + ds->palette = s->last_palette; s->get_bpp = vga_get_bpp; s->get_offsets = vga_get_offsets; s->get_resolution = vga_get_resolution; - s->update = vga_update_display; - s->invalidate = vga_invalidate_display; - s->screen_dump = vga_screen_dump; - s->text_update = vga_update_text; + graphic_console_init(s->ds, vga_update_display, vga_invalidate_display, + vga_screen_dump, s); + + vga_bios_init(s); } /* used by both ISA and PCI */ -void vga_init(VGAState *s) +static void vga_init(VGAState *s) { int vga_io_memory; - register_savevm("vga", 0, 2, vga_save, vga_load, s); + register_savevm("vga", 0, 3, vga_save, vga_load, s); register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s); @@ -2053,81 +2212,6 @@ void vga_init(VGAState *s) vga_io_memory); } -/* 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->base_ctrl) >> 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->base_ctrl) >> 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->base_ctrl) >> 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->base_ctrl) >> 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->base_ctrl) >> 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->base_ctrl) >> 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->base_ctrl = ctrl_base; - 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); -} - int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size) { @@ -2140,34 +2224,6 @@ int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size); vga_init(s); - graphic_console_init(s->ds, 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(DisplayState *ds, 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) -{ - VGAState *s; - - s = qemu_mallocz(sizeof(VGAState)); - if (!s) - return -1; - - vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size); - vga_mm_init(s, vram_base, ctrl_base, it_shift); - - graphic_console_init(s->ds, 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, @@ -2193,10 +2249,6 @@ int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size); vga_init(s); - - graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, - s->text_update, s); - s->pci_dev = &d->dev; pci_conf = d->dev.config; @@ -2225,6 +2277,33 @@ int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, return 0; } +void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size) +{ + uint8_t *old_pointer; + + if (s->vram_size != vga_ram_size) { + fprintf(stderr, "No support to change vga_ram_size\n"); + return NULL; + } + + if (!vga_ram_base) { + vga_ram_base = qemu_memalign(TARGET_PAGE_SIZE, vga_ram_size + TARGET_PAGE_SIZE + 1); + if (!vga_ram_base) { + fprintf(stderr, "reallocate error\n"); + return NULL; + } + } + + /* XXX lock needed? */ + old_pointer = s->vram_alloc; + s->vram_alloc = vga_ram_base; + vga_ram_base = (uint8_t *)((long)(vga_ram_base + 15) & ~15L); + memcpy(vga_ram_base, s->vram_ptr, vga_ram_size); + s->vram_ptr = vga_ram_base; + + return old_pointer; +} + /********************************************************/ /* vga screen dump */ @@ -2235,7 +2314,7 @@ static void vga_save_dpy_update(DisplayState *s, { } -static void vga_save_dpy_resize(DisplayState *s, int w, int h) +static void vga_save_dpy_resize(DisplayState *s, int w, int h, int linesize) { s->linesize = w * 4; s->data = qemu_malloc(h * s->linesize); @@ -2247,8 +2326,8 @@ static void vga_save_dpy_refresh(DisplayState *s) { } -int ppm_save(const char *filename, uint8_t *data, - int w, int h, int linesize) +static int ppm_save(const char *filename, uint8_t *data, + int w, int h, int linesize) { FILE *f; uint8_t *d, *d1; diff --git a/hw/vga_int.h b/hw/vga_int.h index da2c30127..67309a66c 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -28,7 +28,7 @@ #define ST01_DISP_ENABLE 0x01 /* bochs VBE support */ -#define CONFIG_BOCHS_VBE +//#define CONFIG_BOCHS_VBE #define VBE_DISPI_MAX_XRES 1600 #define VBE_DISPI_MAX_YRES 1200 @@ -80,13 +80,15 @@ #define VGA_MAX_HEIGHT 2048 #define VGA_STATE_COMMON \ + uint8_t *vram_alloc; \ uint8_t *vram_ptr; \ + uint8_t *vram_shadow; \ unsigned long vram_offset; \ unsigned int vram_size; \ unsigned long bios_offset; \ unsigned int bios_size; \ - target_phys_addr_t base_ctrl; \ - int it_shift; \ + unsigned long lfb_addr; \ + unsigned long lfb_end; \ PCIDevice *pci_dev; \ uint32_t latch; \ uint8_t sr_index; \ @@ -137,10 +139,6 @@ uint32_t cursor_offset; \ unsigned int (*rgb_to_pixel)(unsigned int r, \ unsigned int g, unsigned b); \ - vga_hw_update_ptr update; \ - vga_hw_invalidate_ptr invalidate; \ - vga_hw_screen_dump_ptr screen_dump; \ - vga_hw_text_update_ptr text_update; \ /* hardware mouse cursor support */ \ uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; \ void (*cursor_invalidate)(struct VGAState *s); \ @@ -164,12 +162,9 @@ static inline int c6_to_8(int v) void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size); -void vga_init(VGAState *s); uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr); void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val); void vga_invalidate_scanlines(VGAState *s, int y1, int y2); -int ppm_save(const char *filename, uint8_t *data, - int w, int h, int linesize); void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1, int poffset, int w, @@ -184,5 +179,6 @@ void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1, unsigned int color0, unsigned int color1, unsigned int color_xor); +void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size); extern const uint8_t sr_mask[8]; extern const uint8_t gr_mask[16]; -- 2.39.5