]> xenbits.xensource.com Git - qemu-xen-4.4-testing.git/commitdiff
Merge changes from xen-unstable 17647 with relevant upstream changes.
authorIan Jackson <iwj@mariner.uk.xensource.com>
Fri, 23 May 2008 17:20:55 +0000 (18:20 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Fri, 23 May 2008 17:20:55 +0000 (18:20 +0100)
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
console.h
hw/cirrus_vga.c
hw/cirrus_vga_rop.h
hw/cirrus_vga_rop2.h
hw/vga.c
hw/vga_int.h

index 880ac831a5940ac76b2b6749ba8b9419ff10ecba..01636c4b32e08a1ce69119bd4a46cc551b01c05d 100644 (file)
--- 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;
index c7f29f50735e9a268b25835d55f0d83a1d3cfefa..1ac74fad3f3cf51aade6d913d838502aca04eb94 100644 (file)
--- 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);
 
index 4e9f98d3716bcd428129f82298fd48bdd3ba947d..c23fc8923e1df00914c6c934a079e94547d3216e 100644 (file)
@@ -31,6 +31,9 @@
 #include "pci.h"
 #include "console.h"
 #include "vga_int.h"
+#ifndef _WIN32
+#include <sys/mman.h>
+#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 */
index 0079d12701dbe30ac01749eeac57c2577bbfab75..15e7fe41c87e1afde351c48abf72916eef8dae19 100644 (file)
  * 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
index 137681ed1c116f8f00928ffb4e778178d3b380f3..47bbf70c0d8c724ac84a26e92feb0ccf90749af6 100644 (file)
  */
 
 #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;
index 2e7de564fd406c8d73e0d71d798e89186dab81db..73c301b8fd291acac1c4969bc5f353d8300abe1d 100644 (file)
--- 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 <signal.h>
+#include <setjmp.h>
+#include <emmintrin.h>
+
+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;
index da2c30127479eaf333684abc112257036a49d0d1..67309a66c9c0fd8bd90fc19f6c24a18e6c1117b2 100644 (file)
@@ -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
 #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;                                                   \
     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];