From: Ian Jackson Date: Thu, 12 Mar 2009 19:18:57 +0000 (+0000) Subject: Merge branch 'upstream' X-Git-Tag: xen-3.4.0-rc2~69 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=00b80c9f1183462c3015f9666ef68e588acd2c85;p=qemu-xen-3.4-testing.git Merge branch 'upstream' Conflicts: .gitignore Makefile.target block-vpc.c console.c console.h hw/cirrus_vga.c hw/ide.c hw/pc.c hw/pc.h hw/pci.h hw/vga.c hw/vga_int.h sdl.c target-ppc/translate_init.c vl.c vnc.c --- 00b80c9f1183462c3015f9666ef68e588acd2c85 diff --cc .gitignore index fb0617cf,773ce512..67e8d5d1 --- a/.gitignore +++ b/.gitignore @@@ -17,6 -17,6 +17,17 @@@ qemu-nb qemu-nbd.8 qemu-nbd.pod .gdbinit ++ ++i386-dm/Makefile ++i386-dm/config.mak ++i386-dm/qemu-dm ++i386-dm/gdbstub-xml.c ++qemu-img-xen ++qemu-nbd-xen ++dist ++*.orig ++*~ ++ *.a *.aux *.cp diff --cc Makefile index c8314c69,4f7a55ae..c395e773 --- a/Makefile +++ b/Makefile @@@ -199,15 -184,11 +193,12 @@@ libqemu_user.a: $(USER_OBJS ###################################################################### qemu-img$(EXESUF): qemu-img.o qemu-tool.o osdep.o $(BLOCK_OBJS) - $(CC) $(LDFLAGS) -o $@ $^ -lz $(LIBS) - - %.o: %.c - $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o osdep.o $(BLOCK_OBJS) - $(CC) $(LDFLAGS) -o $@ $^ -lz $(LIBS) + + qemu-img$(EXESUF) qemu-nbd$(EXESUF): LIBS += -lz + clean: # avoid old build problems by removing potentially incorrect old files rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h diff --cc Makefile.target index 7e9cbda6,372d1859..3cc3d341 --- a/Makefile.target +++ b/Makefile.target @@@ -253,12 -210,7 +212,10 @@@ endi # libqemu +-include hookslib.mak +-include hookstarget.mak + libqemu.a: $(LIBOBJS) - rm -f $@ - $(AR) rcs $@ $(LIBOBJS) translate.o: translate.c cpu.h @@@ -776,11 -717,10 +725,13 @@@ LDFLAGS+=- main.o: CFLAGS+=-p endif +-include hooks.mak +all: $(PROGS) + + $(QEMU_PROG): LIBS += $(SDL_LIBS) $(COCOA_LIBS) $(CURSES_LIBS) $(BRLAPI_LIBS) $(VDE_LIBS) + $(QEMU_PROG): $(OBJS) ../libqemu_common.a libqemu.a - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(CURSES_LIBS) $(BRLAPI_LIBS) $(VDE_LIBS) + $(LINK) endif # !CONFIG_USER_ONLY diff --cc console.c index 147daf16,68ac9706..85945491 --- a/console.c +++ b/console.c @@@ -139,11 -139,11 +139,6 @@@ struct TextConsole TextCell *cells; int text_x[2], text_y[2], cursor_invalidate; -- int update_x0; -- int update_y0; -- int update_x1; -- int update_y1; -- enum TTYState state; int esc_params[MAX_ESC_PARAMS]; int nb_esc_params; @@@ -189,7 -195,8 +184,7 @@@ static unsigned int vga_get_color(Displ { unsigned int r, g, b, color; -- switch(ds_get_bits_per_pixel(ds)) { -#if 0 ++ switch(ds->depth) { case 8: r = (rgba >> 16) & 0xff; g = (rgba >> 8) & 0xff; @@@ -222,9 -232,9 +217,9 @@@ static void vga_fill_rect (DisplayStat uint8_t *d, *d1; int x, y, bpp; -- bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; -- d1 = ds_get_data(ds) + -- ds_get_linesize(ds) * posy + bpp * posx; ++ bpp = (ds->depth + 7) >> 3; ++ d1 = ds->data + ++ ds->linesize * posy + bpp * posx; for (y = 0; y < height; y++) { d = d1; switch(bpp) { @@@ -247,7 -257,7 +242,7 @@@ } break; } -- d1 += ds_get_linesize(ds); ++ d1 += ds->linesize; } } @@@ -258,27 -268,27 +253,27 @@@ static void vga_bitblt(DisplayState *ds uint8_t *d; int wb, y, bpp; -- bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; ++ bpp = (ds->depth + 7) >> 3; wb = w * bpp; if (yd <= ys) { -- s = ds_get_data(ds) + -- ds_get_linesize(ds) * ys + bpp * xs; -- d = ds_get_data(ds) + -- ds_get_linesize(ds) * yd + bpp * xd; ++ s = ds->data + ++ ds->linesize * ys + bpp * xs; ++ d = ds->data + ++ ds->linesize * yd + bpp * xd; for (y = 0; y < h; y++) { memmove(d, s, wb); -- d += ds_get_linesize(ds); -- s += ds_get_linesize(ds); ++ d += ds->linesize; ++ s += ds->linesize; } } else { -- s = ds_get_data(ds) + -- ds_get_linesize(ds) * (ys + h - 1) + bpp * xs; -- d = ds_get_data(ds) + -- ds_get_linesize(ds) * (yd + h - 1) + bpp * xd; ++ s = ds->data + ++ ds->linesize * (ys + h - 1) + bpp * xs; ++ d = ds->data + ++ ds->linesize * (yd + h - 1) + bpp * xd; for (y = 0; y < h; y++) { memmove(d, s, wb); -- d -= ds_get_linesize(ds); -- s -= ds_get_linesize(ds); ++ d -= ds->linesize; ++ s -= ds->linesize; } } } @@@ -368,7 -378,7 +363,7 @@@ static const uint32_t color_table_rgb[2 static inline unsigned int col_expand(DisplayState *ds, unsigned int col) { -- switch(ds_get_bits_per_pixel(ds)) { ++ switch(ds->depth) { case 8: col |= col << 8; col |= col << 16; @@@ -438,13 -448,13 +433,13 @@@ static void vga_putcharxy(DisplayState bgcol = color_table[t_attrib->bold][t_attrib->bgcol]; } -- bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; -- d = ds_get_data(ds) + -- ds_get_linesize(ds) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH; -- linesize = ds_get_linesize(ds); ++ bpp = (ds->depth + 7) >> 3; ++ d = ds->data + ++ ds->linesize * y * FONT_HEIGHT + bpp * x * FONT_WIDTH; ++ linesize = ds->linesize; font_ptr = vgafont16 + FONT_HEIGHT * ch; xorcol = bgcol ^ fgcol; -- switch(ds_get_bits_per_pixel(ds)) { ++ switch(ds->depth) { case 8: for(i = 0; i < FONT_HEIGHT; i++) { font_data = *font_ptr++; @@@ -524,18 -534,26 +519,6 @@@ static void text_console_resize(TextCon 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 invalidate_xy(TextConsole *s, int x, int y) --{ -- if (s->update_x0 > x * FONT_WIDTH) -- s->update_x0 = x * FONT_WIDTH; -- if (s->update_y0 > y * FONT_HEIGHT) -- s->update_y0 = y * FONT_HEIGHT; -- if (s->update_x1 < (x + 1) * FONT_WIDTH) -- s->update_x1 = (x + 1) * FONT_WIDTH; -- if (s->update_y1 < (y + 1) * FONT_HEIGHT) -- s->update_y1 = (y + 1) * FONT_HEIGHT; --} -- static void update_xy(TextConsole *s, int x, int y) { TextCell *c; @@@ -550,7 -573,7 +533,8 @@@ c = &s->cells[y1 * s->width + x]; vga_putcharxy(s->ds, x, y2, c->ch, &(c->t_attrib)); -- invalidate_xy(s, x, y2); ++ dpy_update(s->ds, x * FONT_WIDTH, y2 * FONT_HEIGHT, ++ FONT_WIDTH, FONT_HEIGHT); } } } @@@ -561,30 -584,30 +545,22 @@@ static void console_show_cursor(TextCon int y, y1; if (s == active_console) { -- int x = s->x; -- -- if (!ds_get_bits_per_pixel(s->ds)) { -- 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)); } -- invalidate_xy(s, x, y); ++ dpy_update(s->ds, s->x * FONT_WIDTH, y * FONT_HEIGHT, ++ FONT_WIDTH, FONT_HEIGHT); } } } @@@ -596,8 -619,16 +572,8 @@@ static void console_refresh(TextConsol if (s != active_console) return; - if (!ds_get_bits_per_pixel(s->ds)) { - 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, ds_get_width(s->ds), ds_get_height(s->ds), ++ vga_fill_rect(s->ds, 0, 0, s->ds->width, s->ds->height, color_table[0][COLOR_BLACK]); y1 = s->y_displayed; for(y = 0; y < s->height; y++) { @@@ -610,8 -641,8 +586,8 @@@ if (++y1 == s->total_height) y1 = 0; } ++ dpy_update(s->ds, 0, 0, s->ds->width, s->ds->height); console_show_cursor(s, 1); -- dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds)); } static void console_scroll(int ydelta) @@@ -679,10 -718,10 +655,8 @@@ static void console_put_lf(TextConsole vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT, s->width * FONT_WIDTH, FONT_HEIGHT, color_table[0][s->t_attrib_default.bgcol]); -- s->update_x0 = 0; -- s->update_y0 = 0; -- s->update_x1 = s->width * FONT_WIDTH; -- s->update_y1 = s->height * FONT_HEIGHT; ++ dpy_update(s->ds, 0, 0, ++ s->width * FONT_WIDTH, s->height * FONT_HEIGHT); } } } @@@ -1026,21 -1061,21 +1000,20 @@@ void console_select(unsigned int index if (index >= MAX_CONSOLES) return; -- active_console->g_width = ds_get_width(active_console->ds); -- active_console->g_height = ds_get_height(active_console->ds); s = consoles[index]; if (s) { -- DisplayState *ds = s->ds; active_console = s; -- if (ds_get_bits_per_pixel(s->ds)) { - ds->surface = qemu_resize_displaysurface(ds, s->g_width, - ds->surface = qemu_resize_displaysurface(ds->surface, s->g_width, -- s->g_height, 32, 4 * s->g_width); ++ if (s->console_type == 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 { -- s->ds->surface->width = s->width; -- s->ds->surface->height = s->height; ++ vga_hw_invalidate(); } -- dpy_resize(s->ds); -- vga_hw_invalidate(); } } @@@ -1049,20 -1084,20 +1022,11 @@@ static int console_puts(CharDriverStat TextConsole *s = chr->opaque; int i; -- s->update_x0 = s->width * FONT_WIDTH; -- s->update_y0 = s->height * FONT_HEIGHT; -- s->update_x1 = 0; -- s->update_y1 = 0; console_show_cursor(s, 0); for(i = 0; i < len; i++) { console_putchar(s, buf[i]); } console_show_cursor(s, 1); -- if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) { -- dpy_update(s->ds, s->update_x0, s->update_y0, -- s->update_x1 - s->update_x0, -- s->update_y1 - s->update_y0); -- } return len; } @@@ -1156,10 -1191,10 +1120,15 @@@ void kbd_put_keysym(int keysym static void text_console_invalidate(void *opaque) { TextConsole *s = (TextConsole *) opaque; -- if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) { -- s->g_width = ds_get_width(s->ds); -- s->g_height = ds_get_height(s->ds); -- text_console_resize(s); ++ ++ 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); } @@@ -1191,18 -1226,18 +1160,6 @@@ static void text_console_update(void *o } } --static TextConsole *get_graphic_console(DisplayState *ds) --{ -- int i; -- TextConsole *s; -- for (i = 0; i < nb_consoles; i++) { -- s = consoles[i]; -- if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds) -- return s; -- } -- return NULL; --} -- static TextConsole *new_console(DisplayState *ds, console_type_t console_type) { TextConsole *s; @@@ -1225,45 -1260,44 +1182,32 @@@ } 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]->console_type == GRAPHIC_CONSOLE) break; consoles[i] = consoles[i - 1]; } consoles[i] = s; -- nb_consoles++; } return s; } --DisplayState *graphic_console_init(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 *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; -- DisplayState *ds; -- -- ds = (DisplayState *) qemu_mallocz(sizeof(DisplayState)); -- if (ds == NULL) -- return NULL; - ds->allocator = &default_allocator; - ds->surface = qemu_create_displaysurface(ds, 640, 480, 32, 640 * 4); - ds->surface = qemu_create_displaysurface(640, 480, 32, 640 * 4); s = new_console(ds, GRAPHIC_CONSOLE); -- if (s == NULL) { - qemu_free_displaysurface(ds); - qemu_free_displaysurface(ds->surface); -- qemu_free(ds); -- return NULL; -- } ++ 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; -- -- register_displaystate(ds); -- return ds; ++ return s; } int is_graphic_console(void) @@@ -1287,21 -1321,21 +1231,19 @@@ void console_color_init(DisplayState *d } } --static int n_text_consoles; --static CharDriverState *text_consoles[128]; --static char *text_console_strs[128]; -- --static void text_console_do_init(CharDriverState *chr, DisplayState *ds, const char *p) ++CharDriverState *text_console_init(DisplayState *ds, const char *p) { ++ 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); if (!s) { free(chr); -- return; ++ return NULL; } chr->opaque = s; chr->chr_write = console_puts; @@@ -1311,40 -1345,40 +1253,18 @@@ s->out_fifo.buf = s->out_fifo_buf; s->out_fifo.buf_size = sizeof(s->out_fifo_buf); s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s); -- s->ds = ds; if (!color_inited) { color_inited = 1; -- console_color_init(s->ds); ++ console_color_init(ds); } s->y_displayed = 0; s->y_base = 0; s->total_height = DEFAULT_BACKSCROLL; s->x = 0; s->y = 0; -- width = ds_get_width(s->ds); -- height = ds_get_height(s->ds); -- 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; @@@ -1360,247 -1393,248 +1280,32 @@@ text_console_resize(s); qemu_chr_reset(chr); -- if (chr->init) -- chr->init(chr); --} -- --CharDriverState *text_console_init(const char *p) --{ -- CharDriverState *chr; -- -- chr = qemu_mallocz(sizeof(CharDriverState)); -- if (!chr) -- return NULL; -- -- if (n_text_consoles == 128) { -- fprintf(stderr, "Too many text consoles\n"); -- exit(1); -- } -- text_consoles[n_text_consoles] = chr; -- text_console_strs[n_text_consoles] = p ? qemu_strdup(p) : NULL; -- n_text_consoles++; return chr; } --void text_consoles_set_display(DisplayState *ds) -{ - int i; - - for (i = 0; i < n_text_consoles; i++) { - text_console_do_init(text_consoles[i], ds, text_console_strs[i]); - qemu_free(text_console_strs[i]); - } - - n_text_consoles = 0; -} - -void qemu_console_resize(DisplayState *ds, int width, int height) -{ - TextConsole *s = get_graphic_console(ds); - if (!s) return; - - s->g_width = width; - s->g_height = height; - if (is_graphic_console()) { - ds->surface = qemu_resize_displaysurface(ds->surface, width, height, 32, 4 * width); - dpy_resize(ds); - } -} - -void qemu_console_copy(DisplayState *ds, int src_x, int src_y, - int dst_x, int dst_y, int w, int h) -{ - if (is_graphic_console()) { - dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h); - } -} - -PixelFormat qemu_different_endianness_pixelformat(int bpp) -{ - PixelFormat pf; - - memset(&pf, 0x00, sizeof(PixelFormat)); - - pf.bits_per_pixel = bpp; - pf.bytes_per_pixel = bpp / 8; - pf.depth = bpp == 32 ? 24 : bpp; - - switch (bpp) { - case 24: - pf.rmask = 0x000000FF; - pf.gmask = 0x0000FF00; - pf.bmask = 0x00FF0000; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.rshift = 0; - pf.gshift = 8; - pf.bshift = 16; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - break; - case 32: - pf.rmask = 0x0000FF00; - pf.gmask = 0x00FF0000; - pf.bmask = 0xFF000000; - pf.amask = 0x00000000; - pf.amax = 255; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.ashift = 0; - pf.rshift = 8; - pf.gshift = 16; - pf.bshift = 24; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - pf.abits = 8; - break; - default: - break; - } - return pf; -} - -PixelFormat qemu_default_pixelformat(int bpp) ++void qemu_console_resize(QEMUConsole *console, int width, int height) { - int i; - PixelFormat pf; -- - for (i = 0; i < n_text_consoles; i++) { - text_console_do_init(text_consoles[i], ds, text_console_strs[i]); - qemu_free(text_console_strs[i]); - memset(&pf, 0x00, sizeof(PixelFormat)); - - pf.bits_per_pixel = bpp; - pf.bytes_per_pixel = bpp / 8; - pf.depth = bpp == 32 ? 24 : bpp; - - switch (bpp) { - case 16: - pf.rmask = 0x0000F800; - pf.gmask = 0x000007E0; - pf.bmask = 0x0000001F; - pf.rmax = 31; - pf.gmax = 63; - pf.bmax = 31; - pf.rshift = 11; - pf.gshift = 5; - pf.bshift = 0; - pf.rbits = 5; - pf.gbits = 6; - pf.bbits = 5; - break; - case 24: - pf.rmask = 0x00FF0000; - pf.gmask = 0x0000FF00; - pf.bmask = 0x000000FF; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.rshift = 16; - pf.gshift = 8; - pf.bshift = 0; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - case 32: - pf.rmask = 0x00FF0000; - pf.gmask = 0x0000FF00; - pf.bmask = 0x000000FF; - pf.amax = 255; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.ashift = 24; - pf.rshift = 16; - pf.gshift = 8; - pf.bshift = 0; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - pf.abits = 8; - break; - default: - break; -- } - return pf; -} -- - n_text_consoles = 0; -DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize) -{ - DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface)); - if (surface == NULL) { - fprintf(stderr, "qemu_create_displaysurface: malloc failed\n"); - exit(1); - } - - surface->width = width; - surface->height = height; - surface->linesize = linesize; - surface->pf = qemu_default_pixelformat(bpp); -#ifdef WORDS_BIGENDIAN - surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG; -#else - surface->flags = QEMU_ALLOCATED_FLAG; -#endif - surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height); - if (surface->data == NULL) { - fprintf(stderr, "qemu_create_displaysurface: malloc failed\n"); - exit(1); - } - - return surface; --} -- - void qemu_console_resize(DisplayState *ds, int width, int height) -DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface, - int width, int height, int bpp, int linesize) --{ - TextConsole *s = get_graphic_console(ds); - if (!s) return; - s->g_width = width; - s->g_height = height; - if (is_graphic_console()) { - ds->surface = qemu_resize_displaysurface(ds, width, height, 32, 4 * width); - dpy_resize(ds); - surface->width = width; - surface->height = height; - surface->linesize = linesize; - surface->pf = qemu_default_pixelformat(bpp); - if (surface->flags & QEMU_ALLOCATED_FLAG) - surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height); - else - surface->data = (uint8_t*) qemu_malloc(surface->linesize * surface->height); - if (surface->data == NULL) { - fprintf(stderr, "qemu_resize_displaysurface: malloc failed\n"); - exit(1); ++ if (console->g_width != width || console->g_height != height ++ || !console->ds->data) { ++ console->g_width = width; ++ console->g_height = height; ++ if (active_console == console) { ++ dpy_resize(console->ds, width, height); ++ } } -#ifdef WORDS_BIGENDIAN - surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG; -#else - surface->flags = QEMU_ALLOCATED_FLAG; -#endif - - return surface; } - void qemu_console_copy(DisplayState *ds, int src_x, int src_y, -DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, - int linesize, uint8_t *data) ++void qemu_console_copy(QEMUConsole *console, int src_x, int src_y, + int dst_x, int dst_y, int w, int h) { - if (is_graphic_console()) { - dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h); - } - } - - PixelFormat qemu_different_endianness_pixelformat(int bpp) - { - PixelFormat pf; - - memset(&pf, 0x00, sizeof(PixelFormat)); - - pf.bits_per_pixel = bpp; - pf.bytes_per_pixel = bpp / 8; - pf.depth = bpp == 32 ? 24 : bpp; - - switch (bpp) { - case 24: - pf.rmask = 0x000000FF; - pf.gmask = 0x0000FF00; - pf.bmask = 0x00FF0000; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.rshift = 0; - pf.gshift = 8; - pf.bshift = 16; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - break; - case 32: - pf.rmask = 0x0000FF00; - pf.gmask = 0x00FF0000; - pf.bmask = 0xFF000000; - pf.amask = 0x00000000; - pf.amax = 255; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.ashift = 0; - pf.rshift = 8; - pf.gshift = 16; - pf.bshift = 24; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - pf.abits = 8; - break; - default: - break; - } - return pf; - } - - PixelFormat qemu_default_pixelformat(int bpp) - { - PixelFormat pf; - - memset(&pf, 0x00, sizeof(PixelFormat)); - - pf.bits_per_pixel = bpp; - pf.bytes_per_pixel = bpp / 8; - pf.depth = bpp == 32 ? 24 : bpp; - - switch (bpp) { - case 16: - pf.rmask = 0x0000F800; - pf.gmask = 0x000007E0; - pf.bmask = 0x0000001F; - pf.rmax = 31; - pf.gmax = 63; - pf.bmax = 31; - pf.rshift = 11; - pf.gshift = 5; - pf.bshift = 0; - pf.rbits = 5; - pf.gbits = 6; - pf.bbits = 5; - break; - case 24: - pf.rmask = 0x00FF0000; - pf.gmask = 0x0000FF00; - pf.bmask = 0x000000FF; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.rshift = 16; - pf.gshift = 8; - pf.bshift = 0; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - case 32: - pf.rmask = 0x00FF0000; - pf.gmask = 0x0000FF00; - pf.bmask = 0x000000FF; - pf.amax = 255; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.ashift = 24; - pf.rshift = 16; - pf.gshift = 8; - pf.bshift = 0; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - pf.abits = 8; - break; - default: - break; - } - return pf; - } - - DisplaySurface* defaultallocator_create_displaysurface(int width, int height, int bpp, int linesize) - { - DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface)); - if (surface == NULL) { - fprintf(stderr, "defaultallocator_create_displaysurface: malloc failed\n"); - exit(1); - } - - surface->width = width; - surface->height = height; - surface->linesize = linesize; - surface->pf = qemu_default_pixelformat(bpp); - #ifdef WORDS_BIGENDIAN - surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG; - #else - surface->flags = QEMU_ALLOCATED_FLAG; - #endif - surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height); - if (surface->data == NULL) { - fprintf(stderr, "defaultallocator_create_displaysurface: malloc failed\n"); - exit(1); - } - - return surface; - } - - DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface, - int width, int height, int bpp, int linesize) - { - surface->width = width; - surface->height = height; - surface->linesize = linesize; - surface->pf = qemu_default_pixelformat(bpp); - if (surface->flags & QEMU_ALLOCATED_FLAG) - surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height); - else - surface->data = (uint8_t*) qemu_malloc(surface->linesize * surface->height); - if (surface->data == NULL) { - fprintf(stderr, "defaultallocator_resize_displaysurface: malloc failed\n"); - exit(1); - } - #ifdef WORDS_BIGENDIAN - surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG; - #else - surface->flags = QEMU_ALLOCATED_FLAG; - #endif - - return surface; - } - - DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, - int linesize, uint8_t *data) - { -- DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface)); -- if (surface == NULL) { -- fprintf(stderr, "qemu_create_displaysurface_from: malloc failed\n"); -- exit(1); ++ if (active_console == console) { ++ if (console->ds->dpy_copy) ++ console->ds->dpy_copy(console->ds, ++ src_x, src_y, dst_x, dst_y, w, h); ++ else { ++ /* TODO */ ++ console->ds->dpy_update(console->ds, dst_x, dst_y, w, h); ++ } } -- -- surface->width = width; -- surface->height = height; -- surface->linesize = linesize; -- surface->pf = qemu_default_pixelformat(bpp); --#ifdef WORDS_BIGENDIAN -- surface->flags = QEMU_BIG_ENDIAN_FLAG; --#endif -- surface->data = data; -- -- return surface; --} -- - void defaultallocator_free_displaysurface(DisplaySurface *surface) -void qemu_free_displaysurface(DisplaySurface *surface) --{ -- if (surface == NULL) -- return; -- if (surface->flags & QEMU_ALLOCATED_FLAG) -- qemu_free(surface->data); -- qemu_free(surface); } diff --cc console.h index f9b8e277,4a2f06fb..d0a99c60 --- a/console.h +++ b/console.h @@@ -92,52 -109,141 +92,27 @@@ struct DisplayState 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); - - struct DisplayChangeListener *next; }; -struct DisplayState { - struct DisplaySurface *surface; - void *opaque; - struct QEMUTimer *gui_timer; - - struct DisplayChangeListener* listeners; - - 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); - - struct DisplayState *next; -}; - -void register_displaystate(DisplayState *ds); -DisplayState *get_displaystate(void); -DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize); -DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface, - int width, int height, int bpp, int linesize); -DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, - int linesize, uint8_t *data); -void qemu_free_displaysurface(DisplaySurface *surface); -PixelFormat qemu_different_endianness_pixelformat(int bpp); -PixelFormat qemu_default_pixelformat(int bpp); - -static inline int is_buffer_shared(DisplaySurface *surface) -{ - return (!(surface->flags & QEMU_ALLOCATED_FLAG)); -} - -static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) -{ - dcl->next = ds->listeners; - ds->listeners = dcl; -} - static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - dcl->dpy_update(s, x, y, w, h); - dcl = dcl->next; - } -} - -static inline void dpy_resize(DisplayState *s) -{ - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - dcl->dpy_resize(s); - dcl = dcl->next; - } + s->dpy_update(s, x, y, w, h); } -static inline void dpy_setdata(DisplayState *s) +static inline void dpy_resize(DisplayState *s, int w, int h) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_setdata) dcl->dpy_setdata(s); - dcl = dcl->next; - } + s->dpy_resize(s, w, h); } - -static inline void dpy_refresh(DisplayState *s) +static inline void dpy_resize_shared(DisplayState *s, int w, int h, int depth, int linesize, void *pixels) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_refresh) dcl->dpy_refresh(s); - dcl = dcl->next; - } -} - -static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y, - int dst_x, int dst_y, int w, int h) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_copy) - dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h); - else /* TODO */ - dcl->dpy_update(s, dst_x, dst_y, w, h); - dcl = dcl->next; - } + s->dpy_resize_shared(s, w, h, depth, linesize, pixels); } - -static inline void dpy_fill(struct DisplayState *s, int x, int y, - int w, int h, uint32_t c) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_fill) dcl->dpy_fill(s, x, y, w, h, c); - dcl = dcl->next; - } -} - -static inline void dpy_cursor(struct DisplayState *s, int x, int y) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_text_cursor) dcl->dpy_text_cursor(s, x, y); - dcl = dcl->next; - } -} - -static inline int ds_get_linesize(DisplayState *ds) -{ - return ds->surface->linesize; -} - -static inline uint8_t* ds_get_data(DisplayState *ds) +static inline void dpy_cursor(DisplayState *s, int x, int y) { - return ds->surface->data; -} - -static inline int ds_get_width(DisplayState *ds) -{ - return ds->surface->width; -} - -static inline int ds_get_height(DisplayState *ds) -{ - return ds->surface->height; -} - -static inline int ds_get_bits_per_pixel(DisplayState *ds) -{ - return ds->surface->pf.bits_per_pixel; -} - -static inline int ds_get_bytes_per_pixel(DisplayState *ds) -{ - return ds->surface->pf.bytes_per_pixel; + if (s->dpy_text_cursor) + s->dpy_text_cursor(s, x, y); } - static inline int ds_get_linesize(DisplayState *ds) - { - return ds->linesize; - } - - static inline uint8_t* ds_get_data(DisplayState *ds) - { - return ds->data; - } - - static inline int ds_get_width(DisplayState *ds) - { - return ds->width; - } - - static inline int ds_get_height(DisplayState *ds) - { - return ds->height; - } - - static inline int ds_get_bits_per_pixel(DisplayState *ds) - { - return ds->depth; - } - typedef unsigned long console_ch_t; static inline void console_write_ch(console_ch_t *dest, uint32_t ch) { diff --cc hw/cirrus_vga.c index cb22c389,d261e40e..91d248eb --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@@ -2648,9 -2625,8 +2640,11 @@@ static CPUWriteMemoryFunc *cirrus_linea static void map_linear_vram(CirrusVGAState *s) { + if (s->lfb_addr && s->lfb_end && s->vram_gmfn != s->lfb_addr) { + set_vram_mapping(s, s->lfb_addr, s->lfb_end); + } + vga_dirty_log_stop((VGAState *)s); + if (!s->map_addr && s->lfb_addr && s->lfb_end) { s->map_addr = s->lfb_addr; s->map_end = s->lfb_end; @@@ -2685,13 -2660,10 +2678,13 @@@ static void unmap_linear_vram(CirrusVGAState *s) { + if (s->lfb_addr && s->lfb_end && s->vram_gmfn != s->lfb_addr) { + unset_vram_mapping(s); + } - if (s->map_addr && s->lfb_addr && s->lfb_end) { - vga_dirty_log_stop((VGAState *)s); + vga_dirty_log_stop((VGAState *)s); + + if (s->map_addr && s->lfb_addr && s->lfb_end) s->map_addr = s->map_end = 0; - } cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000, s->vga_io_memory); @@@ -3348,9 -3253,36 +3310,36 @@@ static void cirrus_init_common(CirrusVG s->vga_io_memory); qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000); + /* I/O handler for LFB */ + s->cirrus_linear_io_addr = + cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write, s); + s->cirrus_linear_write = cpu_get_io_memory_write(s->cirrus_linear_io_addr); + + /* I/O handler for LFB */ + s->cirrus_linear_bitblt_io_addr = + cpu_register_io_memory(0, cirrus_linear_bitblt_read, + cirrus_linear_bitblt_write, s); + + /* I/O handler for memory-mapped I/O */ + s->cirrus_mmio_io_addr = + cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s); + + s->real_vram_size = + (s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024; + + /* XXX: s->vram_size must be a power of two */ + s->cirrus_addr_mask = s->real_vram_size - 1; + s->linear_mmio_mask = s->real_vram_size - 256; + + s->get_bpp = cirrus_get_bpp; + s->get_offsets = cirrus_get_offsets; + s->get_resolution = cirrus_get_resolution; + s->cursor_invalidate = cirrus_cursor_invalidate; + s->cursor_draw_line = cirrus_cursor_draw_line; + qemu_register_reset(cirrus_reset, s); cirrus_reset(s); - register_savevm("cirrus_vga", 0, 2, cirrus_vga_save, cirrus_vga_load, s); + register_savevm("cirrus_vga", 0, 3, cirrus_vga_save, cirrus_vga_load, s); } /*************************************** @@@ -3372,8 -3299,10 +3361,8 @@@ void isa_cirrus_vga_init(uint8_t *vga_r s = qemu_mallocz(sizeof(CirrusVGAState)); vga_common_init((VGAState *)s, - ds, vga_ram_base, vga_ram_offset, vga_ram_size); + vga_ram_base, vga_ram_offset, vga_ram_size); cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0); - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); /* XXX ISA-LFB support */ } @@@ -3430,32 -3373,23 +3439,29 @@@ void pci_cirrus_vga_init(PCIBus *bus, u /* setup PCI configuration registers */ d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA", sizeof(PCICirrusVGAState), - -1, NULL, NULL); + -1, NULL, pci_cirrus_write_config); pci_conf = d->dev.config; - pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff); - pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8); - pci_conf[0x02] = (uint8_t) (device_id & 0xff); - pci_conf[0x03] = (uint8_t) (device_id >> 8); + pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_CIRRUS); + pci_config_set_device_id(pci_conf, device_id); pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS; - pci_conf[0x0a] = PCI_CLASS_SUB_VGA; - pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY; + pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA); 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; + + if (vga_ram_size != 4*1024*1024) { + fprintf(stderr, "The -videoram option does not work with the cirrus vga model. Video ram set to 4M. \n"); + vga_ram_size = 4*1024*1024; + } /* setup VGA */ s = &d->cirrus_vga; vga_common_init((VGAState *)s, - ds, vga_ram_base, vga_ram_offset, vga_ram_size); + vga_ram_base, vga_ram_offset, vga_ram_size); cirrus_init_common(s, device_id, 1); - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); - s->pci_dev = (PCIDevice *)d; /* setup memory space */ diff --cc hw/ide.c index 42920b07,bcaee46a..7031ba1f --- a/hw/ide.c +++ b/hw/ide.c @@@ -503,178 -505,8 +511,179 @@@ typedef struct PCIIDEState int type; /* see IDE_TYPE_xxx */ } PCIIDEState; +static PCIIDEState *principal_ide_controller; + +#if defined(__ia64__) +#include + +struct buffered_piopage *buffered_pio_page; + +static inline struct pio_buffer * +piobuf_by_addr(uint32_t addr) +{ + if (addr == 0x1F0) + return &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY]; + if (addr == 0x170) + return &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY]; + return NULL; +} + +static void +buffered_pio_init(void) +{ + struct pio_buffer *p1, *p2; + uint32_t off1, off2; + + if (!buffered_pio_page) + return; + + p1 = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY]; + p2 = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY]; + off1 = offsetof(struct buffered_piopage, buffer); + off2 = (off1 + TARGET_PAGE_SIZE)/2; + + p1->buf_size = off2 - off1; + p1->page_offset = off1; + + p2->buf_size = TARGET_PAGE_SIZE - off2; + p2->page_offset = off2; +} + +static inline void +__buffered_pio_flush(struct pio_buffer *piobuf, IDEState *s, uint32_t pointer) +{ + uint8_t *buf = (uint8_t *)buffered_pio_page + piobuf->page_offset; + memcpy(s->data_ptr, buf, pointer); + s->data_ptr += pointer; +} + +static inline void +buffered_pio_flush(struct pio_buffer *piobuf) +{ + IDEState *s = piobuf->opaque; + uint32_t pointer = piobuf->pointer; + + if (s != NULL && pointer > 0) + __buffered_pio_flush(piobuf, s, pointer); +} + +static inline void +buffered_pio_reset(IDEState *s) +{ + struct pio_buffer *piobuf; + + if ((unsigned)s->drive_serial - 1 < 2) /* 1,2 */ + piobuf = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY]; + else if ((unsigned)s->drive_serial - 3 < 2) /* 3,4 */ + piobuf = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY]; + else + return; + buffered_pio_flush(piobuf); + piobuf->pointer = 0; + piobuf->data_end = 0; + piobuf->opaque = NULL; +} + +static inline void +buffered_pio_write(IDEState *s, uint32_t addr, int size) +{ + struct pio_buffer *piobuf = piobuf_by_addr(addr); + int data_end; + + if (!piobuf) + return; + buffered_pio_flush(piobuf); + data_end = s->data_end - s->data_ptr - size; + if (data_end <= 0) + data_end = 0; + else if (data_end > piobuf->buf_size) + data_end = piobuf->buf_size; + piobuf->pointer = 0; + piobuf->data_end = data_end; + piobuf->opaque = s; +} + +static inline void +buffered_pio_read(IDEState *s, uint32_t addr, int size) +{ + struct pio_buffer *piobuf = piobuf_by_addr(addr); + int data_end; + + if (!piobuf) + return; + s->data_ptr += piobuf->pointer; + data_end = s->data_end - s->data_ptr - size; + if (data_end <= 0) { + data_end = 0; + } else { + uint8_t *buf = (uint8_t *)buffered_pio_page + piobuf->page_offset; + if (data_end > piobuf->buf_size) + data_end = piobuf->buf_size; + memcpy(buf, s->data_ptr + size, data_end); + } + piobuf->pointer = 0; + piobuf->data_end = data_end; + piobuf->opaque = NULL; +} + +/* + * buffered pio reads are undone. It results in normal pio when the domain + * is restored. + * buffered pio writes are handled before saving domain. + * However currently pci_ide_save/load() just discards a pending transfer. XXX + */ +static void +__handle_buffered_pio(struct pio_buffer *piobuf) +{ + IDEState *s = piobuf->opaque; + uint32_t pointer = piobuf->pointer; + + + if (pointer == 0) + return;/* no buffered pio */ + + if (s != NULL) { + /* written data are pending in pio_buffer. process it */ + __buffered_pio_flush(piobuf, s, pointer); + } else { + /* data are buffered for pio read in pio_buffer. + * undone buffering by buffered_pio_read() + */ + if (pointer > s->data_ptr - s->io_buffer) + pointer = s->data_ptr - s->io_buffer; + s->data_ptr -= pointer; + } + + piobuf->pointer = 0; + piobuf->data_end = 0; + piobuf->opaque = NULL; +} + +void +handle_buffered_pio(void) +{ + struct pio_buffer *p1, *p2; + + if (!buffered_pio_page) + return; + + p1 = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY]; + p2 = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY]; + + __handle_buffered_pio(p1); + __handle_buffered_pio(p2); +} + +#else /* !__ia64__ */ +#define buffered_pio_init() do {} while (0) +#define buffered_pio_reset(I) do {} while (0) +#define buffered_pio_write(I,A,S) do {} while (0) +#define buffered_pio_read(I,A,S) do {} while (0) +#endif + + static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb); + static void ide_dma_restart(IDEState *s); static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret); static void padstr(char *str, const char *src, int len) @@@ -1094,14 -1006,39 +1187,47 @@@ static int dma_buf_rw(BMDMAState *bm, i return 1; } + typedef struct { + BMDMAState *bm; + void (*cb)(void *opaque, int ret); + QEMUBH *bh; + } MapFailureContinuation; + + static void reschedule_dma(void *opaque) + { + MapFailureContinuation *cont = opaque; + + cont->cb(cont->bm, 0); + qemu_bh_delete(cont->bh); + qemu_free(cont); + } + + static void continue_after_map_failure(void *opaque) + { + MapFailureContinuation *cont = opaque; + + cont->bh = qemu_bh_new(reschedule_dma, opaque); + qemu_bh_schedule(cont->bh); + } + + static void wait_for_bounce_buffer(BMDMAState *bmdma, + void (*cb)(void *opaque, int ret)) + { + MapFailureContinuation *cont = qemu_malloc(sizeof(*cont)); + + cont->bm = bmdma; + cont->cb = cb; + cpu_register_map_client(cont, continue_after_map_failure); + } + +static void ide_dma_eot(BMDMAState *bm) { + bm->status &= ~BM_STATUS_DMAING; + bm->status |= BM_STATUS_INT; + bm->dma_cb = NULL; + bm->ide_if = NULL; + bm->aiocb = NULL; +} + static void ide_read_dma_cb(void *opaque, int ret) { BMDMAState *bm = opaque; @@@ -1177,12 -1121,10 +1308,14 @@@ static void ide_sector_write(IDEState * if (n > s->req_nb_sectors) n = s->req_nb_sectors; ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); + + if (ret == 0 && !s->write_cache) { + ret = bdrv_flush(s->bs); + } ++ if (ret != 0) { - ide_rw_error(s); - return; + if (ide_handle_write_error(s, -ret, BM_STATUS_PIO_RETRY)) + return; } s->nsector -= n; @@@ -1214,20 -1156,20 +1347,34 @@@ } } +static void ide_write_flush_cb(void *opaque, int ret) { + BMDMAState *bm = opaque; + IDEState *s = bm->ide_if; + + if (ret != 0) { + ide_dma_error(s); + return; + } + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + ide_dma_eot(bm); + return; +} + + static void ide_dma_restart_cb(void *opaque, int running, int reason) + { + BMDMAState *bm = opaque; + if (!running) + return; + if (bm->status & BM_STATUS_DMA_RETRY) { + bm->status &= ~BM_STATUS_DMA_RETRY; + ide_dma_restart(bm->ide_if); + } else if (bm->status & BM_STATUS_PIO_RETRY) { + bm->status &= ~BM_STATUS_PIO_RETRY; + ide_sector_write(bm->ide_if); + } + } + static void ide_write_dma_cb(void *opaque, int ret) { BMDMAState *bm = opaque; @@@ -1236,12 -1178,10 +1383,12 @@@ int64_t sector_num; if (ret < 0) { - ide_dma_error(s); - return; + if (ide_handle_write_error(s, -ret, BM_STATUS_DMA_RETRY)) + return; } + if (!s->bs) return; /* ouch! (see ide_flush_cb) */ + n = s->io_buffer_size >> 9; sector_num = ide_get_sector(s); if (n > 0) { @@@ -3396,7 -3262,7 +3565,7 @@@ static int pci_ide_load(QEMUFile* f, vo PCIIDEState *d = opaque; int ret, i; - if (version_id != 1 && version_id != 2) - if (version_id != 2) ++ if (version_id != 3) return -EINVAL; ret = pci_device_load(&d->dev, f); if (ret < 0) @@@ -3474,15 -3345,10 +3648,13 @@@ void pci_cmd646_ide_init(PCIBus *bus, B sizeof(PCIIDEState), -1, NULL, NULL); + if (principal_ide_controller) + abort(); + principal_ide_controller = d; d->type = IDE_TYPE_CMD646; pci_conf = d->dev.config; - pci_conf[0x00] = 0x95; // CMD646 - pci_conf[0x01] = 0x10; - pci_conf[0x02] = 0x46; - pci_conf[0x03] = 0x06; + pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_CMD); + pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_CMD_646); pci_conf[0x08] = 0x07; // IDE controller revision pci_conf[0x09] = 0x8f; @@@ -3517,7 -3382,7 +3688,7 @@@ ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], irq[0]); ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], irq[1]); - register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d); - register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d); ++ register_savevm("ide", 0, 3, pci_ide_save, pci_ide_load, d); qemu_register_reset(cmd646_reset, d); cmd646_reset(d); } @@@ -3557,18 -3419,11 +3728,15 @@@ void pci_piix3_ide_init(PCIBus *bus, Bl d->type = IDE_TYPE_PIIX3; pci_conf = d->dev.config; - pci_conf[0x00] = 0x86; // Intel - pci_conf[0x01] = 0x80; - pci_conf[0x02] = 0x10; - pci_conf[0x03] = 0x70; + pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL); + pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_1); pci_conf[0x09] = 0x80; // legacy ATA mode - pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE - pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage + pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE); pci_conf[0x0e] = 0x00; // header_type + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; qemu_register_reset(piix3_reset, d); piix3_reset(d); @@@ -3581,9 -3436,7 +3749,9 @@@ ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6); ide_init_ioport(&d->ide_if[2], 0x170, 0x376); - register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d); + buffered_pio_init(); + - register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d); ++ register_savevm("ide", 0, 3, pci_ide_save, pci_ide_load, d); } /* hd_table must contain 4 block drivers */ @@@ -3602,18 -3455,11 +3770,15 @@@ void pci_piix4_ide_init(PCIBus *bus, Bl d->type = IDE_TYPE_PIIX4; pci_conf = d->dev.config; - pci_conf[0x00] = 0x86; // Intel - pci_conf[0x01] = 0x80; - pci_conf[0x02] = 0x11; - pci_conf[0x03] = 0x71; + pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL); + pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB); pci_conf[0x09] = 0x80; // legacy ATA mode - pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE - pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage + pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE); pci_conf[0x0e] = 0x00; // header_type + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; qemu_register_reset(piix3_reset, d); piix3_reset(d); @@@ -3626,11 -3472,10 +3791,12 @@@ ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6); ide_init_ioport(&d->ide_if[2], 0x170, 0x376); - register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d); + buffered_pio_init(); + - register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d); ++ register_savevm("ide", 0, 3, pci_ide_save, pci_ide_load, d); } + #if defined(TARGET_PPC) /***********************************************************/ /* MacIO based PowerPC IDE */ diff --cc hw/ne2000.c index 0cb1c4aa,1bad3fdf..0a25a9d8 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@@ -822,17 -790,10 +822,14 @@@ void pci_ne2000_init(PCIBus *bus, NICIn devfn, NULL, NULL); pci_conf = d->dev.config; - pci_conf[0x00] = 0xec; // Realtek 8029 - pci_conf[0x01] = 0x10; - pci_conf[0x02] = 0x29; - pci_conf[0x03] = 0x80; - pci_conf[0x0a] = 0x00; // ethernet network controller - pci_conf[0x0b] = 0x02; + pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REALTEK); + pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_REALTEK_RTL8029); + pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET); pci_conf[0x0e] = 0x00; // header_type + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; pci_conf[0x3d] = 1; // interrupt pin 0 pci_register_io_region(&d->dev, 0, 0x100, diff --cc hw/pc.c index 2ffbefdb,176730e0..81e0935c --- a/hw/pc.c +++ b/hw/pc.c @@@ -772,11 -752,10 +772,11 @@@ static void pc_init_ne2k_isa(NICInfo *n /* PC hardware initialisation */ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, - const char *boot_device, DisplayState *ds, + const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, - int pci_enabled, const char *cpu_model) + int pci_enabled, const char *cpu_model, + const char *direct_pci) { char buf[1024]; int ret, linux_boot, i; @@@ -996,22 -968,7 +996,22 @@@ vga_bios_error } } +#ifdef CONFIG_PASSTHROUGH + /* Pass-through Initialization + * init libpci even direct_pci is null, as can hotplug a dev runtime + */ + if ( pci_enabled ) + { + rc = pt_init(pci_bus, direct_pci); + if ( rc < 0 ) + { + fprintf(logfile, "Error: Initialization failed for pass-through devices\n"); + exit(1); + } + } +#endif + - rtc_state = rtc_init(0x70, i8259[8]); + rtc_state = rtc_init(0x70, i8259[8], 2000); qemu_register_boot_set(pc_boot_set, rtc_state); @@@ -1177,13 -1115,11 +1177,13 @@@ static void pc_init_pci(ram_addr_t ram_ const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, - const char *cpu_model) + const char *cpu_model, + const char *direct_pci) { - pc_init1(ram_size, vga_ram_size, boot_device, ds, + pc_init1(ram_size, vga_ram_size, boot_device, kernel_filename, kernel_cmdline, - initrd_filename, 1, cpu_model); + initrd_filename, 1, cpu_model, + direct_pci); } static void pc_init_isa(ram_addr_t ram_size, int vga_ram_size, @@@ -1191,21 -1127,11 +1191,21 @@@ const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, - const char *cpu_model) + const char *cpu_model, + const char *direct_pci) { - pc_init1(ram_size, vga_ram_size, boot_device, ds, + pc_init1(ram_size, vga_ram_size, boot_device, kernel_filename, kernel_cmdline, - initrd_filename, 0, cpu_model); + initrd_filename, 0, cpu_model, + direct_pci); +} + +/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE) + BIOS will read it and start S3 resume at POST Entry*/ +void cmos_set_s3_resume(void) +{ + if (rtc_state) + rtc_set_memory(rtc_state, 0xF, 0xFE); } /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE) diff --cc hw/pc.h index 0a8f8e3d,c67294d0..5a43c958 --- a/hw/pc.h +++ b/hw/pc.h @@@ -130,12 -127,18 +131,18 @@@ enum vga_retrace_method extern enum vga_retrace_method vga_retrace_method; + #ifndef TARGET_SPARC + #define VGA_RAM_SIZE (8192 * 1024) + #else + #define VGA_RAM_SIZE (9 * 1024 * 1024) + #endif + -int isa_vga_init(uint8_t *vga_ram_base, +int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size); -int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base, +int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size, unsigned long vga_bios_offset, int vga_bios_size); -int isa_vga_mm_init(uint8_t *vga_ram_base, +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); diff --cc hw/pci.h index 7645cd43,edb05949..6136845b --- a/hw/pci.h +++ b/hw/pci.h @@@ -131,30 -224,27 +229,48 @@@ int pci_bus_num(PCIBus *s) void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d)); void pci_info(void); - PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id, + PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did, pci_map_irq_fn map_irq, const char *name); +/* PCI slot 6~7 support ACPI PCI hot plug */ +#define PHP_SLOT_START (6) +#define PHP_SLOT_END (8) +#define PHP_SLOT_LEN (PHP_SLOT_END - PHP_SLOT_START) +#define PHP_TO_PCI_SLOT(x) (x + PHP_SLOT_START) +#define PCI_TO_PHP_SLOT(x) (x - PHP_SLOT_START) +#define PHP_DEVFN_START (PHP_SLOT_START << 3) +#define PHP_DEVFN_END (PHP_SLOT_END << 3) + +int insert_to_pci_slot(char*); +int test_pci_slot(int); +int bdf_to_slot(char*); +int power_on_php_slot(int); +int power_off_php_slot(int); + +/* pci_emulation.c */ +#include "hw/pci_emulation.h" + +void do_pci_add(char *devname); +void do_pci_del(char *devname); + + static inline void + pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val) + { + cpu_to_le16wu((uint16_t *)&pci_config[PCI_VENDOR_ID], val); + } + + static inline void + pci_config_set_device_id(uint8_t *pci_config, uint16_t val) + { + cpu_to_le16wu((uint16_t *)&pci_config[PCI_DEVICE_ID], val); + } + + static inline void + pci_config_set_class(uint8_t *pci_config, uint16_t val) + { + cpu_to_le16wu((uint16_t *)&pci_config[PCI_CLASS_DEVICE], val); + } + /* lsi53c895a.c */ #define LSI_MAX_DEVS 7 void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id); diff --cc hw/pcnet.c index 3f303305,828d9801..2e20db06 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@@ -1929,9 -1929,8 +1929,9 @@@ static int pcnet_load(QEMUFile *f, voi return 0; } - static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str) + static void pcnet_common_init(PCNetState *d, NICInfo *nd) { + int instance; d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d); d->nd = nd; diff --cc hw/piix_pci.c index 54c1559b,53e20a0a..36127a4b --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@@ -207,20 -190,15 +207,17 @@@ PCIBus *i440fx_init(PCIDevice **pi440fx register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s); d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0, - NULL, i440fx_write_config); + NULL, NULL); - d->config[0x00] = 0x86; // vendor_id - d->config[0x01] = 0x80; - d->config[0x02] = 0x37; // device_id - d->config[0x03] = 0x12; + pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL); + pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_82441); d->config[0x08] = 0x02; // revision - d->config[0x0a] = 0x00; // class_sub = host2pci - d->config[0x0b] = 0x06; // class_base = PCI_bridge + pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); d->config[0x0e] = 0x00; // header_type +#ifndef CONFIG_DM d->config[0x72] = 0x02; /* SMRAM */ +#endif /* !CONFIG_DM */ register_savevm("I440FX", 0, 2, i440fx_save, i440fx_load, d); *pi440fx_state = d; diff --cc hw/scsi-disk.c index d7999834,c4d7d520..9745ca33 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@@ -39,15 -39,11 +39,17 @@@ do { fprintf(stderr, "scsi-disk: " fmt #define STATUS_GOOD 0 #define STATUS_CHECK_CONDITION 2 +#ifdef CONFIG_STUBDOM +#include +#define SCSI_DMA_BUF_SIZE ((BLKIF_MAX_SEGMENTS_PER_REQUEST - 1) * PAGE_SIZE) +#else #define SCSI_DMA_BUF_SIZE 131072 +#endif + #define SCSI_MAX_INQUIRY_LEN 256 + #define SCSI_REQ_STATUS_RETRY 0x01 + typedef struct SCSIRequest { SCSIDeviceState *dev; uint32_t tag; diff --cc hw/vga.c index 13519255,bad120ba..d1d61ea1 --- a/hw/vga.c +++ b/hw/vga.c @@@ -1164,7 -1152,7 +1164,7 @@@ static int update_basic_params(VGAStat static inline int get_depth_index(DisplayState *s) { -- switch(ds_get_bits_per_pixel(s)) { ++ switch(s->depth) { default: case 8: return 0; @@@ -1173,7 -1161,7 +1173,10 @@@ case 16: return 2; case 32: -- return 3; ++ if (s->bgr) ++ return 4; ++ else ++ return 3; } } @@@ -1245,51 -1276,8 +1248,51 @@@ static void vga_draw_text(VGAState *s, vga_draw_glyph8_func *vga_draw_glyph8; vga_draw_glyph9_func *vga_draw_glyph9; - vga_dirty_log_stop(s); + /* Disable dirty bit tracking */ + xc_hvm_track_dirty_vram(xc_handle, domid, 0, 0, NULL); + + /* 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; + } + if ((height * width) > CH_ATTR_SIZE) { + /* better than nothing: exit if transient size is too big */ + return; + } + ++ s->last_scr_width = width * cw; ++ s->last_scr_height = height * cheight; + if (width != s->last_width || height != s->last_height || + cw != s->last_cw || cheight != s->last_ch || s->last_depth) { - s->last_scr_width = width * cw; - s->last_scr_height = height * cheight; - qemu_console_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_depth = 0; - s->last_width = width; - s->last_height = height; - s->last_ch = cheight; - s->last_cw = cw; + full_update = 1; + } ++ s->last_width = width; ++ s->last_height = height; ++ s->last_ch = cheight; ++ s->last_cw = cw; + + s->rgb_to_pixel = + rgb_to_pixel_dup_table[get_depth_index(s->ds)]; + full_update |= update_palette16(s); + palette = s->last_palette; + - x_incr = cw * ds_get_bytes_per_pixel(s->ds); ++ x_incr = cw * ((s->ds->depth + 7) >> 3); /* compute font data address (in plane 2) */ v = s->sr[3]; offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2; @@@ -1316,34 -1304,19 +1319,34 @@@ line_offset = s->line_offset; s1 = s->vram_ptr + (s->start_addr * 4); - vga_get_text_resolution(s, &width, &height, &cw, &cheight); - x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); + /* 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 */ - x_incr = cw * ds_get_bytes_per_pixel(s->ds); ++ x_incr = cw * ((s->ds->depth + 7) >> 3); + 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; + } if ((height * width) > CH_ATTR_SIZE) { /* better than nothing: exit if transient size is too big */ return; } if (width != s->last_width || height != s->last_height || - cw != s->last_cw || cheight != s->last_ch || s->last_depth) { + cw != s->last_cw || cheight != s->last_ch) { s->last_scr_width = width * cw; s->last_scr_height = height * cheight; -- qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height); - s->last_depth = 0; ++ qemu_console_resize(s->console, s->last_scr_width, s->last_scr_height); s->last_width = width; s->last_height = height; s->last_ch = cheight; @@@ -1373,8 -1352,8 +1376,8 @@@ vga_draw_glyph8 = vga_draw_glyph8_table[depth_index]; vga_draw_glyph9 = vga_draw_glyph9_table[depth_index]; -- dest = ds_get_data(s->ds); -- linesize = ds_get_linesize(s->ds); ++ dest = s->ds->data; ++ linesize = s->ds->linesize; ch_attr_ptr = s->last_ch_attr; for(cy = 0; cy < height; cy++) { d1 = dest; @@@ -1612,50 -1615,46 +1615,38 @@@ static void vga_draw_graphic(VGAState * s->shift_control = shift_control; s->double_scan = double_scan; } + if (shift_control == 1 && (s->sr[0x01] & 8)) { + disp_width <<= 1; + } - ds_depth = ds_get_bits_per_pixel(s->ds); ++ ds_depth = s->ds->depth; depth = s->get_bpp(s); - if (s->line_offset != s->last_line_offset || - if (s->line_offset != s->last_line_offset || -- disp_width != s->last_width || -- height != s->last_height || -- s->last_depth != depth) { --#if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) -- if (depth == 16 || depth == 32) { --#else -- if (depth == 32) { --#endif -- if (is_graphic_console()) { - qemu_free_displaysurface(s->ds); - qemu_free_displaysurface(s->ds->surface); -- s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth, -- s->line_offset, -- s->vram_ptr + (s->start_addr * 4)); --#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) -- s->ds->surface->pf = qemu_different_endianness_pixelformat(depth); --#endif -- dpy_resize(s->ds); -- } else { -- qemu_console_resize(s->ds, disp_width, height); -- } -- } else { -- qemu_console_resize(s->ds, disp_width, height); -- } ++ if (s->ds->dpy_resize_shared) { ++ if (s->line_offset != s->last_line_offset || ++ disp_width != s->last_width || ++ height != s->last_height || ++ s->last_depth != depth) { ++ dpy_resize_shared(s->ds, disp_width, height, depth, s->line_offset, s->vram_ptr + (s->start_addr * 4)); ++ 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; ++ s->last_depth = depth; ++ full_update = 1; ++ } else 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)); ++ } else if (disp_width != s->last_width || ++ height != s->last_height) { ++ dpy_resize(s->ds, disp_width, height); 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; -- s->last_depth = depth; full_update = 1; -- } else if (is_graphic_console() && is_buffer_shared(s->ds->surface) && -- (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) { -- s->ds->surface->data = s->vram_ptr + (s->start_addr * 4); -- dpy_setdata(s->ds); } - s->rgb_to_pixel = + s->rgb_to_pixel = rgb_to_pixel_dup_table[get_depth_index(s->ds)]; if (shift_control == 0) { @@@ -1705,9 -1706,9 +1696,9 @@@ break; } } - vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)]; - if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate) + vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)]; - if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate) ++ if (!s->ds->shared_buf && s->cursor_invalidate) s->cursor_invalidate(s); line_offset = s->line_offset; @@@ -1766,10 -1719,10 +1757,10 @@@ addr1 = (s->start_addr * 4); bwidth = (width * bits + 7) / 8; y_start = -1; - page_min = 0x7fffffff; - page_max = -1; - d = ds_get_data(s->ds); - linesize = ds_get_linesize(s->ds); + page_min = 0; + page_max = 0; - d = ds_get_data(s->ds); - linesize = ds_get_linesize(s->ds); ++ d = s->ds->data; ++ linesize = s->ds->linesize; y1 = 0; for(y = 0; y < height; y++) { addr = addr1; @@@ -1797,11 -1750,11 +1788,11 @@@ 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; - if (!is_buffer_shared(s->ds->surface)) { - if (!(is_buffer_shared(s->ds->surface))) { ++ 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); @@@ -1856,15 -1807,15 +1847,15 @@@ static void vga_draw_blank(VGAState *s s->rgb_to_pixel = rgb_to_pixel_dup_table[get_depth_index(s->ds)]; -- if (ds_get_bits_per_pixel(s->ds) == 8) ++ if (s->ds->depth == 8) val = s->rgb_to_pixel(0, 0, 0); else val = 0; - w = s->last_scr_width * ds_get_bytes_per_pixel(s->ds); - w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); -- d = ds_get_data(s->ds); ++ w = s->last_scr_width * ((s->ds->depth + 7) >> 3); ++ d = s->ds->data; for(i = 0; i < s->last_scr_height; i++) { memset(d, val, w); -- d += ds_get_linesize(s->ds); ++ d += s->ds->linesize; } dpy_update(s->ds, 0, 0, s->last_scr_width, s->last_scr_height); @@@ -1879,7 -1830,7 +1870,7 @@@ static void vga_update_display(void *op VGAState *s = (VGAState *)opaque; int full_update, graphic_mode; -- if (ds_get_bits_per_pixel(s->ds) == 0) { ++ if (s->ds->depth == 0) { /* nothing to do */ } else { full_update = 0; @@@ -1989,9 -2003,9 +1980,7 @@@ static void vga_update_text(void *opaqu cw != s->last_cw || cheight != s->last_ch) { s->last_scr_width = width * cw; s->last_scr_height = height * cheight; -- s->ds->surface->width = width; -- s->ds->surface->height = height; -- dpy_resize(s->ds); ++ qemu_console_resize(s->console, width, height); s->last_width = width; s->last_height = height; s->last_ch = cheight; @@@ -2072,9 -2086,9 +2061,7 @@@ s->last_width = 60; s->last_height = height = 3; dpy_cursor(s->ds, -1, -1); -- s->ds->surface->width = s->last_width; -- s->ds->surface->height = height; -- dpy_resize(s->ds); ++ qemu_console_resize(s->console, s->last_width, height); for (dst = chardata, i = 0; i < s->last_width * height; i ++) console_write_ch(dst ++, ' '); @@@ -2303,207 -2231,36 +2290,207 @@@ static void vga_map(PCIDevice *pci_dev } } -void vga_dirty_log_stop(VGAState *s) +/* 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 */ +} + + +static VGAState *xen_vga_state; + +/* Allocate video memory in the GPFN space */ +void xen_vga_populate_vram(uint64_t vram_addr, uint32_t vga_ram_size) { - if (kvm_enabled() && s->map_addr) - kvm_log_stop(s->map_addr, s->map_end - s->map_addr); + unsigned long nr_pfn; + xen_pfn_t *pfn_list; + int i; + int rc; + + fprintf(logfile, "populating video RAM at %llx\n", + (unsigned long long)vram_addr); + + nr_pfn = vga_ram_size >> TARGET_PAGE_BITS; + + pfn_list = malloc(sizeof(*pfn_list) * nr_pfn); + + for (i = 0; i < nr_pfn; i++) + pfn_list[i] = (vram_addr >> TARGET_PAGE_BITS) + i; - if (kvm_enabled() && s->lfb_vram_mapped) { - kvm_log_stop(isa_mem_base + 0xa0000, 0x8000); - kvm_log_stop(isa_mem_base + 0xa8000, 0x8000); + if (xc_domain_memory_populate_physmap(xc_handle, domid, nr_pfn, 0, 0, pfn_list)) { + fprintf(stderr, "Failed to populate video ram\n"); + exit(1); } + free(pfn_list); + + xen_vga_vram_map(vram_addr, vga_ram_size); + + /* Win2K seems to assume that the pattern buffer is at 0xff + initially ! */ + memset(xen_vga_state->vram_ptr, 0xff, vga_ram_size); } -static void vga_map(PCIDevice *pci_dev, int region_num, - uint32_t addr, uint32_t size, int type) +/* Mapping the video memory from GPFN space */ +void xen_vga_vram_map(uint64_t vram_addr, uint32_t vga_ram_size) { - PCIVGAState *d = (PCIVGAState *)pci_dev; - VGAState *s = &d->vga_state; - if (region_num == PCI_ROM_SLOT) { - cpu_register_physical_memory(addr, s->bios_size, s->bios_offset); - } else { - cpu_register_physical_memory(addr, s->vram_size, s->vram_offset); - } + unsigned long nr_pfn; + xen_pfn_t *pfn_list; + int i; + void *vram; - s->map_addr = addr; - s->map_end = addr + VGA_RAM_SIZE; + fprintf(logfile, "mapping video RAM from %llx\n", + (unsigned long long)vram_addr); - vga_dirty_log_start(s); + nr_pfn = vga_ram_size >> TARGET_PAGE_BITS; + + pfn_list = malloc(sizeof(*pfn_list) * nr_pfn); + + for (i = 0; i < nr_pfn; i++) + pfn_list[i] = (vram_addr >> TARGET_PAGE_BITS) + i; + + vram = xc_map_foreign_pages(xc_handle, domid, + PROT_READ|PROT_WRITE, + pfn_list, nr_pfn); + + if (!vram) { + fprintf(stderr, "Failed to map vram nr_pfn=0x%lx vram_addr=%llx: %s\n", + nr_pfn, (unsigned long long)vram_addr, strerror(errno)); + exit(1); + } + + xen_vga_state->vram_ptr = vram; +#ifdef CONFIG_STUBDOM - xenfb_pv_display_vram(vram); ++ xenfb_pv_display_start(vram); +#endif } -void vga_common_init(VGAState *s, uint8_t *vga_ram_base, - ram_addr_t vga_ram_offset, int vga_ram_size) +/* when used on xen environment, the vga_ram_base is not used */ - void vga_common_init(VGAState *s, uint8_t *vga_ram_base, ++void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size) { int i, j, v, b; @@@ -2530,24 -2287,16 +2517,26 @@@ expand4to8[i] = v; } - s->vram_ptr = vga_ram_base; + vga_reset(s); + + xen_vga_state = s; 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; + - s->ds = graphic_console_init(vga_update_display, vga_invalidate_display, - vga_screen_dump, vga_update_text, s); - + if (!restore) { + xen_vga_populate_vram(VRAM_RESERVED_ADDRESS, s->vram_size); + s->vram_gmfn = VRAM_RESERVED_ADDRESS; + } + ++ graphic_console_init(s->ds, vga_update_display, vga_invalidate_display, ++ vga_screen_dump, vga_update_text, s); ++ + vga_bios_init(s); switch (vga_retrace_method) { case VGA_RETRACE_DUMB: s->retrace = vga_dumb_retrace; @@@ -2612,9 -2360,85 +2601,9 @@@ static void vga_init(VGAState *s vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s); cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, vga_io_memory); - qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000); -} - -/* Memory mapped interface */ -static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr) -{ - VGAState *s = opaque; - - return vga_ioport_read(s, addr >> s->it_shift) & 0xff; -} - -static void vga_mm_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) -{ - VGAState *s = opaque; - - vga_ioport_write(s, addr >> s->it_shift, value & 0xff); -} - -static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr) -{ - VGAState *s = opaque; - - return vga_ioport_read(s, addr >> s->it_shift) & 0xffff; -} - -static void vga_mm_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) -{ - VGAState *s = opaque; - - vga_ioport_write(s, addr >> s->it_shift, value & 0xffff); -} - -static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr) -{ - VGAState *s = opaque; - - return vga_ioport_read(s, addr >> s->it_shift); -} - -static void vga_mm_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) -{ - VGAState *s = opaque; - - vga_ioport_write(s, addr >> s->it_shift, value); -} - -static CPUReadMemoryFunc *vga_mm_read_ctrl[] = { - &vga_mm_readb, - &vga_mm_readw, - &vga_mm_readl, -}; - -static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = { - &vga_mm_writeb, - &vga_mm_writew, - &vga_mm_writel, -}; - -static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base, - target_phys_addr_t ctrl_base, int it_shift) -{ - int s_ioport_ctrl, vga_io_memory; - - s->it_shift = it_shift; - s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s); - vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s); - - register_savevm("vga", 0, 2, vga_save, vga_load, s); - - cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl); - s->bank_offset = 0; - cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory); - qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000); } --int isa_vga_init(uint8_t *vga_ram_base, ++int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size) { VGAState *s; @@@ -2622,15 -2446,38 +2611,15 @@@ s = qemu_mallocz(sizeof(VGAState)); if (!s) return -1; + + if (vga_ram_size > 16*1024*1024) { + fprintf (stderr, "The stdvga/VBE device model has no use for more than 16 Megs of vram. Video ram set to 16M. \n"); + vga_ram_size = 16*1024*1024; + } -- vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size); ++ vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size); vga_init(s); - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); - -#ifdef CONFIG_BOCHS_VBE - /* XXX: use optimized standard vga accesses */ - cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, - vga_ram_size, vga_ram_offset); -#endif - return 0; -} - -int isa_vga_mm_init(uint8_t *vga_ram_base, - unsigned long vga_ram_offset, int vga_ram_size, - target_phys_addr_t vram_base, target_phys_addr_t ctrl_base, - int it_shift) -{ - VGAState *s; - - s = qemu_mallocz(sizeof(VGAState)); - if (!s) - return -1; - - vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size); - vga_mm_init(s, vram_base, ctrl_base, it_shift); - - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); - #ifdef CONFIG_BOCHS_VBE /* XXX: use optimized standard vga accesses */ cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, @@@ -2639,7 -2486,7 +2628,7 @@@ return 0; } --int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base, ++int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size, unsigned long vga_bios_offset, int vga_bios_size) { @@@ -2654,13 -2501,12 +2643,13 @@@ return -1; s = &d->vga_state; - vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size); - vga_init(s); - - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); + if (vga_ram_size > 16*1024*1024) { + fprintf (stderr, "The stdvga/VBE device model has no use for more than 16 Megs of vram. Video ram set to 16M. \n"); + vga_ram_size = 16*1024*1024; + } - vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size); ++ vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size); + vga_init(s); s->pci_dev = &d->dev; pci_conf = d->dev.config; @@@ -2697,86 -2536,131 +2686,79 @@@ /********************************************************/ /* vga screen dump */ ++static int vga_save_w, vga_save_h; ++ static void vga_save_dpy_update(DisplayState *s, int x, int y, int w, int h) { } --static void vga_save_dpy_resize(DisplayState *s) ++static void vga_save_dpy_resize(DisplayState *s, int w, int h) { ++ s->linesize = w * 4; ++ s->data = qemu_mallocz(h * s->linesize); ++ vga_save_w = w; ++ vga_save_h = h; } static void vga_save_dpy_refresh(DisplayState *s) { } --int ppm_save(const char *filename, struct DisplaySurface *ds) ++static int ppm_save(const char *filename, uint8_t *data, ++ int w, int h, int linesize) { FILE *f; uint8_t *d, *d1; -- uint32_t v; ++ unsigned int v; int y, x; -- uint8_t r, g, b; f = fopen(filename, "wb"); if (!f) return -1; fprintf(f, "P6\n%d %d\n%d\n", -- ds->width, ds->height, 255); -- d1 = ds->data; -- for(y = 0; y < ds->height; y++) { ++ w, h, 255); ++ d1 = data; ++ for(y = 0; y < h; y++) { d = d1; -- for(x = 0; x < ds->width; x++) { -- if (ds->pf.bits_per_pixel == 32) -- v = *(uint32_t *)d; -- else -- v = (uint32_t) (*(uint16_t *)d); -- r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 / -- (ds->pf.rmax + 1); -- g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 / -- (ds->pf.gmax + 1); -- b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 / -- (ds->pf.bmax + 1); -- fputc(r, f); -- fputc(g, f); -- fputc(b, f); -- d += ds->pf.bytes_per_pixel; ++ for(x = 0; x < w; x++) { ++ v = *(uint32_t *)d; ++ fputc((v >> 16) & 0xff, f); ++ fputc((v >> 8) & 0xff, f); ++ fputc((v) & 0xff, f); ++ d += 4; } -- d1 += ds->linesize; ++ d1 += linesize; } fclose(f); return 0; } -static void vga_screen_dump_blank(VGAState *s, const char *filename) -{ - FILE *f; - unsigned int y, x, w, h; - - w = s->last_scr_width * sizeof(uint32_t); - h = s->last_scr_height; - - f = fopen(filename, "wb"); - if (!f) - return; - fprintf(f, "P6\n%d %d\n%d\n", w, h, 255); - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - fputc(0, f); - } - } - fclose(f); -} - -static void vga_screen_dump_common(VGAState *s, const char *filename, - int w, int h) +/* save the vga display in a PPM image even if no display is + available */ +static void vga_screen_dump(void *opaque, const char *filename) { + VGAState *s = (VGAState *)opaque; DisplayState *saved_ds, ds1, *ds = &ds1; -- DisplayChangeListener dcl; - int w, h; - - s->get_resolution(s, &w, &h); /* XXX: this is a little hackish */ vga_invalidate_display(s); saved_ds = s->ds; memset(ds, 0, sizeof(DisplayState)); -- memset(&dcl, 0, sizeof(DisplayChangeListener)); -- dcl.dpy_update = vga_save_dpy_update; -- dcl.dpy_resize = vga_save_dpy_resize; -- dcl.dpy_refresh = vga_save_dpy_refresh; -- register_displaychangelistener(ds, &dcl); - ds->surface = qemu_create_displaysurface(ds, w, h, 32, 4 * w); - - ds->surface = qemu_create_displaysurface(w, h, 32, 4 * w); ++ ds->dpy_update = vga_save_dpy_update; ++ ds->dpy_resize = vga_save_dpy_resize; ++ ds->dpy_refresh = vga_save_dpy_refresh; ++ ds->depth = 32; + s->ds = ds; s->graphic_mode = -1; vga_update_display(s); -- ppm_save(filename, ds->surface); -- - qemu_free_displaysurface(ds); - qemu_free_displaysurface(ds->surface); ++ if (ds->data) { ++ ppm_save(filename, ds->data, vga_save_w, vga_save_h, ++ s->ds->linesize); ++ qemu_free(ds->data); ++ } s->ds = saved_ds; } - -static void vga_screen_dump_graphic(VGAState *s, const char *filename) -{ - int w, h; - - s->get_resolution(s, &w, &h); - vga_screen_dump_common(s, filename, w, h); -} - -static void vga_screen_dump_text(VGAState *s, const char *filename) -{ - int w, h, cwidth, cheight; - - vga_get_text_resolution(s, &w, &h, &cwidth, &cheight); - vga_screen_dump_common(s, filename, w * cwidth, h * cheight); -} - -/* save the vga display in a PPM image even if no display is - available */ -static void vga_screen_dump(void *opaque, const char *filename) -{ - VGAState *s = (VGAState *)opaque; - - if (!(s->ar_index & 0x20)) - vga_screen_dump_blank(s, filename); - else if (s->gr[6] & 1) - vga_screen_dump_graphic(s, filename); - else - vga_screen_dump_text(s, filename); -} diff --cc hw/vga_int.h index c9be893d,f97e98fc..d914b62e --- a/hw/vga_int.h +++ b/hw/vga_int.h @@@ -144,6 -145,6 +144,7 @@@ typedef void (* vga_update_retrace_info VGA_STATE_COMMON_BOCHS_VBE \ /* display refresh support */ \ DisplayState *ds; \ ++ QEMUConsole *console; \ uint32_t font_offsets[2]; \ int graphic_mode; \ uint8_t shift_control; \ @@@ -186,12 -191,18 +187,11 @@@ static inline int c6_to_8(int v return (v << 2) | (b << 1) | b; } --void vga_common_init(VGAState *s, uint8_t *vga_ram_base, - ram_addr_t vga_ram_offset, int vga_ram_size); -void vga_init(VGAState *s); -void vga_reset(void *s); - -void vga_dirty_log_start(VGAState *s); -void vga_dirty_log_stop(VGAState *s); - ++void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size); 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, struct DisplaySurface *ds); void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1, int poffset, int w, diff --cc hw/xen_machine_fv.c index 976e7e73,00000000..c63d5d56 mode 100644,000000..100644 --- a/hw/xen_machine_fv.c +++ b/hw/xen_machine_fv.c @@@ -1,302 -1,0 +1,303 @@@ +/* + * QEMU Xen FV Machine + * + * Copyright (c) 2003-2007 Fabrice Bellard + * Copyright (c) 2007 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw.h" +#include "pc.h" +#include "boards.h" +#include "exec-all.h" +#include "qemu-xen.h" + +#include +#include + +#if defined(MAPCACHE) + +#if defined(__i386__) +#define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */ +#define MCACHE_BUCKET_SHIFT 16 +#elif defined(__x86_64__) +#define MAX_MCACHE_SIZE 0x1000000000 /* 64GB max for x86_64 */ +#define MCACHE_BUCKET_SHIFT 20 +#endif + +#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT) + +#define BITS_PER_LONG (sizeof(long)*8) +#define BITS_TO_LONGS(bits) \ + (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) +#define DECLARE_BITMAP(name,bits) \ + unsigned long name[BITS_TO_LONGS(bits)] +#define test_bit(bit,map) \ + (!!((map)[(bit)/BITS_PER_LONG] & (1UL << ((bit)%BITS_PER_LONG)))) + +struct map_cache { + unsigned long paddr_index; + uint8_t *vaddr_base; + DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>XC_PAGE_SHIFT); +}; + +static struct map_cache *mapcache_entry; +static unsigned long nr_buckets; + +/* For most cases (>99.9%), the page address is the same. */ +static unsigned long last_address_index = ~0UL; +static uint8_t *last_address_vaddr; + +static int qemu_map_cache_init(void) +{ + unsigned long size; + + nr_buckets = (((MAX_MCACHE_SIZE >> XC_PAGE_SHIFT) + + (1UL << (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)) - 1) >> + (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)); + + /* + * Use mmap() directly: lets us allocate a big hash table with no up-front + * cost in storage space. The OS will allocate memory only for the buckets + * that we actually use. All others will contain all zeroes. + */ + size = nr_buckets * sizeof(struct map_cache); + size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1); + fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx size %lu\n", nr_buckets, size); + mapcache_entry = mmap(NULL, size, PROT_READ|PROT_WRITE, + MAP_SHARED|MAP_ANON, -1, 0); + if (mapcache_entry == MAP_FAILED) { + errno = ENOMEM; + return -1; + } + + return 0; +} + +static void qemu_remap_bucket(struct map_cache *entry, + unsigned long address_index) +{ + uint8_t *vaddr_base; + unsigned long pfns[MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT]; + unsigned int i, j; + + if (entry->vaddr_base != NULL) { + errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); + if (errno) { + fprintf(logfile, "unmap fails %d\n", errno); + exit(-1); + } + } + + for (i = 0; i < MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT; i++) + pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-XC_PAGE_SHIFT)) + i; + + vaddr_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE, + pfns, MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT); + if (vaddr_base == NULL) { + fprintf(logfile, "xc_map_foreign_batch error %d\n", errno); + exit(-1); + } + + entry->vaddr_base = vaddr_base; + entry->paddr_index = address_index; + + for (i = 0; i < MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT; i += BITS_PER_LONG) { + unsigned long word = 0; + j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT)) ? + (MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG; + while (j > 0) + word = (word << 1) | (((pfns[i + --j] >> 28) & 0xf) != 0xf); + entry->valid_mapping[i / BITS_PER_LONG] = word; + } +} + +uint8_t *qemu_map_cache(target_phys_addr_t phys_addr) +{ + struct map_cache *entry; + unsigned long address_index = phys_addr >> MCACHE_BUCKET_SHIFT; + unsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1); + + if (address_index == last_address_index) + return last_address_vaddr + address_offset; + + entry = &mapcache_entry[address_index % nr_buckets]; + + if (entry->vaddr_base == NULL || entry->paddr_index != address_index || + !test_bit(address_offset>>XC_PAGE_SHIFT, entry->valid_mapping)) + qemu_remap_bucket(entry, address_index); + + if (!test_bit(address_offset>>XC_PAGE_SHIFT, entry->valid_mapping)) { + last_address_index = ~0UL; + return NULL; + } + + last_address_index = address_index; + last_address_vaddr = entry->vaddr_base; + + return last_address_vaddr + address_offset; +} + +void qemu_invalidate_map_cache(void) +{ + unsigned long i; + + mapcache_lock(); + + for (i = 0; i < nr_buckets; i++) { + struct map_cache *entry = &mapcache_entry[i]; + + if (entry->vaddr_base == NULL) + continue; + + errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); + if (errno) { + fprintf(logfile, "unmap fails %d\n", errno); + exit(-1); + } + + entry->paddr_index = 0; + entry->vaddr_base = NULL; + } + + last_address_index = ~0UL; + last_address_vaddr = NULL; + + mapcache_unlock(); +} + +#endif /* defined(MAPCACHE) */ + + +static void xen_init_fv(ram_addr_t ram_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename,const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model, + const char *direct_pci) +{ + unsigned long ioreq_pfn; + extern void *shared_page; + extern void *buffered_io_page; +#ifdef __ia64__ + unsigned long nr_pages; + xen_pfn_t *page_array; + extern void *buffered_pio_page; + int i; +#endif + +#if defined(__i386__) || defined(__x86_64__) + + if (qemu_map_cache_init()) { + fprintf(logfile, "qemu_map_cache_init returned: error %d\n", errno); + exit(-1); + } +#endif + +#ifdef CONFIG_STUBDOM /* the hvmop is not supported on older hypervisors */ + xc_set_hvm_param(xc_handle, domid, HVM_PARAM_DM_DOMAIN, DOMID_SELF); +#endif + xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn); + fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn); + shared_page = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, + PROT_READ|PROT_WRITE, ioreq_pfn); + if (shared_page == NULL) { + fprintf(logfile, "map shared IO page returned error %d\n", errno); + exit(-1); + } + + xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn); + fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn); + buffered_io_page = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, + PROT_READ|PROT_WRITE, ioreq_pfn); + if (buffered_io_page == NULL) { + fprintf(logfile, "map buffered IO page returned error %d\n", errno); + exit(-1); + } + +#if defined(__ia64__) + xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFPIOREQ_PFN, &ioreq_pfn); + fprintf(logfile, "buffered pio page at pfn %lx\n", ioreq_pfn); + buffered_pio_page = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, + PROT_READ|PROT_WRITE, ioreq_pfn); + if (buffered_pio_page == NULL) { + fprintf(logfile, "map buffered PIO page returned error %d\n", errno); + exit(-1); + } + + nr_pages = ram_size / XC_PAGE_SIZE; + + page_array = (xen_pfn_t *)malloc(nr_pages * sizeof(xen_pfn_t)); + if (page_array == NULL) { + fprintf(logfile, "malloc returned error %d\n", errno); + exit(-1); + } + + for (i = 0; i < nr_pages; i++) + page_array[i] = i; + + /* VTI will not use memory between 3G~4G, so we just pass a legal pfn + to make QEMU map continuous virtual memory space */ + if (ram_size > MMIO_START) { + for (i = 0 ; i < (MEM_G >> XC_PAGE_SHIFT); i++) + page_array[(MMIO_START >> XC_PAGE_SHIFT) + i] = + (STORE_PAGE_START >> XC_PAGE_SHIFT); + } + /* skipping VGA hole, same as above */ + if (ram_size > VGA_IO_START) { + for (i = 0 ; i < (VGA_IO_SIZE >> XC_PAGE_SHIFT); i++) + page_array[(VGA_IO_START >> XC_PAGE_SHIFT) + i] = + (STORE_PAGE_START >> XC_PAGE_SHIFT); + } + + phys_ram_base = xc_map_foreign_batch(xc_handle, domid, + PROT_READ|PROT_WRITE, + page_array, nr_pages); + if (phys_ram_base == 0) { + fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno); + exit(-1); + } + free(page_array); +#endif + + timeoffset_get(); + + + pc_machine.init(ram_size, vga_ram_size, boot_device, ds, + kernel_filename, kernel_cmdline, initrd_filename, + cpu_model, direct_pci); +} + +QEMUMachine xenfv_machine = { + "xenfv", + "Xen Fully-virtualized PC", + xen_init_fv, + BIOS_SIZE | RAMSIZE_FIXED, + .max_cpus = 1, ++ .nodisk_ok = 1, +}; + +/* + * Local variables: + * indent-tabs-mode: nil + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff --cc hw/xen_machine_pv.c index 1dcfa31f,00000000..4c334d75 mode 100644,000000..100644 --- a/hw/xen_machine_pv.c +++ b/hw/xen_machine_pv.c @@@ -1,89 -1,0 +1,90 @@@ +/* + * QEMU Xen PV Machine + * + * Copyright (c) 2007 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw.h" +#include "pc.h" +#include "sysemu.h" +#include "boards.h" +#include "xen_backend.h" + +int xen_domid; +enum xen_mode xen_mode = XEN_EMULATE; + +extern void init_blktap(void); + + +/* The Xen PV machine currently provides + * - a virtual framebuffer + * - .... + */ +static void xen_init_pv(ram_addr_t ram_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + const char *cpu_model, + const char *direct_pci) +{ + struct xenfb *xenfb; + extern int domid; + CPUState *env; + +#ifndef CONFIG_STUBDOM + /* Initialize tapdisk client */ + init_blktap(); +#endif + + /* Initialize a dummy CPU */ + env = cpu_init(NULL); + + /* Initialize backend core & drivers */ + if (-1 == xen_be_init()) { + fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__); + exit(1); + } + xen_be_register("console", &xen_console_ops); + xen_be_register("vkbd", &xen_kbdmouse_ops); + xen_be_register("vfb", &xen_framebuffer_ops); + + /* setup framebuffer */ + xen_set_display(xen_domid, ds); +} + +QEMUMachine xenpv_machine = { + "xenpv", + "Xen Para-virtualized PC", + xen_init_pv, + BIOS_SIZE | RAMSIZE_FIXED, + .max_cpus = 1, ++ .nodisk_ok = 1, +}; + +/* + * Local variables: + * indent-tabs-mode: nil + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff --cc qemu-common.h index 8e5d2eb7,8aef5586..ca145365 --- a/qemu-common.h +++ b/qemu-common.h @@@ -6,11 -6,11 +6,12 @@@ #define WIN32_LEAN_AND_MEAN #define WINVER 0x0501 /* needed for ipv6 bits */ #include ++#define NO_UNIX_SOCKETS 1 #endif - #define noreturn __attribute__ ((__noreturn__)) + #define QEMU_NORETURN __attribute__ ((__noreturn__)) - /* Hack around the mess dyngen-exec.h causes: We need noreturn in files that + /* Hack around the mess dyngen-exec.h causes: We need QEMU_NORETURN in files that cannot include the following headers without conflicts. This condition has to be removed once dyngen is gone. */ #ifndef __DYNGEN_EXEC_H__ diff --cc sdl.c index e9256732,cfdf8523..9afd8840 --- a/sdl.c +++ b/sdl.c @@@ -31,13 -31,9 +31,12 @@@ #include #endif -static DisplayChangeListener *dcl; -static SDL_Surface *real_screen; -static SDL_Surface *guest_screen = NULL; +#ifdef CONFIG_OPENGL +#include +#endif + - static DisplayChangeListener *dcl; - static SDL_Surface *real_screen; - static SDL_Surface *guest_screen = NULL; ++static SDL_Surface *screen; ++static SDL_Surface *shared = NULL; static int gui_grab; /* if true, all keyboard/mouse events are grabbed */ static int last_vm_running; static int gui_saved_grab; @@@ -52,180 -48,60 +51,281 @@@ static int width, height static SDL_Cursor *sdl_cursor_normal; static SDL_Cursor *sdl_cursor_hidden; static int absolute_enabled = 0; -static int guest_cursor = 0; -static int guest_x, guest_y; -static SDL_Cursor *guest_sprite = 0; +static int opengl_enabled; + ++static void sdl_colourdepth(DisplayState *ds, int depth); ++ +#ifdef CONFIG_OPENGL +static GLint tex_format; +static GLint tex_type; +static GLuint texture_ref = 0; +static GLint gl_format; - static uint8_t bgr; + - static void opengl_setdata(DisplayState *ds) ++static void opengl_setdata(DisplayState *ds, void *pixels) +{ + glEnable(GL_TEXTURE_RECTANGLE_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glClearColor(0, 0, 0, 0); + glDisable(GL_BLEND); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glDisable(GL_CULL_FACE); - glViewport( 0, 0, real_screen->w, real_screen->h); ++ glViewport( 0, 0, screen->w, screen->h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); - glOrtho(0, real_screen->w, real_screen->h, 0, -1,1); ++ glOrtho(0, screen->w, screen->h, 0, -1,1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glClear(GL_COLOR_BUFFER_BIT); ++ ds->data = pixels; + + if (texture_ref) { + glDeleteTextures(1, &texture_ref); + texture_ref = 0; + } + + glGenTextures(1, &texture_ref); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_ref); + glPixelStorei(GL_UNPACK_LSB_FIRST, 1); - switch (ds_get_bits_per_pixel(ds)) { ++ switch (ds->depth) { ++ case 8: ++ if (ds->palette == NULL) { ++ tex_format = GL_RGB; ++ tex_type = GL_UNSIGNED_BYTE_3_3_2; ++ } else { ++ int i; ++ GLushort paletter[256], paletteg[256], paletteb[256]; ++ for (i = 0; i < 256; i++) { ++ uint8_t rgb = ds->palette[i] >> 16; ++ paletter[i] = ((rgb & 0xe0) >> 5) * 65535 / 7; ++ paletteg[i] = ((rgb & 0x1c) >> 2) * 65535 / 7; ++ paletteb[i] = (rgb & 0x3) * 65535 / 3; ++ } ++ glPixelMapusv(GL_PIXEL_MAP_I_TO_R, 256, paletter); ++ glPixelMapusv(GL_PIXEL_MAP_I_TO_G, 256, paletteg); ++ glPixelMapusv(GL_PIXEL_MAP_I_TO_B, 256, paletteb); ++ ++ tex_format = GL_COLOR_INDEX; ++ tex_type = GL_UNSIGNED_BYTE; ++ } ++ break; + case 16: + tex_format = GL_RGB; + tex_type = GL_UNSIGNED_SHORT_5_6_5; + break; + case 24: + tex_format = GL_BGR; + tex_type = GL_UNSIGNED_BYTE; + break; + case 32: - if (bgr == (ds->surface->pf.rshift < ds->surface->pf.bshift)) { ++ if (!ds->bgr) { + tex_format = GL_BGRA; + tex_type = GL_UNSIGNED_BYTE; + } else { + tex_format = GL_RGBA; + tex_type = GL_UNSIGNED_BYTE; + } + break; + } - glPixelStorei(GL_UNPACK_ROW_LENGTH, (ds_get_linesize(ds) / ds_get_bytes_per_pixel(ds))); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, gl_format, ds_get_width(ds), ds_get_height(ds), 0, tex_format, tex_type, ds_get_data(ds)); ++ glPixelStorei(GL_UNPACK_ROW_LENGTH, (ds->linesize * 8) / ds->depth); ++ glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, gl_format, ds->width, ds->height, 0, tex_format, tex_type, pixels); + glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_PRIORITY, 1.0); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); +} + +static void opengl_update(DisplayState *ds, int x, int y, int w, int h) +{ - int bpp = ds_get_bytes_per_pixel(ds); - GLvoid *pixels = ds_get_data(ds) + y * ds_get_linesize(ds) + x * bpp; ++ int bpp = ds->depth / 8; ++ GLvoid *pixels = ds->data + y * ds->linesize + x * bpp; + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_ref); - glPixelStorei(GL_UNPACK_ROW_LENGTH, ds_get_linesize(ds) / bpp); ++ glPixelStorei(GL_UNPACK_ROW_LENGTH, ds->linesize / bpp); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, w, h, tex_format, tex_type, pixels); + glBegin(GL_QUADS); + glTexCoord2d(0, 0); + glVertex2d(0, 0); - glTexCoord2d(ds_get_width(ds), 0); - glVertex2d(real_screen->w, 0); - glTexCoord2d(ds_get_width(ds), ds_get_height(ds)); - glVertex2d(real_screen->w, real_screen->h); - glTexCoord2d(0, ds_get_height(ds)); - glVertex2d(0, real_screen->h); ++ glTexCoord2d(ds->width, 0); ++ glVertex2d(screen->w, 0); ++ glTexCoord2d(ds->width, ds->height); ++ glVertex2d(screen->w, screen->h); ++ glTexCoord2d(0, ds->height); ++ glVertex2d(0, screen->h); + glEnd(); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + SDL_GL_SwapBuffers(); +} +#endif static void sdl_update(DisplayState *ds, int x, int y, int w, int h) { -- SDL_Rect rec; -- rec.x = x; -- rec.y = y; -- rec.w = w; -- rec.h = h; - // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);i - - SDL_BlitSurface(guest_screen, &rec, real_screen, &rec); - SDL_UpdateRect(real_screen, x, y, w, h); + // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); - - SDL_BlitSurface(guest_screen, &rec, real_screen, &rec); - SDL_UpdateRect(real_screen, x, y, w, h); ++ if (shared) { ++ SDL_Rect rec; ++ rec.x = x; ++ rec.y = y; ++ rec.w = w; ++ rec.h = h; ++ SDL_BlitSurface(shared, &rec, screen, &rec); ++ } ++ SDL_Flip(screen); } --static void sdl_setdata(DisplayState *ds) ++static void sdl_setdata(DisplayState *ds, void *pixels) { -- SDL_Rect rec; -- rec.x = 0; -- rec.y = 0; -- rec.w = real_screen->w; -- rec.h = real_screen->h; -- -- if (guest_screen != NULL) SDL_FreeSurface(guest_screen); -- -- guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds), -- ds_get_bits_per_pixel(ds), ds_get_linesize(ds), -- ds->surface->pf.rmask, ds->surface->pf.gmask, -- ds->surface->pf.bmask, ds->surface->pf.amask); ++ uint32_t rmask, gmask, bmask, amask = 0; ++ switch (ds->depth) { ++ case 8: ++ rmask = 0x000000E0; ++ gmask = 0x0000001C; ++ bmask = 0x00000003; ++ break; ++ case 16: ++ rmask = 0x0000F800; ++ gmask = 0x000007E0; ++ bmask = 0x0000001F; ++ break; ++ case 24: ++ rmask = 0x00FF0000; ++ gmask = 0x0000FF00; ++ bmask = 0x000000FF; ++ break; ++ case 32: ++ rmask = 0x00FF0000; ++ gmask = 0x0000FF00; ++ bmask = 0x000000FF; ++ break; ++ default: ++ return; ++ } ++ shared = SDL_CreateRGBSurfaceFrom(pixels, width, height, ds->depth, ds->linesize, rmask , gmask, bmask, amask); ++ if (ds->depth == 8 && ds->palette != NULL) { ++ SDL_Color palette[256]; ++ int i; ++ for (i = 0; i < 256; i++) { ++ uint8_t rgb = ds->palette[i] >> 16; ++ palette[i].r = ((rgb & 0xe0) >> 5) * 255 / 7; ++ palette[i].g = ((rgb & 0x1c) >> 2) * 255 / 7; ++ palette[i].b = (rgb & 0x3) * 255 / 3; ++ } ++ SDL_SetColors(shared, palette, 0, 256); ++ } ++ ds->data = pixels; } --static void sdl_resize(DisplayState *ds) ++static void sdl_resize_shared(DisplayState *ds, int w, int h, int depth, int linesize, void *pixels) { int flags; // printf("resizing to %d %d\n", w, h); + - flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL; - if (gui_fullscreen) ++ sdl_colourdepth(ds, depth); ++ +#ifdef CONFIG_OPENGL - if (opengl_enabled) ++ if (ds->shared_buf && opengl_enabled) + flags = SDL_OPENGL|SDL_RESIZABLE; + else +#endif - flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL; ++ flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_DOUBLEBUF|SDL_HWPALETTE; + - if (gui_fullscreen) ++ if (gui_fullscreen) { flags |= SDL_FULLSCREEN; ++ flags &= ~SDL_RESIZABLE; ++ } if (gui_noframe) flags |= SDL_NOFRAME; -- width = ds_get_width(ds); -- height = ds_get_height(ds); -- real_screen = SDL_SetVideoMode(width, height, 0, flags); -- if (!real_screen) { - fprintf(stderr, "Could not open SDL display\n"); ++ width = w; ++ height = h; ++ ++ again: ++ screen = SDL_SetVideoMode(w, h, 0, flags); ++ ++ if (!screen) { ++ fprintf(stderr, "Could not open SDL display: %s\n", SDL_GetError()); + if (opengl_enabled) { + /* Fallback to SDL */ + opengl_enabled = 0; - dcl->dpy_update = sdl_update; - dcl->dpy_setdata = sdl_setdata; - sdl_resize(ds); ++ ds->dpy_update = sdl_update; ++ ds->dpy_setdata = sdl_setdata; ++ ds->dpy_resize_shared = sdl_resize_shared; ++ sdl_resize_shared(ds, w, h, depth, linesize, pixels); + return; + } - fprintf(stderr, "Could not open SDL display\n"); exit(1); } - #ifdef CONFIG_OPENGL - if (real_screen->format->Bshift > real_screen->format->Rshift) { - bgr = 1; - } else { - bgr = 0; - sdl_setdata(ds); ++ if (!opengl_enabled) { ++ if (!screen->pixels && (flags & SDL_HWSURFACE) && (flags & SDL_FULLSCREEN)) { ++ flags &= ~SDL_HWSURFACE; ++ goto again; ++ } ++ ++ if (!screen->pixels) { ++ fprintf(stderr, "Could not open SDL display: %s\n", SDL_GetError()); ++ exit(1); ++ } + } - switch(real_screen->format->BitsPerPixel) { ++ ++ ds->width = w; ++ ds->height = h; ++ if (!ds->shared_buf) { ++ ds->depth = screen->format->BitsPerPixel; ++ if (screen->format->Bshift > screen->format->Rshift) { ++ ds->bgr = 1; ++ } else { ++ ds->bgr = 0; ++ } ++ shared = NULL; ++ ds->data = screen->pixels; ++ ds->linesize = screen->pitch; ++ } else { ++ ds->linesize = linesize; ++#ifdef CONFIG_OPENGL ++ switch(screen->format->BitsPerPixel) { + case 8: + gl_format = GL_RGB; + break; + case 16: + gl_format = GL_RGB; + break; + case 24: + gl_format = GL_RGB; + break; + case 32: - if (!real_screen->format->Rshift) ++ if (!screen->format->Rshift) + gl_format = GL_BGRA; + else + gl_format = GL_RGBA; + break; - }; ++ }; +#endif ++ } ++ if (ds->shared_buf) ds->dpy_setdata(ds, pixels); ++} + - dcl->dpy_setdata(ds); ++static void sdl_resize(DisplayState *ds, int w, int h) ++{ ++ sdl_resize_shared(ds, w, h, 0, w * (ds->depth / 8), NULL); ++} ++ ++static void sdl_colourdepth(DisplayState *ds, int depth) ++{ ++ if (!depth || !ds->depth) { ++ ds->shared_buf = 0; ++ ds->dpy_update = sdl_update; ++ return; ++ } ++ ds->shared_buf = 1; ++ ds->depth = depth; ++#ifdef CONFIG_OPENGL ++ if (opengl_enabled) { ++ ds->dpy_update = opengl_update; ++ } ++#endif } /* generic keyboard conversion */ @@@ -423,9 -318,8 +523,9 @@@ static void sdl_send_mouse_event(int dx absolute_enabled = 1; } - dx = x * 0x7FFF / (width - 1); - dy = y * 0x7FFF / (height - 1); + SDL_GetMouseState(&dx, &dy); - dx = dx * 0x7FFF / (real_screen->w - 1); - dy = dy * 0x7FFF / (real_screen->h - 1); ++ dx = dx * 0x7FFF / (screen->w - 1); ++ dy = dy * 0x7FFF / (screen->h - 1); } else if (absolute_enabled) { sdl_show_cursor(); absolute_enabled = 0; @@@ -437,7 -338,7 +537,7 @@@ static void toggle_full_screen(DisplayState *ds) { gui_fullscreen = !gui_fullscreen; -- sdl_resize(ds); ++ sdl_resize_shared(ds, ds->width, ds->height, ds->depth, ds->linesize, ds->data); if (gui_fullscreen) { gui_saved_grab = gui_grab; sdl_grab_start(); @@@ -465,7 -367,7 +565,7 @@@ static void sdl_refresh(DisplayState *d while (SDL_PollEvent(ev)) { switch (ev->type) { case SDL_VIDEOEXPOSE: - dcl->dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); - sdl_update(ds, 0, 0, real_screen->w, real_screen->h); ++ ds->dpy_update(ds, 0, 0, ds->width, ds->height); break; case SDL_KEYDOWN: case SDL_KEYUP: @@@ -622,30 -519,18 +722,30 @@@ !ev->active.gain && !gui_fullscreen_initial_grab) { sdl_grab_end(); } - if (ev->active.state & SDL_APPACTIVE) { - if (ev->active.gain) { - /* Back to default interval */ - dcl->gui_timer_interval = 0; - dcl->idle = 0; - } else { - /* Sleeping interval */ - dcl->gui_timer_interval = 500; - dcl->idle = 1; - } + if (ev->active.state & SDL_APPACTIVE) { + if (ev->active.gain) { + /* Back to default interval */ - dcl->gui_timer_interval = 0; - dcl->idle = 0; ++ ds->gui_timer_interval = 0; ++ ds->idle = 0; + } else { + /* Sleeping interval */ - dcl->gui_timer_interval = 500; - dcl->idle = 1; ++ ds->gui_timer_interval = 500; ++ ds->idle = 1; + } + } + break; +#ifdef CONFIG_OPENGL + case SDL_VIDEORESIZE: + { - if (opengl_enabled) { ++ if (ds->shared_buf && opengl_enabled) { + SDL_ResizeEvent *rev = &ev->resize; - real_screen = SDL_SetVideoMode(rev->w, rev->h, 0, SDL_OPENGL|SDL_RESIZABLE); - opengl_setdata(ds); - opengl_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); ++ screen = SDL_SetVideoMode(rev->w, rev->h, 0, SDL_OPENGL|SDL_RESIZABLE); ++ opengl_setdata(ds, ds->data); ++ opengl_update(ds, 0, 0, ds->width, ds->height); } break; + } +#endif default: break; } @@@ -685,27 -636,19 +785,23 @@@ void sdl_display_init(DisplayState *ds fprintf(stderr, "Could not initialize SDL - exiting\n"); exit(1); } +#ifndef _WIN32 + /* NOTE: we still want Ctrl-C to work, so we undo the SDL redirections */ + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); +#endif -- dcl = qemu_mallocz(sizeof(DisplayChangeListener)); -- if (!dcl) -- exit(1); -- dcl->dpy_update = sdl_update; -- dcl->dpy_resize = sdl_resize; -- dcl->dpy_refresh = sdl_refresh; -- dcl->dpy_setdata = sdl_setdata; - dcl->dpy_fill = sdl_fill; - ds->mouse_set = sdl_mouse_warp; - ds->cursor_define = sdl_mouse_define; - register_displaychangelistener(ds, dcl); ++ ds->dpy_update = sdl_update; ++ ds->dpy_resize = sdl_resize; ++ ds->dpy_resize_shared = sdl_resize_shared; ++ ds->dpy_refresh = sdl_refresh; ++ ds->dpy_setdata = sdl_setdata; +#ifdef CONFIG_OPENGL - if (opengl_enabled) { - dcl->dpy_update = opengl_update; - dcl->dpy_setdata = opengl_setdata; - } ++ if (opengl_enabled) ++ ds->dpy_setdata = opengl_setdata; +#endif - register_displaychangelistener(ds, dcl); ++ sdl_resize(ds, 640, 400); sdl_update_caption(); SDL_EnableKeyRepeat(250, 50); gui_grab = 0; diff --cc vl.c index 7be1ade8,36765378..fceec987 --- a/vl.c +++ b/vl.c @@@ -46,8 -43,7 +43,11 @@@ #include "kvm.h" #include "balloon.h" - #include ++#include "hw/pci.h" ++#include "hw/xen.h" +#include ++ + #include #include #include #include @@@ -3867,14 -3849,10 +3878,16 @@@ static int main_loop(void return ret; } +#else /* CONFIG_DM */ +void main_loop_prepare(void) { + cur_cpu = first_cpu; +} +#endif /* !CONFIG_DM */ + static void help(int exitcode) { + /* Please keep in synch with QEMU_OPTION_ enums, qemu_options[] + and qemu-doc.texi */ printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n" "usage: %s [options] [disk_image]\n" "\n" @@@ -3924,16 -3887,27 +3922,30 @@@ " use -soundhw ? to get the list of supported cards\n" " use -soundhw all to enable all of them\n" #endif + "-usb enable the USB driver (will be the default soon)\n" + "-usbdevice name add the host or guest USB device 'name'\n" + "-name string set the name of the guest\n" + "-uuid %%08x-%%04x-%%04x-%%04x-%%012x\n" + " specify machine UUID\n" + "\n" + "Display options:\n" + "-nographic disable graphical output and redirect serial I/Os to console\n" + #ifdef CONFIG_CURSES + "-curses use a curses/ncurses interface instead of SDL\n" + #endif + #ifdef CONFIG_SDL + "-no-frame open SDL window without a frame and window decorations\n" + "-alt-grab use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt)\n" + "-no-quit disable SDL window close capability\n" + "-sdl enable SDL\n" ++#ifdef CONFIG_OPENGL ++ "-disable-opengl disable OpenGL rendering, using SDL" ++#endif + #endif + "-portrait rotate graphical output 90 deg left (only PXA LCD)\n" "-vga [std|cirrus|vmware|none]\n" " select video card type\n" - "-localtime set the real time clock to local time [default=utc]\n" "-full-screen start in full screen\n" - #ifdef TARGET_I386 - "-win2k-hack use it when installing Windows 2000 to avoid a disk full bug\n" - "-rtc-td-hack use it to fix time drift in Windows ACPI HAL\n" - #endif - "-usb enable the USB driver (will be the default soon)\n" - "-usbdevice name add the host or guest USB device 'name'\n" #if defined(TARGET_PPC) || defined(TARGET_SPARC) "-g WxH[xDEPTH] Set the initial graphical resolution and depth\n" #endif @@@ -4042,10 -4014,23 +4053,30 @@@ #endif "-clock force the use of the given methods for timer alarm.\n" " To see what timers are available use -clock ?\n" + "-localtime set the real time clock to local time [default=utc]\n" "-startdate select initial date of the clock\n" "-icount [N|auto]\n" - " Enable virtual instruction counter with 2^N clock ticks per instruction\n" + " enable virtual instruction counter with 2^N clock ticks per instruction\n" + "-echr chr set terminal escape character instead of ctrl-a\n" + "-virtioconsole c\n" + " set virtio console\n" + "-show-cursor show cursor\n" + #if defined(TARGET_ARM) || defined(TARGET_M68K) + "-semihosting semihosting mode\n" + #endif + #if defined(TARGET_ARM) + "-old-param old param mode\n" + #endif + "-tb-size n set TB size\n" + "-incoming p prepare for incoming migration, listen on port p\n" "\n" ++ "Options specific to the Xen version:\n" ++ "-videoram set amount of memory available to virtual video adapter\n" ++ "-direct-pci s specify pci passthrough, with configuration string s\n" ++ "-pciemulation name:vendorid:deviceid:command:status:revision:classcode:headertype:subvendorid:subsystemid:interruputline:interruputpin\n" ++ "-vncunused bind the VNC server to an unused port\n" ++ "-std-vga alias for -vga std\n" ++ "\n" "During emulation, the following keys are useful:\n" "ctrl-alt-f toggle full screen\n" "ctrl-alt-n switch to virtual console 'n'\n" @@@ -4106,6 -4114,11 +4160,19 @@@ enum QEMU_OPTION_append, QEMU_OPTION_initrd, ++ /* Xen tree: */ ++ QEMU_OPTION_disable_opengl, ++ QEMU_OPTION_direct_pci, ++ QEMU_OPTION_pci_emulation, ++ QEMU_OPTION_vncunused, ++ QEMU_OPTION_videoram, ++ QEMU_OPTION_std_vga, ++ + /* Debug/Expert options: */ + QEMU_OPTION_serial, + QEMU_OPTION_parallel, + QEMU_OPTION_monitor, + QEMU_OPTION_pidfile, QEMU_OPTION_S, QEMU_OPTION_s, QEMU_OPTION_p, @@@ -4239,66 -4252,24 +4306,44 @@@ static const QEMUOption qemu_options[] #ifdef CONFIG_KVM { "enable-kvm", 0, QEMU_OPTION_enable_kvm }, #endif - #if defined(TARGET_PPC) || defined(TARGET_SPARC) - { "g", 1, QEMU_OPTION_g }, + { "no-reboot", 0, QEMU_OPTION_no_reboot }, + { "no-shutdown", 0, QEMU_OPTION_no_shutdown }, + { "loadvm", HAS_ARG, QEMU_OPTION_loadvm }, + { "daemonize", 0, QEMU_OPTION_daemonize }, + { "option-rom", HAS_ARG, QEMU_OPTION_option_rom }, + #if defined(TARGET_SPARC) || defined(TARGET_PPC) + { "prom-env", HAS_ARG, QEMU_OPTION_prom_env }, #endif + { "clock", HAS_ARG, QEMU_OPTION_clock }, { "localtime", 0, QEMU_OPTION_localtime }, - { "std-vga", 0, QEMU_OPTION_std_vga }, - { "videoram", HAS_ARG, QEMU_OPTION_videoram }, - { "vga", HAS_ARG, QEMU_OPTION_vga }, + { "startdate", HAS_ARG, QEMU_OPTION_startdate }, + { "icount", HAS_ARG, QEMU_OPTION_icount }, { "echr", HAS_ARG, QEMU_OPTION_echr }, - { "monitor", HAS_ARG, QEMU_OPTION_monitor }, - { "domain-name", 1, QEMU_OPTION_domainname }, - { "serial", HAS_ARG, QEMU_OPTION_serial }, { "virtioconsole", HAS_ARG, QEMU_OPTION_virtiocon }, - { "parallel", HAS_ARG, QEMU_OPTION_parallel }, - { "loadvm", HAS_ARG, QEMU_OPTION_loadvm }, - { "full-screen", 0, QEMU_OPTION_full_screen }, - #ifdef CONFIG_SDL - { "no-frame", 0, QEMU_OPTION_no_frame }, - { "alt-grab", 0, QEMU_OPTION_alt_grab }, - { "no-quit", 0, QEMU_OPTION_no_quit }, + { "show-cursor", 0, QEMU_OPTION_show_cursor }, + #if defined(TARGET_ARM) || defined(TARGET_M68K) + { "semihosting", 0, QEMU_OPTION_semihosting }, #endif ++ ++ /* Xen tree options: */ ++ { "std-vga", 0, QEMU_OPTION_std_vga }, ++ { "videoram", HAS_ARG, QEMU_OPTION_videoram }, ++ { "d", HAS_ARG, QEMU_OPTION_domid }, /* deprecated; for xend compatibility */ ++ { "domid", HAS_ARG, QEMU_OPTION_domid }, ++ { "domain-name", 1, QEMU_OPTION_domainname }, +#ifdef CONFIG_OPENGL + { "disable-opengl", 0, QEMU_OPTION_disable_opengl }, +#endif - { "vcpus", 1, QEMU_OPTION_vcpus }, + { "acpi", 0, QEMU_OPTION_acpi }, /* deprecated, for xend compatibility */ + { "direct_pci", HAS_ARG, QEMU_OPTION_direct_pci }, + { "pciemulation", HAS_ARG, QEMU_OPTION_pci_emulation }, - { "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, - { "win2k-hack", 0, QEMU_OPTION_win2k_hack }, - { "rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack }, - { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice }, - { "smp", HAS_ARG, QEMU_OPTION_smp }, - { "vnc", HAS_ARG, QEMU_OPTION_vnc }, + { "vncunused", 0, QEMU_OPTION_vncunused }, - #ifdef CONFIG_CURSES - { "curses", 0, QEMU_OPTION_curses }, - #endif - { "uuid", HAS_ARG, QEMU_OPTION_uuid }, +#ifdef CONFIG_XEN + { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, + { "xen-create", 0, QEMU_OPTION_xen_create }, + { "xen-attach", 0, QEMU_OPTION_xen_attach }, +#endif + - /* temporary options */ - { "usb", 0, QEMU_OPTION_usb }, - { "no-acpi", 0, QEMU_OPTION_no_acpi }, - { "no-hpet", 0, QEMU_OPTION_no_hpet }, - { "no-reboot", 0, QEMU_OPTION_no_reboot }, - { "no-shutdown", 0, QEMU_OPTION_no_shutdown }, - { "show-cursor", 0, QEMU_OPTION_show_cursor }, - { "daemonize", 0, QEMU_OPTION_daemonize }, - { "option-rom", HAS_ARG, QEMU_OPTION_option_rom }, - #if defined(TARGET_ARM) || defined(TARGET_M68K) - { "semihosting", 0, QEMU_OPTION_semihosting }, - #endif - { "name", HAS_ARG, QEMU_OPTION_name }, - #if defined(TARGET_SPARC) || defined(TARGET_PPC) - { "prom-env", HAS_ARG, QEMU_OPTION_prom_env }, - #endif #if defined(TARGET_ARM) { "old-param", 0, QEMU_OPTION_old_param }, #endif @@@ -4624,35 -4586,7 +4660,34 @@@ int main(int argc, char **argv, char ** int autostart; const char *incoming = NULL; + qemu_cache_utils_init(envp); + logfile = stderr; /* initial value */ + +#if !defined(__sun__) && !defined(CONFIG_STUBDOM) + /* Maximise rlimits. Needed where default constraints are tight (*BSD). */ + if (getrlimit(RLIMIT_STACK, &rl) != 0) { + perror("getrlimit(RLIMIT_STACK)"); + exit(1); + } + rl.rlim_cur = rl.rlim_max; + if (setrlimit(RLIMIT_STACK, &rl) != 0) + perror("setrlimit(RLIMIT_STACK)"); + if (getrlimit(RLIMIT_DATA, &rl) != 0) { + perror("getrlimit(RLIMIT_DATA)"); + exit(1); + } + rl.rlim_cur = rl.rlim_max; + if (setrlimit(RLIMIT_DATA, &rl) != 0) + perror("setrlimit(RLIMIT_DATA)"); + rl.rlim_cur = RLIM_INFINITY; + rl.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_RSS, &rl) != 0) + perror("setrlimit(RLIMIT_RSS)"); + rl.rlim_cur = RLIM_INFINITY; + rl.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0) + perror("setrlimit(RLIMIT_MEMLOCK)"); - #endif - - qemu_cache_utils_init(envp); ++#endif LIST_INIT (&vm_change_state_head); #ifndef _WIN32 @@@ -5151,7 -5057,6 +5157,7 @@@ break; case QEMU_OPTION_loadvm: loadvm = optarg; - restore = 1; ++ restore = 1; break; case QEMU_OPTION_full_screen: full_screen = 1; @@@ -5166,20 -5071,10 +5172,65 @@@ case QEMU_OPTION_no_quit: no_quit = 1; break; + case QEMU_OPTION_sdl: + sdl = 1; + break; #endif ++ ++ case QEMU_OPTION_pci_emulation: ++ if (nb_pci_emulation >= MAX_PCI_EMULATION) { ++ fprintf(stderr, "Too many PCI emulations\n"); ++ exit(1); ++ } ++ pstrcpy(pci_emulation_config_text[nb_pci_emulation], ++ sizeof(pci_emulation_config_text[0]), ++ optarg); ++ nb_pci_emulation++; ++ break; ++ case QEMU_OPTION_domid: /* depricated, use -xen-* instead */ ++ xen_domid = domid = atoi(optarg); ++ xen_mode = XEN_ATTACH; ++ fprintf(logfile, "domid: %d\n", domid); ++ break; ++ case QEMU_OPTION_videoram: ++ { ++ char *ptr; ++ vga_ram_size = strtol(optarg,&ptr,10); ++ vga_ram_size *= 1024 * 1024; ++ } ++ break; ++ case QEMU_OPTION_std_vga: ++ cirrus_vga_enabled = 0; ++ vmsvga_enabled = 0; ++ break; + case QEMU_OPTION_disable_opengl: + opengl_enabled = 0; + break; + case QEMU_OPTION_direct_pci: - direct_pci = optarg; ++ direct_pci = optarg; + break; + case QEMU_OPTION_vcpus: + vcpus = atoi(optarg); + fprintf(logfile, "qemu: the number of cpus is %d\n", vcpus); + break; + case QEMU_OPTION_acpi: + acpi_enabled = 1; + break; ++ case QEMU_OPTION_vncunused: ++ vncunused = 1; ++ break; ++#ifdef CONFIG_XEN ++ case QEMU_OPTION_xen_domid: ++ xen_domid = domid = atoi(optarg); ++ break; ++ case QEMU_OPTION_xen_create: ++ xen_mode = XEN_CREATE; ++ break; ++ case QEMU_OPTION_xen_attach: ++ xen_mode = XEN_ATTACH; ++ break; ++#endif ++ case QEMU_OPTION_pidfile: pid_file = optarg; break; @@@ -5268,11 -5160,8 +5316,11 @@@ case QEMU_OPTION_semihosting: semihosting_enabled = 1; break; + case QEMU_OPTION_domainname: /* depricated, use -name instead */ case QEMU_OPTION_name: - qemu_name = optarg; + snprintf(domain_name, sizeof(domain_name), + "Xen-%s", optarg); + qemu_name = optarg; break; #if defined(TARGET_SPARC) || defined(TARGET_PPC) case QEMU_OPTION_prom_env: @@@ -5531,16 -5406,8 +5565,15 @@@ exit(1); } } - #endif +#if defined (__ia64__) + if (ram_size > VGA_IO_START) + ram_size += VGA_IO_SIZE; /* skip VGA I/O hole */ + if (ram_size > MMIO_START) + ram_size += 1 * MEM_G; /* skip 3G-4G MMIO, LEGACY_IO_SPACE etc. */ +#endif + /* init the bluetooth world */ for (i = 0; i < nb_bt_opts; i++) if (bt_parse(bt_opts[i])) @@@ -5627,48 -5469,9 +5660,11 @@@ register_savevm("timer", 0, 2, timer_save, timer_load, NULL); register_savevm_live("ram", 0, 3, ram_save_live, NULL, ram_load, NULL); - /* terminal init */ - memset(&display_state, 0, sizeof(display_state)); - #ifdef CONFIG_STUBDOM - if (xenfb_pv_display_init(ds) == 0) { - } else - #endif - if (nographic) { - if (curses) { - fprintf(stderr, "fatal: -nographic can't be used with -curses\n"); - exit(1); - } - /* nearly nothing to do */ - dumb_display_init(ds); - } else if (vnc_display != NULL || vncunused != 0) { - int vnc_display_port; - char password[20]; - vnc_display_init(ds); - xenstore_read_vncpasswd(domid, password, sizeof(password)); - vnc_display_password(ds, password); - vnc_display_port = vnc_display_open(ds, vnc_display, vncunused); - if (vnc_display_port < 0) - exit(1); - xenstore_write_vncport(vnc_display_port); - } else - #if defined(CONFIG_CURSES) - if (curses) { - curses_display_init(ds, full_screen); - } else - #endif - { - #if defined(CONFIG_SDL) - sdl_display_init(ds, full_screen, no_frame, opengl_enabled); - #elif defined(CONFIG_COCOA) - cocoa_display_init(ds, full_screen); - #else - dumb_display_init(ds); - #endif - } - #ifndef _WIN32 ++#ifndef CONFIG_DM /* must be after terminal init, SDL library changes signal handlers */ termsig_setup(); ++#endif #endif /* Maintain compatibility with multiple stdio monitors */ @@@ -5751,21 -5549,8 +5742,9 @@@ } } - machine->init(ram_size, vga_ram_size, boot_devices, ds, + machine->init(ram_size, vga_ram_size, boot_devices, - kernel_filename, kernel_cmdline, initrd_filename, cpu_model); + kernel_filename, kernel_cmdline, initrd_filename, cpu_model, + direct_pci); /* Set KVM's vcpu state to qemu's initial CPUState. */ if (kvm_enabled()) { @@@ -5788,9 -5573,87 +5767,107 @@@ } } - if (display_state.dpy_refresh) { - display_state.gui_timer = qemu_new_timer(rt_clock, gui_update, &display_state); - qemu_mod_timer(display_state.gui_timer, qemu_get_clock(rt_clock)); + if (!display_state) + dumb_display_init(); + /* just use the first displaystate for the moment */ + ds = display_state; + /* terminal init */ +++#ifdef CONFIG_STUBDOM +++ if (xenfb_pv_display_init(ds) == 0) { +++ } else +++#endif + if (nographic) { + if (curses) { + fprintf(stderr, "fatal: -nographic can't be used with -curses\n"); + exit(1); + } + } else { + #if defined(CONFIG_CURSES) + if (curses) { + /* At the moment curses cannot be used with other displays */ + curses_display_init(ds, full_screen); + } else + #endif + { - if (vnc_display != NULL) { - vnc_display_init(ds); - if (vnc_display_open(ds, vnc_display) < 0) ++ if (vnc_display != NULL || vncunused != 0) { ++ int vnc_display_port; ++ char password[20]; ++ vnc_display_init(ds, vncunused); ++ xenstore_read_vncpasswd(domid, password, sizeof(password)); ++ vnc_display_password(ds, password); ++ vnc_display_port = vnc_display_open(ds, vnc_display, vncunused); ++ if (vnc_display_port < 0) + exit(1); ++ xenstore_write_vncport(vnc_display_port); + } + #if defined(CONFIG_SDL) + if (sdl || !vnc_display) - sdl_display_init(ds, full_screen, no_frame); ++ sdl_display_init(ds, full_screen, no_frame, opengl_enabled); + #elif defined(CONFIG_COCOA) + if (sdl || !vnc_display) + cocoa_display_init(ds, full_screen); + #endif + } + } + dpy_resize(ds); + + dcl = ds->listeners; + while (dcl != NULL) { + if (dcl->dpy_refresh != NULL) { + ds->gui_timer = qemu_new_timer(rt_clock, gui_update, ds); + qemu_mod_timer(ds->gui_timer, qemu_get_clock(rt_clock)); + } + dcl = dcl->next; + } + + if (nographic || (vnc_display && !sdl)) { + nographic_timer = qemu_new_timer(rt_clock, nographic_update, NULL); + qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock)); + } + + text_consoles_set_display(display_state); + + if (monitor_device && monitor_hd) + monitor_init(monitor_hd, !nographic); + + for(i = 0; i < MAX_SERIAL_PORTS; i++) { + const char *devname = serial_devices[i]; + if (devname && strcmp(devname, "none")) { + char label[32]; + snprintf(label, sizeof(label), "serial%d", i); + if (strstart(devname, "vc", 0)) + qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i); + } + } + + for(i = 0; i < MAX_PARALLEL_PORTS; i++) { + const char *devname = parallel_devices[i]; + if (devname && strcmp(devname, "none")) { + char label[32]; + snprintf(label, sizeof(label), "parallel%d", i); + if (strstart(devname, "vc", 0)) + qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i); + } + } + ++ for (i = 0; i < nb_pci_emulation; i++) { ++ if(pci_emulation_add(pci_emulation_config_text[i]) < 0) { ++ fprintf(stderr, "Warning: could not add PCI device %s\n", ++ pci_emulation_config_text[i]); ++ } ++ } ++ ++ if (strlen(direct_pci_str) > 0) ++ direct_pci = direct_pci_str; ++ + for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { + const char *devname = virtio_consoles[i]; + if (virtcon_hds[i] && devname) { + char label[32]; + snprintf(label, sizeof(label), "virtcon%d", i); + if (strstart(devname, "vc", 0)) + qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i); + } } #ifdef CONFIG_GDBSTUB diff --cc vnc.c index 52e46274,0c4d96e2..02d3b1d1 --- a/vnc.c +++ b/vnc.c @@@ -74,12 -58,12 +74,6 @@@ static void vnc_debug_gnutls_log(int le #define VNC_DEBUG(fmt, ...) do { } while (0) #endif --#define count_bits(c, v) { \ -- for (c = 0; v; v >>= 1) \ -- { \ -- c += v & 1; \ -- } \ --} typedef struct Buffer { @@@ -168,19 -96,10 +162,22 @@@ struct VncStat int lsock; int csock; DisplayState *ds; - int need_update; - uint32_t dirty_row[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS]; - char *old_data; - uint32_t features; ++ int width; ++ int height; + uint64_t *dirty_row; /* screen regions which are possibly dirty */ + int dirty_pixel_shift; + uint64_t *update_row; /* outstanding updates */ + int has_update; /* there's outstanding updates in the + * visible area */ + + int update_requested; /* the client requested an update */ + + uint8_t *old_data; ++ int depth; /* internal VNC frame buffer byte per pixel */ + int has_resize; + int has_hextile; + int has_pointer_type_change; + int has_WMVi; int absolute; int last_x; int last_y; @@@ -217,7 -136,10 +214,10 @@@ /* current output mode information */ VncWritePixels *write_pixels; VncSendHextileTile *send_hextile_tile; -- DisplaySurface clientds, serverds; - - CaptureVoiceOut *audio_cap; - struct audsettings as; ++ int pix_bpp, pix_big_endian; ++ int red_shift, red_max, red_shift1, red_max1; ++ int green_shift, green_max, green_shift1, green_max1; ++ int blue_shift, blue_max, blue_shift1, blue_max1; VncReadEvent *read_handler; size_t read_handler_expect; @@@ -232,13 -148,11 +232,12 @@@ }; static VncState *vnc_state; /* needed for info vnc */ --static DisplayChangeListener *dcl; + +#define DIRTY_PIXEL_BITS 64 +#define X2DP_DOWN(vs, x) ((x) >> (vs)->dirty_pixel_shift) +#define X2DP_UP(vs, x) \ + (((x) + (1ULL << (vs)->dirty_pixel_shift) - 1) >> (vs)->dirty_pixel_shift) +#define DP2X(vs, x) ((x) << (vs)->dirty_pixel_shift) void do_info_vnc(void) { @@@ -269,18 -187,11 +268,18 @@@ static void vnc_write_s32(VncState *vs static void vnc_write_u16(VncState *vs, uint16_t value); static void vnc_write_u8(VncState *vs, uint8_t value); static void vnc_flush(VncState *vs); +static void _vnc_update_client(void *opaque); static void vnc_update_client(void *opaque); static void vnc_client_read(void *opaque); - -static void vnc_colordepth(DisplayState *ds); - +static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h); +static void pixel_format_message (VncState *vs); +static void enqueue_framebuffer_update(VncState *vs, int x, int y, int w, int h, int32_t encoding); +static void dequeue_framebuffer_update(VncState *vs); +static int is_empty_queue(VncState *vs); +static void free_queue(VncState *vs); - static void vnc_colordepth(DisplayState *ds); ++static void vnc_colourdepth(DisplayState *ds, int depth); + +#if 0 static inline void vnc_set_bit(uint32_t *d, int k) { d[k >> 5] |= 1 << (k & 0x1f); @@@ -321,42 -232,29 +320,42 @@@ static inline int vnc_and_bits(const ui } return 0; } +#endif -static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) +static void set_bits_in_row(VncState *vs, uint64_t *row, + int x, int y, int w, int h) { - VncState *vs = ds->opaque; - int i; + int x1, x2; + uint64_t mask; - h += y; + if (w == 0) + return; - /* round x down to ensure the loop only spans one 16-pixel block per, - iteration. otherwise, if (x % 16) != 0, the last iteration may span - two 16-pixel blocks but we only mark the first as dirty - */ - w += (x % 16); - x -= (x % 16); + x1 = X2DP_DOWN(vs, x); + x2 = X2DP_UP(vs, x + w); - x = MIN(x, vs->serverds.width); - y = MIN(y, vs->serverds.height); - w = MIN(x + w, vs->serverds.width) - x; - h = MIN(h, vs->serverds.height); + if (X2DP_UP(vs, w) != DIRTY_PIXEL_BITS) + mask = ((1ULL << (x2 - x1)) - 1) << x1; + else + mask = ~(0ULL); + h += y; - if (h > ds_get_height(vs->ds)) - h = ds_get_height(vs->ds); ++ if (h > vs->ds->height) ++ h = vs->ds->height; for (; y < h; y++) - for (i = 0; i < w; i += 16) - vnc_set_bit(vs->dirty_row[y], (x + i) / 16); + row[y] |= mask; +} + +static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) +{ + VncState *vs = ds->opaque; + - x = MIN(x, vs->serverds.width); - y = MIN(y, vs->serverds.height); - w = MIN(w, vs->serverds.width - x); - h = MIN(h, vs->serverds.height - y); ++ x = MIN(x, vs->width); ++ y = MIN(y, vs->height); ++ w = MIN(w, vs->width - x); ++ h = MIN(h, vs->height - y); + + set_bits_in_row(vs, vs->dirty_row, x, y, w, h); } static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h, @@@ -370,43 -268,70 +369,69 @@@ vnc_write_s32(vs, encoding); } -static void buffer_reserve(Buffer *buffer, size_t len) -{ - if ((buffer->capacity - buffer->offset) < len) { - buffer->capacity += (len + 1024); - buffer->buffer = qemu_realloc(buffer->buffer, buffer->capacity); - if (buffer->buffer == NULL) { - fprintf(stderr, "vnc: out of memory\n"); - exit(1); - } - } -} - -static int buffer_empty(Buffer *buffer) -{ - return buffer->offset == 0; -} - -static uint8_t *buffer_end(Buffer *buffer) -{ - return buffer->buffer + buffer->offset; -} - -static void buffer_reset(Buffer *buffer) -{ - buffer->offset = 0; -} - -static void buffer_append(Buffer *buffer, const void *data, size_t len) -{ - memcpy(buffer->buffer + buffer->offset, data, len); - buffer->offset += len; -} - --static void vnc_dpy_resize(DisplayState *ds) ++static void vnc_dpy_resize_shared(DisplayState *ds, int w, int h, int depth, int linesize, void *pixels) { ++ static int allocated; int size_changed; VncState *vs = ds->opaque; + int o; - vs->old_data = qemu_realloc(vs->old_data, ds_get_height(ds) * ds_get_linesize(ds)); - vs->dirty_row = qemu_realloc(vs->dirty_row, ds_get_height(ds) * sizeof(vs->dirty_row[0])); - vs->update_row = qemu_realloc(vs->update_row, ds_get_height(ds) * sizeof(vs->dirty_row[0])); - vs->old_data = qemu_realloc(vs->old_data, ds_get_linesize(ds) * ds_get_height(ds)); ++ vnc_colourdepth(ds, depth); ++ if (!ds->shared_buf) { ++ ds->linesize = w * vs->depth; ++ if (allocated) ++ ds->data = qemu_realloc(ds->data, h * ds->linesize); ++ else ++ ds->data = malloc(h * ds->linesize); ++ allocated = 1; ++ } else { ++ ds->linesize = linesize; ++ if (allocated) { ++ free(ds->data); ++ allocated = 0; ++ } ++ } ++ vs->old_data = qemu_realloc(vs->old_data, h * ds->linesize); ++ vs->dirty_row = qemu_realloc(vs->dirty_row, h * sizeof(vs->dirty_row[0])); ++ vs->update_row = qemu_realloc(vs->update_row, h * sizeof(vs->dirty_row[0])); - if (vs->old_data == NULL || vs->dirty_row == NULL || vs->update_row == NULL) { - if (vs->old_data == NULL) { ++ if (ds->data == NULL || vs->old_data == NULL || ++ vs->dirty_row == NULL || vs->update_row == NULL) { fprintf(stderr, "vnc: memory allocation failed\n"); exit(1); } -- if (ds_get_bytes_per_pixel(ds) != vs->serverds.pf.bytes_per_pixel) ++ if (ds->depth != vs->depth * 8) { ++ ds->depth = vs->depth * 8; console_color_init(ds); -- vnc_colordepth(ds); -- size_changed = ds_get_width(ds) != vs->serverds.width || -- ds_get_height(ds) != vs->serverds.height; -- vs->serverds = *(ds->surface); - if (size_changed) { - if (vs->csock != -1 && vnc_has_feature(vs, VNC_FEATURE_RESIZE)) { - vnc_write_u8(vs, 0); /* msg id */ - vnc_write_u8(vs, 0); - vnc_write_u16(vs, 1); /* number of rects */ - vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), - VNC_ENCODING_DESKTOPRESIZE); - vnc_flush(vs); ++ } ++ size_changed = ds->width != w || ds->height != h; ++ ds->width = w; ++ ds->height = h; + if (vs->csock != -1 && vs->has_resize && size_changed) { ++ vs->width = ds->width; ++ vs->height = ds->height; + if (vs->update_requested) { + vnc_write_u8(vs, 0); /* msg id */ + vnc_write_u8(vs, 0); + vnc_write_u16(vs, 1); /* number of rects */ - vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), -223); ++ vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223); + vnc_flush(vs); + vs->update_requested--; + } else { - enqueue_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), -223); ++ enqueue_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223); } } + vs->dirty_pixel_shift = 0; - for (o = DIRTY_PIXEL_BITS; o < ds_get_width(ds); o *= 2) ++ for (o = DIRTY_PIXEL_BITS; o < ds->width; o *= 2) + vs->dirty_pixel_shift++; - framebuffer_set_updated(vs, 0, 0, ds_get_width(ds), ds_get_height(ds)); ++ framebuffer_set_updated(vs, 0, 0, ds->width, ds->height); ++ if (ds->shared_buf) ds->data = pixels; ++} + - memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row)); - memset(vs->old_data, 42, ds_get_linesize(vs->ds) * ds_get_height(vs->ds)); ++static void vnc_dpy_resize(DisplayState *ds, int w, int h) ++{ ++ vnc_dpy_resize_shared(ds, w, h, 0, w * (ds->depth / 8), NULL); } /* fastest code */ @@@ -420,72 -345,72 +445,62 @@@ static void vnc_convert_pixel(VncState { uint8_t r, g, b; -- r = ((((v & vs->serverds.pf.rmask) >> vs->serverds.pf.rshift) << vs->clientds.pf.rbits) >> -- vs->serverds.pf.rbits); -- g = ((((v & vs->serverds.pf.gmask) >> vs->serverds.pf.gshift) << vs->clientds.pf.gbits) >> -- vs->serverds.pf.gbits); -- b = ((((v & vs->serverds.pf.bmask) >> vs->serverds.pf.bshift) << vs->clientds.pf.bbits) >> -- vs->serverds.pf.bbits); -- v = (r << vs->clientds.pf.rshift) | -- (g << vs->clientds.pf.gshift) | -- (b << vs->clientds.pf.bshift); -- switch(vs->clientds.pf.bytes_per_pixel) { ++ r = ((v >> vs->red_shift1) & vs->red_max1) * (vs->red_max + 1) / (vs->red_max1 + 1); ++ g = ((v >> vs->green_shift1) & vs->green_max1) * (vs->green_max + 1) / (vs->green_max1 + 1); ++ b = ((v >> vs->blue_shift1) & vs->blue_max1) * (vs->blue_max + 1) / (vs->blue_max1 + 1); ++ switch(vs->pix_bpp) { case 1: - buf[0] = v; - buf[0] = v; ++ buf[0] = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift); break; case 2: -- if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { -- buf[0] = v >> 8; -- buf[1] = v; -- } else { -- buf[1] = v >> 8; -- buf[0] = v; ++ { ++ uint16_t *p = (uint16_t *) buf; ++ *p = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift); ++ if (vs->pix_big_endian) { ++ *p = htons(*p); } ++ } break; default: case 4: -- if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { -- buf[0] = v >> 24; -- buf[1] = v >> 16; -- buf[2] = v >> 8; -- buf[3] = v; -- } else { -- buf[3] = v >> 24; -- buf[2] = v >> 16; -- buf[1] = v >> 8; -- buf[0] = v; ++ { ++ uint32_t *p = (uint32_t *) buf; ++ *p = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift); ++ if (vs->pix_big_endian) { ++ *p = htonl(*p); } break; } ++ } } static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size) { uint8_t buf[4]; -- if (vs->serverds.pf.bytes_per_pixel == 4) { ++ if (vs->depth == 4) { uint32_t *pixels = pixels1; int n, i; n = size >> 2; for(i = 0; i < n; i++) { vnc_convert_pixel(vs, buf, pixels[i]); -- vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); ++ vnc_write(vs, buf, vs->pix_bpp); } -- } else if (vs->serverds.pf.bytes_per_pixel == 2) { ++ } else if (vs->depth == 2) { uint16_t *pixels = pixels1; int n, i; n = size >> 1; for(i = 0; i < n; i++) { vnc_convert_pixel(vs, buf, pixels[i]); -- vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); ++ vnc_write(vs, buf, vs->pix_bpp); } -- } else if (vs->serverds.pf.bytes_per_pixel == 1) { ++ } else if (vs->depth == 1) { uint8_t *pixels = pixels1; int n, i; n = size; for(i = 0; i < n; i++) { vnc_convert_pixel(vs, buf, pixels[i]); -- vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); ++ vnc_write(vs, buf, vs->pix_bpp); } } else { fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n"); @@@ -497,12 -422,10 +512,12 @@@ static void send_framebuffer_update_raw int i; uint8_t *row; - row = ds_get_data(vs->ds) + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds); + vnc_framebuffer_update(vs, x, y, w, h, 0); + - row = ds_get_data(vs->ds) + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds); ++ row = vs->ds->data + y * vs->ds->linesize + x * vs->depth; for (i = 0; i < h; i++) { -- vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds)); -- row += ds_get_linesize(vs->ds); ++ vs->write_pixels(vs, row, w * vs->depth); ++ row += vs->ds->linesize; } } @@@ -546,12 -469,10 +561,12 @@@ static void send_framebuffer_update_hex { int i, j; int has_fg, has_bg; - uint8_t *last_fg, *last_bg; + void *last_fg, *last_bg; - last_fg = (uint8_t *) malloc(vs->serverds.pf.bytes_per_pixel); - last_bg = (uint8_t *) malloc(vs->serverds.pf.bytes_per_pixel); + vnc_framebuffer_update(vs, x, y, w, h, 5); + - last_fg = (void *) malloc(vs->serverds.pf.bytes_per_pixel); - last_bg = (void *) malloc(vs->serverds.pf.bytes_per_pixel); ++ last_fg = (void *) malloc(vs->depth); ++ last_bg = (void *) malloc(vs->depth); has_fg = has_bg = 0; for (j = y; j < (y + h); j += 16) { for (i = x; i < (x + w); i += 16) { @@@ -561,48 -482,139 +576,79 @@@ } } free(last_fg); - free(last_bg); - -} - -static void vnc_zlib_init(VncState *vs) -{ - int i; - for (i=0; i<(sizeof(vs->zlib_stream) / sizeof(z_stream)); i++) - vs->zlib_stream[i].opaque = NULL; + free(last_bg); } -static void vnc_zlib_start(VncState *vs) +static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h) { - buffer_reset(&vs->zlib); - - // make the output buffer be the zlib buffer, so we can compress it later - vs->zlib_tmp = vs->output; - vs->output = vs->zlib; + if (vs->has_hextile) + send_framebuffer_update_hextile(vs, x, y, w, h); + else + send_framebuffer_update_raw(vs, x, y, w, h); } -static int vnc_zlib_stop(VncState *vs, int stream_id) +static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { - z_streamp zstream = &vs->zlib_stream[stream_id]; - int previous_out; - - // switch back to normal output/zlib buffers - vs->zlib = vs->output; - vs->output = vs->zlib_tmp; - - // compress the zlib buffer - - // initialize the stream - // XXX need one stream per session - if (zstream->opaque != vs) { - int err; - - VNC_DEBUG("VNC: initializing zlib stream %d\n", stream_id); - VNC_DEBUG("VNC: opaque = %p | vs = %p\n", zstream->opaque, vs); - zstream->zalloc = Z_NULL; - zstream->zfree = Z_NULL; - - err = deflateInit2(zstream, vs->tight_compression, Z_DEFLATED, MAX_WBITS, - MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); - - if (err != Z_OK) { - fprintf(stderr, "VNC: error initializing zlib\n"); - return -1; - } ++ int src, dst; ++ uint8_t *src_row; ++ uint8_t *dst_row; ++ uint8_t *old_row; ++ int y = 0; ++ int pitch = ds->linesize; + VncState *vs = ds->opaque; + int updating_client = 1; - zstream->opaque = vs; ++ if (ds->shared_buf) { ++ framebuffer_set_updated(vs, dst_x, dst_y, w, h); ++ return; + } + - // XXX what to do if tight_compression changed in between? + if (!vs->update_requested || + src_x < vs->visible_x || src_y < vs->visible_y || + dst_x < vs->visible_x || dst_y < vs->visible_y || + (src_x + w) > (vs->visible_x + vs->visible_w) || + (src_y + h) > (vs->visible_y + vs->visible_h) || + (dst_x + w) > (vs->visible_x + vs->visible_w) || + (dst_y + h) > (vs->visible_y + vs->visible_h)) + updating_client = 0; - // reserve memory in output buffer - buffer_reserve(&vs->output, vs->zlib.offset + 64); + if (updating_client) - _vnc_update_client(vs); ++ _vnc_update_client(vs); + - // set pointers - zstream->next_in = vs->zlib.buffer; - zstream->avail_in = vs->zlib.offset; - zstream->next_out = vs->output.buffer + vs->output.offset; - zstream->avail_out = vs->output.capacity - vs->output.offset; - zstream->data_type = Z_BINARY; - previous_out = zstream->total_out; - - // start encoding - if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) { - fprintf(stderr, "VNC: error during zlib compression\n"); - return -1; ++ if (dst_y > src_y) { ++ y = h - 1; ++ pitch = -pitch; + } + - vs->output.offset = vs->output.capacity - zstream->avail_out; - return zstream->total_out - previous_out; -} - -static void send_framebuffer_update_zlib(VncState *vs, int x, int y, int w, int h) -{ - int old_offset, new_offset, bytes_written; - - vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_ZLIB); - - // remember where we put in the follow-up size - old_offset = vs->output.offset; - vnc_write_s32(vs, 0); ++ src = (ds->linesize * (src_y + y) + vs->depth * src_x); ++ dst = (ds->linesize * (dst_y + y) + vs->depth * dst_x); + - // compress the stream - vnc_zlib_start(vs); - send_framebuffer_update_raw(vs, x, y, w, h); - bytes_written = vnc_zlib_stop(vs, 0); - - if (bytes_written == -1) - return; - - // hack in the size - new_offset = vs->output.offset; - vs->output.offset = old_offset; - vnc_write_u32(vs, bytes_written); - vs->output.offset = new_offset; -} ++ src_row = ds->data + src; ++ dst_row = ds->data + dst; ++ old_row = vs->old_data + dst; + -static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h) -{ - switch(vs->vnc_encoding) { - case VNC_ENCODING_ZLIB: - send_framebuffer_update_zlib(vs, x, y, w, h); - break; - case VNC_ENCODING_HEXTILE: - vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE); - send_framebuffer_update_hextile(vs, x, y, w, h); - break; - default: - vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW); - send_framebuffer_update_raw(vs, x, y, w, h); - break; ++ for (y = 0; y < h; y++) { ++ memmove(old_row, src_row, w * vs->depth); ++ memmove(dst_row, src_row, w * vs->depth); ++ src_row += pitch; ++ dst_row += pitch; ++ old_row += pitch; + } -} - -static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h) -{ - VncState *vs = ds->opaque; - vnc_update_client(vs); - - vnc_write_u8(vs, 0); /* msg id */ - vnc_write_u8(vs, 0); - vnc_write_u16(vs, 1); /* number of rects */ - vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT); - vnc_write_u16(vs, src_x); - vnc_write_u16(vs, src_y); - vnc_flush(vs); + if (updating_client && vs->csock != -1 && !vs->has_update) { + vnc_write_u8(vs, 0); /* msg id */ + vnc_write_u8(vs, 0); + vnc_write_u16(vs, 1); /* number of rects */ + vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1); + vnc_write_u16(vs, src_x); + vnc_write_u16(vs, src_y); + vnc_flush(vs); + vs->update_requested--; + } else + framebuffer_set_updated(vs, dst_x, dst_y, w, h); } -static int find_dirty_height(VncState *vs, int y, int last_x, int x) +static int find_update_height(VncState *vs, int y, int maxy, int last_x, int x) { int h; @@@ -617,190 -629,100 +663,190 @@@ return h; } -static void vnc_update_client(void *opaque) +static void _vnc_update_client(void *opaque) { VncState *vs = opaque; + int64_t now; + int y; + uint8_t *row; + uint8_t *old_row; + uint64_t width_mask; + int n_rectangles; + int saved_offset; + int maxx, maxy; - int tile_bytes = vs->serverds.pf.bytes_per_pixel * DP2X(vs, 1); ++ int tile_bytes = vs->depth * DP2X(vs, 1); + + if (!vs->update_requested || vs->csock == -1) + return; + while (!is_empty_queue(vs) && vs->update_requested) { + int enc = vs->upqueue.queue_end->enc; + dequeue_framebuffer_update(vs); + switch (enc) { + case 0x574D5669: + pixel_format_message(vs); + break; + default: + break; + } + vs->update_requested--; + } + if (!vs->update_requested) return; - if (vs->need_update && vs->csock != -1) { - int y; - uint8_t *row; - char *old_row; - uint32_t width_mask[VNC_DIRTY_WORDS]; - int n_rectangles; - int saved_offset; - int has_dirty = 0; - - vga_hw_update(); - - vnc_set_bits(width_mask, (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS); - - /* Walk through the dirty map and eliminate tiles that - really aren't dirty */ - row = ds_get_data(vs->ds); - old_row = vs->old_data; - - for (y = 0; y < ds_get_height(vs->ds); y++) { - if (vnc_and_bits(vs->dirty_row[y], width_mask, VNC_DIRTY_WORDS)) { - int x; - uint8_t *ptr; - char *old_ptr; - - ptr = row; - old_ptr = (char*)old_row; - - for (x = 0; x < ds_get_width(vs->ds); x += 16) { - if (memcmp(old_ptr, ptr, 16 * ds_get_bytes_per_pixel(vs->ds)) == 0) { - vnc_clear_bit(vs->dirty_row[y], (x / 16)); - } else { - has_dirty = 1; - memcpy(old_ptr, ptr, 16 * ds_get_bytes_per_pixel(vs->ds)); - } + now = qemu_get_clock(rt_clock); - if (vs->serverds.width != DP2X(vs, DIRTY_PIXEL_BITS)) - width_mask = (1ULL << X2DP_UP(vs, ds_get_width(vs->ds))) - 1; - ptr += 16 * ds_get_bytes_per_pixel(vs->ds); - old_ptr += 16 * ds_get_bytes_per_pixel(vs->ds); - } - } ++ if (vs->width != DP2X(vs, DIRTY_PIXEL_BITS)) ++ width_mask = (1ULL << X2DP_UP(vs, vs->ds->width)) - 1; + else + width_mask = ~(0ULL); - row += ds_get_linesize(vs->ds); - old_row += ds_get_linesize(vs->ds); - } + /* Walk through the dirty map and eliminate tiles that really + aren't dirty */ - row = ds_get_data(vs->ds); ++ row = vs->ds->data; + old_row = vs->old_data; - for (y = 0; y < ds_get_height(vs->ds); y++) { - if (!has_dirty && !vs->audio_cap) { - qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL); - return; - } ++ for (y = 0; y < vs->ds->height; y++) { + if (vs->dirty_row[y] & width_mask) { + int x; + uint8_t *ptr, *old_ptr; - /* Count rectangles */ - n_rectangles = 0; - vnc_write_u8(vs, 0); /* msg id */ - vnc_write_u8(vs, 0); - saved_offset = vs->output.offset; - vnc_write_u16(vs, 0); + ptr = row; + old_ptr = old_row; - for (x = 0; x < X2DP_UP(vs, ds_get_width(vs->ds)); x++) { - for (y = 0; y < vs->serverds.height; y++) { - int x; - int last_x = -1; - for (x = 0; x < vs->serverds.width / 16; x++) { - if (vnc_get_bit(vs->dirty_row[y], x)) { - if (last_x == -1) { - last_x = x; ++ for (x = 0; x < X2DP_UP(vs, vs->ds->width); x++) { + if (vs->dirty_row[y] & (1ULL << x)) { + if (memcmp(old_ptr, ptr, tile_bytes)) { + vs->has_update = 1; + vs->update_row[y] |= (1ULL << x); + memcpy(old_ptr, ptr, tile_bytes); } - vnc_clear_bit(vs->dirty_row[y], x); - } else { - if (last_x != -1) { - int h = find_dirty_height(vs, y, last_x, x); - send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h); + vs->dirty_row[y] &= ~(1ULL << x); + } + + ptr += tile_bytes; + old_ptr += tile_bytes; + } + } + - row += ds_get_linesize(vs->ds); - old_row += ds_get_linesize(vs->ds); ++ row += vs->ds->linesize; ++ old_row += vs->ds->linesize; + } + - if (!vs->has_update || vs->visible_y >= ds_get_height(vs->ds) || - vs->visible_x >= ds_get_width(vs->ds)) ++ if (!vs->has_update || vs->visible_y >= vs->ds->height || ++ vs->visible_x >= vs->ds->width) + goto backoff; + + /* Count rectangles */ + n_rectangles = 0; + vnc_write_u8(vs, 0); /* msg id */ + vnc_write_u8(vs, 0); + saved_offset = vs->output.offset; + vnc_write_u16(vs, 0); + + maxy = vs->visible_y + vs->visible_h; - if (maxy > ds_get_height(vs->ds)) - maxy = ds_get_height(vs->ds); ++ if (maxy > vs->ds->height) ++ maxy = vs->ds->height; + maxx = vs->visible_x + vs->visible_w; - if (maxx > ds_get_width(vs->ds)) - maxx = ds_get_width(vs->ds); ++ if (maxx > vs->ds->width) ++ maxx = vs->ds->width; + + for (y = vs->visible_y; y < maxy; y++) { + int x; + int last_x = -1; + for (x = X2DP_DOWN(vs, vs->visible_x); + x < X2DP_UP(vs, maxx); x++) { + if (vs->update_row[y] & (1ULL << x)) { + if (last_x == -1) + last_x = x; + vs->update_row[y] &= ~(1ULL << x); + } else { + if (last_x != -1) { + int h = find_update_height(vs, y, maxy, last_x, x); + if (h != 0) { + send_framebuffer_update(vs, DP2X(vs, last_x), y, + DP2X(vs, (x - last_x)), h); n_rectangles++; } - last_x = -1; } + last_x = -1; } - if (last_x != -1) { - int h = find_dirty_height(vs, y, last_x, x); - send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h); + } + if (last_x != -1) { + int h = find_update_height(vs, y, maxy, last_x, x); + if (h != 0) { + send_framebuffer_update(vs, DP2X(vs, last_x), y, + DP2X(vs, (x - last_x)), h); n_rectangles++; } } - vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF; - vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF; - vnc_flush(vs); - } + vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF; + vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF; - if (vs->csock != -1) { - qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL); + if (n_rectangles == 0) { + vs->output.offset = saved_offset - 2; + goto backoff; + } else + vs->update_requested--; + + vs->has_update = 0; + vnc_flush(vs); + vs->last_update_time = now; - dcl->idle = 0; ++ vs->ds->idle = 0; + + vs->timer_interval /= 2; + if (vs->timer_interval < VNC_REFRESH_INTERVAL_BASE) + vs->timer_interval = VNC_REFRESH_INTERVAL_BASE; + + return; + + backoff: + /* No update -> back off a bit */ + vs->timer_interval += VNC_REFRESH_INTERVAL_INC; + if (vs->timer_interval > VNC_REFRESH_INTERVAL_MAX) { + vs->timer_interval = VNC_REFRESH_INTERVAL_MAX; + if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL) { + if (!vs->update_requested) { - dcl->idle = 1; ++ vs->ds->idle = 1; + } else { + /* Send a null update. If the client is no longer + interested (e.g. minimised) it'll ignore this, and we + can stop scanning the buffer until it sends another + update request. */ + /* It turns out that there's a bug in realvncviewer 4.1.2 + which means that if you send a proper null update (with + no update rectangles), it gets a bit out of sync and + never sends any further requests, regardless of whether + it needs one or not. Fix this by sending a single 1x1 + update rectangle instead. */ + vnc_write_u8(vs, 0); + vnc_write_u8(vs, 0); + vnc_write_u16(vs, 1); + send_framebuffer_update(vs, 0, 0, 1, 1); + vnc_flush(vs); + vs->last_update_time = now; + vs->update_requested--; + return; + } + } } + qemu_mod_timer(vs->timer, now + vs->timer_interval); + return; +} + +static void vnc_update_client(void *opaque) +{ + VncState *vs = opaque; + vga_hw_update(); + _vnc_update_client(vs); +} + +static void vnc_timer_init(VncState *vs) +{ + if (vs->timer == NULL) { + vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs); + vs->timer_interval = VNC_REFRESH_INTERVAL_BASE; + } } static int vnc_listen_poll(void *opaque) @@@ -946,11 -818,10 +992,11 @@@ static int vnc_client_io_error(VncStat qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); closesocket(vs->csock); vs->csock = -1; -- dcl->idle = 1; ++ vs->ds->idle = 1; buffer_reset(&vs->input); buffer_reset(&vs->output); - vs->need_update = 0; + free_queue(vs); + vs->update_requested = 0; #ifdef CONFIG_VNC_TLS if (vs->tls_session) { gnutls_deinit(vs->tls_session); @@@ -1161,19 -1031,14 +1207,19 @@@ static void client_cut_text(VncState *v static void check_pointer_type_change(VncState *vs, int absolute) { - if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) { - vnc_write_u8(vs, 0); - vnc_write_u8(vs, 0); - vnc_write_u16(vs, 1); - vnc_framebuffer_update(vs, absolute, 0, - ds_get_width(vs->ds), ds_get_height(vs->ds), - VNC_ENCODING_POINTER_TYPE_CHANGE); - vnc_flush(vs); + if (vs->has_pointer_type_change && vs->absolute != absolute) { + if (vs->update_requested) { + vnc_write_u8(vs, 0); + vnc_write_u8(vs, 0); + vnc_write_u16(vs, 1); + vnc_framebuffer_update(vs, absolute, 0, - ds_get_width(vs->ds), ds_get_height(vs->ds), -257); ++ vs->ds->width, vs->ds->height, -257); + vnc_flush(vs); + vs->update_requested--; + } else { + enqueue_framebuffer_update(vs, absolute, 0, - ds_get_width(vs->ds), ds_get_height(vs->ds), -257); ++ vs->ds->width, vs->ds->height, -257); + } } vs->absolute = absolute; } @@@ -1195,10 -1060,10 +1241,10 @@@ static void pointer_event(VncState *vs dz = 1; if (vs->absolute) { - kbd_mouse_event(x * 0x7FFF / (ds_get_width(vs->ds) - 1), - y * 0x7FFF / (ds_get_height(vs->ds) - 1), - kbd_mouse_event(x * 0x7FFF / (ds_get_width(vs->ds) - 1), - y * 0x7FFF / (ds_get_height(vs->ds) - 1), ++ kbd_mouse_event(x * 0x7FFF / (vs->ds->width - 1), ++ y * 0x7FFF / (vs->ds->height - 1), dz, buttons); - } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) { + } else if (vs->has_pointer_type_change) { x -= 0x7FFF; y -= 0x7FFF; @@@ -1516,114 -1271,136 +1562,116 @@@ static void framebuffer_update_request( static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) { int i; - unsigned int enc = 0; - vnc_zlib_init(vs); - vs->features = 0; - vs->vnc_encoding = 0; - vs->tight_compression = 9; - vs->tight_quality = 9; + vs->has_hextile = 0; + vs->has_resize = 0; + vs->has_pointer_type_change = 0; + vs->has_WMVi = 0; vs->absolute = -1; -- dcl->dpy_copy = NULL; ++ vs->ds->dpy_copy = NULL; for (i = n_encodings - 1; i >= 0; i--) { - enc = encodings[i]; - switch (enc) { - case VNC_ENCODING_RAW: - vs->vnc_encoding = enc; - break; - case VNC_ENCODING_COPYRECT: - dcl->dpy_copy = vnc_copy; - break; - case VNC_ENCODING_HEXTILE: - vs->features |= VNC_FEATURE_HEXTILE_MASK; - vs->vnc_encoding = enc; - break; - case VNC_ENCODING_ZLIB: - vs->features |= VNC_FEATURE_ZLIB_MASK; - vs->vnc_encoding = enc; - break; - case VNC_ENCODING_DESKTOPRESIZE: - vs->features |= VNC_FEATURE_RESIZE_MASK; - break; - case VNC_ENCODING_POINTER_TYPE_CHANGE: - vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK; - break; - case VNC_ENCODING_EXT_KEY_EVENT: - send_ext_key_event_ack(vs); - break; - case VNC_ENCODING_AUDIO: - send_ext_audio_ack(vs); - break; - case VNC_ENCODING_WMVi: - vs->features |= VNC_FEATURE_WMVI_MASK; - break; - case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9: - vs->tight_compression = (enc & 0x0F); - break; - case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9: - vs->tight_quality = (enc & 0x0F); - break; - default: - VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc); - break; - } + switch (encodings[i]) { + case 0: /* Raw */ + vs->has_hextile = 0; + break; + case 1: /* CopyRect */ - dcl->dpy_copy = vnc_copy; ++ vs->ds->dpy_copy = vnc_copy; + break; + case 5: /* Hextile */ + vs->has_hextile = 1; + break; + case -223: /* DesktopResize */ + vs->has_resize = 1; + break; + case -257: + vs->has_pointer_type_change = 1; + break; + case 0x574D5669: + vs->has_WMVi = 1; + default: + break; + } } check_pointer_type_change(vs, kbd_mouse_is_absolute()); } --static void set_pixel_conversion(VncState *vs) --{ -- if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == -- (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) && -- !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) { -- vs->write_pixels = vnc_write_pixels_copy; -- switch (vs->ds->surface->pf.bits_per_pixel) { -- case 8: -- vs->send_hextile_tile = send_hextile_tile_8; -- break; -- case 16: -- vs->send_hextile_tile = send_hextile_tile_16; -- break; -- case 32: -- vs->send_hextile_tile = send_hextile_tile_32; -- break; -- } -- } else { -- vs->write_pixels = vnc_write_pixels_generic; -- switch (vs->ds->surface->pf.bits_per_pixel) { -- case 8: -- vs->send_hextile_tile = send_hextile_tile_generic_8; -- break; -- case 16: -- vs->send_hextile_tile = send_hextile_tile_generic_16; -- break; -- case 32: -- vs->send_hextile_tile = send_hextile_tile_generic_32; -- break; -- } -- } --} -- static void set_pixel_format(VncState *vs, int bits_per_pixel, int depth, int big_endian_flag, int true_color_flag, int red_max, int green_max, int blue_max, int red_shift, int green_shift, int blue_shift) { ++ int host_big_endian_flag; ++ ++#ifdef WORDS_BIGENDIAN ++ host_big_endian_flag = 1; ++#else ++ host_big_endian_flag = 0; ++#endif if (!true_color_flag) { ++ fail: vnc_client_error(vs); return; } -- -- vs->clientds = vs->serverds; -- vs->clientds.pf.rmax = red_max; -- count_bits(vs->clientds.pf.rbits, red_max); -- vs->clientds.pf.rshift = red_shift; -- vs->clientds.pf.rmask = red_max << red_shift; -- vs->clientds.pf.gmax = green_max; -- count_bits(vs->clientds.pf.gbits, green_max); -- vs->clientds.pf.gshift = green_shift; -- vs->clientds.pf.gmask = green_max << green_shift; -- vs->clientds.pf.bmax = blue_max; -- count_bits(vs->clientds.pf.bbits, blue_max); -- vs->clientds.pf.bshift = blue_shift; -- vs->clientds.pf.bmask = blue_max << blue_shift; -- vs->clientds.pf.bits_per_pixel = bits_per_pixel; -- vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8; -- vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel; -- vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00; -- -- set_pixel_conversion(vs); -- -- vga_hw_invalidate(); -- vga_hw_update(); ++ if (bits_per_pixel == 32 && ++ bits_per_pixel == vs->depth * 8 && ++ host_big_endian_flag == big_endian_flag && ++ red_max == 0xff && green_max == 0xff && blue_max == 0xff && ++ red_shift == 16 && green_shift == 8 && blue_shift == 0) { ++ vs->write_pixels = vnc_write_pixels_copy; ++ vs->send_hextile_tile = send_hextile_tile_32; ++ } else ++ if (bits_per_pixel == 16 && ++ bits_per_pixel == vs->depth * 8 && ++ host_big_endian_flag == big_endian_flag && ++ red_max == 31 && green_max == 63 && blue_max == 31 && ++ red_shift == 11 && green_shift == 5 && blue_shift == 0) { ++ vs->write_pixels = vnc_write_pixels_copy; ++ vs->send_hextile_tile = send_hextile_tile_16; ++ } else ++ if (bits_per_pixel == 8 && ++ bits_per_pixel == vs->depth * 8 && ++ red_max == 7 && green_max == 7 && blue_max == 3 && ++ red_shift == 5 && green_shift == 2 && blue_shift == 0) { ++ vs->depth = 1; ++ vs->write_pixels = vnc_write_pixels_copy; ++ vs->send_hextile_tile = send_hextile_tile_8; ++ } else ++ { ++ /* generic and slower case */ ++ if (bits_per_pixel != 8 && ++ bits_per_pixel != 16 && ++ bits_per_pixel != 32) ++ goto fail; ++ if (vs->depth == 4) { ++ vs->send_hextile_tile = send_hextile_tile_generic_32; ++ } else if (vs->depth == 2) { ++ vs->send_hextile_tile = send_hextile_tile_generic_16; ++ } else { ++ vs->send_hextile_tile = send_hextile_tile_generic_8; ++ } ++ ++ vs->pix_big_endian = big_endian_flag; ++ vs->write_pixels = vnc_write_pixels_generic; ++ } ++ ++ vs->red_shift = red_shift; ++ vs->red_max = red_max; ++ vs->green_shift = green_shift; ++ vs->green_max = green_max; ++ vs->blue_shift = blue_shift; ++ vs->blue_max = blue_max; ++ vs->pix_bpp = bits_per_pixel / 8; } static void pixel_format_message (VncState *vs) { char pad[3] = { 0, 0, 0 }; -- vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */ -- vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */ ++ vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */ ++ if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */ ++ else vnc_write_u8(vs, vs->depth * 8); /* depth */ #ifdef WORDS_BIGENDIAN vnc_write_u8(vs, 1); /* big-endian-flag */ @@@ -1631,51 -1408,45 +1679,150 @@@ vnc_write_u8(vs, 0); /* big-endian-flag */ #endif vnc_write_u8(vs, 1); /* true-color-flag */ -- vnc_write_u16(vs, vs->ds->surface->pf.rmax); /* red-max */ -- vnc_write_u16(vs, vs->ds->surface->pf.gmax); /* green-max */ -- vnc_write_u16(vs, vs->ds->surface->pf.bmax); /* blue-max */ -- vnc_write_u8(vs, vs->ds->surface->pf.rshift); /* red-shift */ -- vnc_write_u8(vs, vs->ds->surface->pf.gshift); /* green-shift */ -- vnc_write_u8(vs, vs->ds->surface->pf.bshift); /* blue-shift */ -- if (vs->ds->surface->pf.bits_per_pixel == 32) ++ if (vs->depth == 4) { ++ vnc_write_u16(vs, 0xFF); /* red-max */ ++ vnc_write_u16(vs, 0xFF); /* green-max */ ++ vnc_write_u16(vs, 0xFF); /* blue-max */ ++ vnc_write_u8(vs, 16); /* red-shift */ ++ vnc_write_u8(vs, 8); /* green-shift */ ++ vnc_write_u8(vs, 0); /* blue-shift */ vs->send_hextile_tile = send_hextile_tile_32; -- else if (vs->ds->surface->pf.bits_per_pixel == 16) ++ } else if (vs->depth == 2) { ++ vnc_write_u16(vs, 31); /* red-max */ ++ vnc_write_u16(vs, 63); /* green-max */ ++ vnc_write_u16(vs, 31); /* blue-max */ ++ vnc_write_u8(vs, 11); /* red-shift */ ++ vnc_write_u8(vs, 5); /* green-shift */ ++ vnc_write_u8(vs, 0); /* blue-shift */ vs->send_hextile_tile = send_hextile_tile_16; -- else if (vs->ds->surface->pf.bits_per_pixel == 8) ++ } else if (vs->depth == 1) { ++ /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */ ++ vnc_write_u16(vs, 7); /* red-max */ ++ vnc_write_u16(vs, 7); /* green-max */ ++ vnc_write_u16(vs, 3); /* blue-max */ ++ vnc_write_u8(vs, 5); /* red-shift */ ++ vnc_write_u8(vs, 2); /* green-shift */ ++ vnc_write_u8(vs, 0); /* blue-shift */ vs->send_hextile_tile = send_hextile_tile_8; -- vs->clientds = *(vs->ds->surface); - vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG; - vs->clientds.flags |= ~QEMU_ALLOCATED_FLAG; ++ } ++ vs->red_max = vs->red_max1; ++ vs->green_max = vs->green_max1; ++ vs->blue_max = vs->blue_max1; ++ vs->red_shift = vs->red_shift1; ++ vs->green_shift = vs->green_shift1; ++ vs->blue_shift = vs->blue_shift1; ++ vs->pix_bpp = vs->depth * 8; vs->write_pixels = vnc_write_pixels_copy; -- ++ vnc_write(vs, pad, 3); /* padding */ } --static void vnc_dpy_setdata(DisplayState *ds) ++static void vnc_dpy_setdata(DisplayState *ds, void *pixels) { -- /* We don't have to do anything */ ++ ds->data = pixels; } --static void vnc_colordepth(DisplayState *ds) ++static void vnc_colourdepth(DisplayState *ds, int depth) { ++ int host_big_endian_flag; struct VncState *vs = ds->opaque; - if (vs->csock != -1 && vnc_has_feature(vs, VNC_FEATURE_WMVI)) { ++ switch (depth) { ++ case 24: ++ ds->shared_buf = 0; ++ if (ds->depth == 32) return; ++ depth = 32; ++ break; ++ case 8: ++ case 0: ++ ds->shared_buf = 0; ++ return; ++ default: ++ ds->shared_buf = 1; ++ break; ++ } ++ ++#ifdef WORDS_BIGENDIAN ++ host_big_endian_flag = 1; ++#else ++ host_big_endian_flag = 0; ++#endif ++ ++ switch (depth) { ++ case 8: ++ vs->depth = depth / 8; ++ vs->red_max1 = 7; ++ vs->green_max1 = 7; ++ vs->blue_max1 = 3; ++ vs->red_shift1 = 5; ++ vs->green_shift1 = 2; ++ vs->blue_shift1 = 0; ++ break; ++ case 16: ++ vs->depth = depth / 8; ++ vs->red_max1 = 31; ++ vs->green_max1 = 63; ++ vs->blue_max1 = 31; ++ vs->red_shift1 = 11; ++ vs->green_shift1 = 5; ++ vs->blue_shift1 = 0; ++ break; ++ case 32: ++ vs->depth = 4; ++ vs->red_max1 = 255; ++ vs->green_max1 = 255; ++ vs->blue_max1 = 255; ++ vs->red_shift1 = 16; ++ vs->green_shift1 = 8; ++ vs->blue_shift1 = 0; ++ break; ++ default: ++ return; ++ } + if (vs->switchbpp) { + vnc_client_error(vs); + } else if (vs->csock != -1 && vs->has_WMVi) { /* Sending a WMVi message to notify the client*/ - vnc_write_u8(vs, 0); /* msg id */ - vnc_write_u8(vs, 0); - vnc_write_u16(vs, 1); /* number of rects */ - vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), - VNC_ENCODING_WMVi); - pixel_format_message(vs); - vnc_flush(vs); + if (vs->update_requested) { + vnc_write_u8(vs, 0); /* msg id */ + vnc_write_u8(vs, 0); + vnc_write_u16(vs, 1); /* number of rects */ - vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), 0x574D5669); ++ vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, 0x574D5669); + pixel_format_message(vs); + vnc_flush(vs); + vs->update_requested--; + } else { - enqueue_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), 0x574D5669); ++ enqueue_framebuffer_update(vs, 0, 0, ds->width, ds->height, 0x574D5669); + } } else { -- set_pixel_conversion(vs); ++ if (vs->pix_bpp == 4 && vs->depth == 4 && ++ host_big_endian_flag == vs->pix_big_endian && ++ vs->red_max == 0xff && vs->green_max == 0xff && vs->blue_max == 0xff && ++ vs->red_shift == 16 && vs->green_shift == 8 && vs->blue_shift == 0) { ++ vs->write_pixels = vnc_write_pixels_copy; ++ vs->send_hextile_tile = send_hextile_tile_32; ++ } else if (vs->pix_bpp == 2 && vs->depth == 2 && ++ host_big_endian_flag == vs->pix_big_endian && ++ vs->red_max == 31 && vs->green_max == 63 && vs->blue_max == 31 && ++ vs->red_shift == 11 && vs->green_shift == 5 && vs->blue_shift == 0) { ++ vs->write_pixels = vnc_write_pixels_copy; ++ vs->send_hextile_tile = send_hextile_tile_16; ++ } else if (vs->pix_bpp == 1 && vs->depth == 1 && ++ host_big_endian_flag == vs->pix_big_endian && ++ vs->red_max == 7 && vs->green_max == 7 && vs->blue_max == 3 && ++ vs->red_shift == 5 && vs->green_shift == 2 && vs->blue_shift == 0) { ++ vs->write_pixels = vnc_write_pixels_copy; ++ vs->send_hextile_tile = send_hextile_tile_8; ++ } else { ++ if (vs->depth == 4) { ++ vs->send_hextile_tile = send_hextile_tile_generic_32; ++ } else if (vs->depth == 2) { ++ vs->send_hextile_tile = send_hextile_tile_generic_16; ++ } else { ++ vs->send_hextile_tile = send_hextile_tile_generic_8; ++ } ++ vs->write_pixels = vnc_write_pixels_generic; ++ } } } @@@ -1765,12 -1588,11 +1912,14 @@@ static int protocol_client_msg(VncStat static int protocol_client_init(VncState *vs, uint8_t *data, size_t len) { - char buf[1024]; - int size; + size_t l; - vnc_write_u16(vs, ds_get_width(vs->ds)); - vnc_write_u16(vs, ds_get_height(vs->ds)); + vga_hw_update(); + - vnc_write_u16(vs, ds_get_width(vs->ds)); - vnc_write_u16(vs, ds_get_height(vs->ds)); ++ vs->width = vs->ds->width; ++ vs->height = vs->ds->height; ++ vnc_write_u16(vs, vs->ds->width); ++ vnc_write_u16(vs, vs->ds->height); pixel_format_message(vs); @@@ -2386,19 -2227,7 +2535,19 @@@ static void vnc_listen_read(void *opaqu vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); if (vs->csock != -1) { - vnc_connect(vs); + VNC_DEBUG("New client on socket %d\n", vs->csock); - dcl->idle = 0; ++ vs->ds->idle = 0; + socket_set_nonblock(vs->csock); + qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque); + vnc_write(vs, "RFB 003.008\n", 12); + vnc_flush(vs); + vnc_read_when(vs, protocol_version, 12); - framebuffer_set_updated(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds)); ++ framebuffer_set_updated(vs, 0, 0, vs->ds->width, vs->ds->height); + vs->has_resize = 0; + vs->has_hextile = 0; + vs->update_requested = 0; - dcl->dpy_copy = NULL; ++ vs->ds->dpy_copy = NULL; + vnc_timer_init(vs); } } @@@ -2409,12 -2236,12 +2558,11 @@@ void vnc_display_init(DisplayState *ds VncState *vs; vs = qemu_mallocz(sizeof(VncState)); -- dcl = qemu_mallocz(sizeof(DisplayChangeListener)); -- if (!vs || !dcl) ++ if (!vs) exit(1); ds->opaque = vs; -- dcl->idle = 1; ++ ds->idle = 1; vnc_state = vs; vs->display = NULL; vs->password = NULL; @@@ -2426,19 -2253,26 +2574,25 @@@ vs->ds = ds; - if (keyboard_layout) - vs->kbd_layout = init_keyboard_layout(keyboard_layout); - else - vs->kbd_layout = init_keyboard_layout("en-us"); + if (!keyboard_layout) + keyboard_layout = "en-us"; + vs->kbd_layout = init_keyboard_layout(keyboard_layout); if (!vs->kbd_layout) exit(1); + vs->modifiers_state[0x45] = 1; /* NumLock on - on boot */ - vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs); - -- dcl->dpy_update = vnc_dpy_update; -- dcl->dpy_resize = vnc_dpy_resize; -- dcl->dpy_setdata = vnc_dpy_setdata; -- dcl->dpy_refresh = NULL; -- register_displaychangelistener(ds, dcl); ++ vs->ds->data = NULL; ++ vs->ds->dpy_update = vnc_dpy_update; ++ vs->ds->dpy_resize = vnc_dpy_resize; ++ vs->ds->dpy_setdata = vnc_dpy_setdata; ++ vs->ds->dpy_resize_shared = vnc_dpy_resize_shared; ++ vs->ds->dpy_refresh = NULL; + - vs->as.freq = 44100; - vs->as.nchannels = 2; - vs->as.fmt = AUD_FMT_S16; - vs->as.endianness = 0; ++ vs->ds->width = 640; ++ vs->ds->height = 400; ++ vs->ds->linesize = 640 * 4; ++ vnc_dpy_resize_shared(ds, ds->width, ds->height, 24, ds->linesize, NULL); } #ifdef CONFIG_VNC_TLS diff --cc xen-vl-extra.c index d01bf471,00000000..2bb32eb2 mode 100644,000000..100644 --- a/xen-vl-extra.c +++ b/xen-vl-extra.c @@@ -1,133 -1,0 +1,151 @@@ +/* + * We #include this from vl.c. + * + * This is a bit yucky, but it means that the line numbers and other + * textual differences in vl.c remain small. + */ +/* There is no need for multiple-inclusion protection since + * there is only one place where this file is included. */ + +#include "qemu-xen.h" + ++ ++/* Max number of PCI emulation */ ++#define MAX_PCI_EMULATION 32 ++ ++int restore; ++#ifdef CONFIG_OPENGL ++int opengl_enabled = 1; ++#else ++int opengl_enabled = 0; ++#endif ++static const char *direct_pci; ++static int nb_pci_emulation = 0; ++static char pci_emulation_config_text[MAX_PCI_EMULATION][256]; ++PCI_EMULATION_INFO *PciEmulationInfoHead = NULL; ++ ++int vncunused; ++ ++ +/* We use simpler state save/load functions for Xen */ + +void do_savevm(const char *name) +{ + QEMUFile *f; + int saved_vm_running, ret; + + f = qemu_fopen(name, "wb"); + + /* ??? Should this occur after vm_stop? */ + qemu_aio_flush(); + + saved_vm_running = vm_running; + vm_stop(0); + + if (!f) { + fprintf(logfile, "Failed to open savevm file '%s'\n", name); + goto the_end; + } + + ret = qemu_savevm_state(f); + qemu_fclose(f); + + if (ret < 0) + fprintf(logfile, "Error %d while writing VM to savevm file '%s'\n", + ret, name); + + the_end: + if (saved_vm_running) + vm_start(); + + return; +} +void do_loadvm(const char *name) +{ + QEMUFile *f; + int saved_vm_running, ret; + + /* Flush all IO requests so they don't interfere with the new state. */ + qemu_aio_flush(); + + saved_vm_running = vm_running; + vm_stop(0); + + /* restore the VM state */ + f = qemu_fopen(name, "rb"); + if (!f) { + fprintf(logfile, "Could not open VM state file\n"); + goto the_end; + } + + ret = qemu_loadvm_state(f); + qemu_fclose(f); + if (ret < 0) { + fprintf(logfile, "Error %d while loading savevm file '%s'\n", + ret, name); + goto the_end; + } + +#if 0 + /* del tmp file */ + if (unlink(name) == -1) + fprintf(stderr, "delete tmp qemu state file failed.\n"); +#endif + + + the_end: + if (saved_vm_running) + vm_start(); +} + +struct qemu_alarm_timer; +static int unix_start_timer(struct qemu_alarm_timer *t) { return 0; } +static void unix_stop_timer(struct qemu_alarm_timer *t) { } + +#ifdef CONFIG_STUBDOM +#include +static int tap_open(char *ifname, int ifname_size) +{ + char nodename[64]; + static int num = 1; // 0 is for our own TCP/IP networking + snprintf(nodename, sizeof(nodename), "device/vif/%d", num++); + return netfront_tap_open(nodename); +} + +#undef DEFAULT_NETWORK_SCRIPT +#define DEFAULT_NETWORK_SCRIPT "" +#undef DEFAULT_NETWORK_DOWN_SCRIPT +#define DEFAULT_NETWORK_DOWN_SCRIPT "" +#endif + +#ifdef CONFIG_PASSTHROUGH +void do_pci_del(char *devname) +{ + int pci_slot; + pci_slot = bdf_to_slot(devname); + + acpi_php_del(pci_slot); +} + +void do_pci_add(char *devname) +{ + int pci_slot; + + pci_slot = insert_to_pci_slot(devname); + + acpi_php_add(pci_slot); +} + +static int pci_emulation_add(char *config_text) +{ + PCI_EMULATION_INFO *new; + if ((new = qemu_mallocz(sizeof(PCI_EMULATION_INFO))) == NULL) { + return -1; + } + parse_pci_emulation_info(config_text, new); + new->next = PciEmulationInfoHead; + PciEmulationInfoHead = new; + return 0; +} + +#endif