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
######################################################################
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
# libqemu
+-include hookslib.mak
+-include hookstarget.mak
+
libqemu.a: $(LIBOBJS)
- rm -f $@
- $(AR) rcs $@ $(LIBOBJS)
translate.o: translate.c cpu.h
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
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;
{
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;
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) {
}
break;
}
-- d1 += ds_get_linesize(ds);
++ d1 += ds->linesize;
}
}
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;
}
}
}
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;
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++;
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;
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);
}
}
}
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);
}
}
}
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++) {
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)
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);
}
}
}
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();
}
}
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;
}
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);
}
}
}
--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;
} 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)
}
}
--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;
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;
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);
}
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)
{
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;
static void unmap_linear_vram(CirrusVGAState *s)
{
- if (s->map_addr && s->lfb_addr && s->lfb_end) {
- vga_dirty_log_stop((VGAState *)s);
+ if (s->lfb_addr && s->lfb_end && s->vram_gmfn != s->lfb_addr) {
+ unset_vram_mapping(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);
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);
}
/***************************************
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 */
}
/* 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 */
int type; /* see IDE_TYPE_xxx */
} PCIIDEState;
+static PCIIDEState *principal_ide_controller;
+
+#if defined(__ia64__)
+#include <xen/hvm/ioreq.h>
+
+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)
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;
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;
}
}
+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;
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) {
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)
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;
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);
}
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);
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 */
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);
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 */
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,
/* 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;
}
}
- rtc_state = rtc_init(0x70, i8259[8]);
+#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], 2000);
qemu_register_boot_set(pc_boot_set, rtc_state);
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,
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)
extern enum vga_retrace_method vga_retrace_method;
-int isa_vga_init(uint8_t *vga_ram_base,
+ #ifndef TARGET_SPARC
+ #define VGA_RAM_SIZE (8192 * 1024)
+ #else
+ #define VGA_RAM_SIZE (9 * 1024 * 1024)
+ #endif
+
+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);
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);
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;
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;
#define STATUS_GOOD 0
#define STATUS_CHECK_CONDITION 2
+#ifdef CONFIG_STUBDOM
+#include <xen/io/blkif.h>
+#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;
static inline int get_depth_index(DisplayState *s)
{
-- switch(ds_get_bits_per_pixel(s)) {
++ switch(s->depth) {
default:
case 8:
return 0;
case 16:
return 2;
case 32:
-- return 3;
++ if (s->bgr)
++ return 4;
++ else
++ return 3;
}
}
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)];
- x_incr = cw * ds_get_bytes_per_pixel(s->ds);
+ full_update |= update_palette16(s);
+ palette = s->last_palette;
+
++ 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;
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;
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;
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) {
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;
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;
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);
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);
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;
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;
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 ++, ' ');
}
}
-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;
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;
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;
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,
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)
{
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;
/********************************************************/
/* 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);
-}
VGA_STATE_COMMON_BOCHS_VBE \
/* display refresh support */ \
DisplayState *ds; \
++ QEMUConsole *console; \
uint32_t font_offsets[2]; \
int graphic_mode; \
uint8_t shift_control; \
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,
--- /dev/null
+/*
+ * 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 <xen/hvm/params.h>
+#include <sys/mman.h>
+
+#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:
+ */
--- /dev/null
+/*
+ * 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:
+ */
#define WIN32_LEAN_AND_MEAN
#define WINVER 0x0501 /* needed for ipv6 bits */
#include <windows.h>
++#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__
#include <signal.h>
#endif
-static DisplayChangeListener *dcl;
-static SDL_Surface *real_screen;
-static SDL_Surface *guest_screen = NULL;
+#ifdef CONFIG_OPENGL
+#include <SDL_opengl.h>
+#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;
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)
+
- if (opengl_enabled)
++ sdl_colourdepth(ds, depth);
++
+#ifdef CONFIG_OPENGL
- flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
++ if (ds->shared_buf && opengl_enabled)
+ flags = SDL_OPENGL|SDL_RESIZABLE;
+ else
+#endif
- if (gui_fullscreen)
++ flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_DOUBLEBUF|SDL_HWPALETTE;
+
++ 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 */
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;
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();
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:
!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;
}
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;
#include "kvm.h"
#include "balloon.h"
- #include <unistd.h>
++#include "hw/pci.h"
++#include "hw/xen.h"
+#include <stdlib.h>
++
+ #include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
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"
" 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
#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"
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,
#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
- { "vcpus", 1, QEMU_OPTION_vcpus },
++
++ /* 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
- { "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 },
+ { "acpi", 0, QEMU_OPTION_acpi }, /* deprecated, for xend compatibility */
+ { "direct_pci", HAS_ARG, QEMU_OPTION_direct_pci },
+ { "pciemulation", HAS_ARG, QEMU_OPTION_pci_emulation },
- #ifdef CONFIG_CURSES
- { "curses", 0, QEMU_OPTION_curses },
- #endif
- { "uuid", HAS_ARG, QEMU_OPTION_uuid },
+ { "vncunused", 0, QEMU_OPTION_vncunused },
- /* 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
+#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
+
#if defined(TARGET_ARM)
{ "old-param", 0, QEMU_OPTION_old_param },
#endif
int autostart;
const char *incoming = NULL;
- #endif
-
- qemu_cache_utils_init(envp);
+ 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
LIST_INIT (&vm_change_state_head);
#ifndef _WIN32
break;
case QEMU_OPTION_loadvm:
loadvm = optarg;
- restore = 1;
++ restore = 1;
break;
case QEMU_OPTION_full_screen:
full_screen = 1;
case QEMU_OPTION_no_quit:
no_quit = 1;
break;
+ case QEMU_OPTION_sdl:
+ sdl = 1;
+ break;
#endif
- direct_pci = optarg;
++
++ 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;
+ 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;
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:
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]))
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 */
}
}
- 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()) {
}
}
- 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
#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
{
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;
/* 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;
};
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)
{
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);
}
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);
- if (h > ds_get_height(vs->ds))
- h = ds_get_height(vs->ds);
+ h += y;
++ 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,
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);
}
}
- for (o = DIRTY_PIXEL_BITS; o < ds_get_width(ds); o *= 2)
+ vs->dirty_pixel_shift = 0;
- framebuffer_set_updated(vs, 0, 0, ds_get_width(ds), ds_get_height(ds));
++ for (o = DIRTY_PIXEL_BITS; o < ds->width; o *= 2)
+ vs->dirty_pixel_shift++;
- memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
- memset(vs->old_data, 42, ds_get_linesize(vs->ds) * ds_get_height(vs->ds));
++ framebuffer_set_updated(vs, 0, 0, ds->width, ds->height);
++ if (ds->shared_buf) ds->data = pixels;
++}
+
++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 */
{
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");
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;
}
}
{
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) {
}
}
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;
return h;
}
-static void vnc_update_client(void *opaque)
+static void _vnc_update_client(void *opaque)
{
VncState *vs = opaque;
- int tile_bytes = vs->serverds.pf.bytes_per_pixel * DP2X(vs, 1);
+ 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->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)
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);
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;
}
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;
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 */
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;
++ }
}
}
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);
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);
}
}
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;
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
--- /dev/null
+/*
+ * 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 <netfront.h>
+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