From: Jean Guyader Date: Tue, 26 May 2009 10:57:48 +0000 (+0100) Subject: Complete refactoring and port of the intel driver to xen 3.4. X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=1f822748d43a54e74449129233b322a47e171e48;p=xenclient%2Fioemu-pq.git Complete refactoring and port of the intel driver to xen 3.4. --- diff --git a/master/intel b/master/intel index 3520c50..af0f3c7 100644 --- a/master/intel +++ b/master/intel @@ -1,34 +1,45 @@ diff --git a/console.h b/console.h -index 97214c0..4c51c50 100644 +index 97214c0..8c9b09b 100644 --- a/console.h +++ b/console.h -@@ -290,6 +290,9 @@ void vga_hw_update(void); +@@ -70,6 +70,8 @@ void kbd_put_keysym(int keysym); + #define QEMU_BIG_ENDIAN_FLAG 0x01 + #define QEMU_ALLOCATED_FLAG 0x02 + ++#define INTEL_MAPPED_FLAG 0x04 ++ + struct PixelFormat { + uint8_t bits_per_pixel; + uint8_t bytes_per_pixel; +@@ -290,6 +292,11 @@ void vga_hw_update(void); void vga_hw_invalidate(void); void vga_hw_screen_dump(const char *filename); - + +void unset_vga_acc(void); +void set_vga_acc(void); ++extern uint32_t guest_framebuffer; ++extern int intel_output; + int is_graphic_console(void); int is_fixedsize_console(void); CharDriverState *text_console_init(const char *p); -@@ -356,4 +359,8 @@ void hid_linux_add_binding(const int *, void (*)(void*), void *); +@@ -356,4 +363,8 @@ void hid_linux_add_binding(const int *, void (*)(void*), void *); void hid_linux_reset_keyboard(void); void hid_linux_probe(int grab); - + +/* intel.c */ +int intel_enter(void); +int intel_leave(void); +void intel_display_init(DisplayState *ds); #endif diff --git a/hw/vga.c b/hw/vga.c -index 90bd544..b0f9f9c 100644 +index 90bd544..d515e9d 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -161,6 +161,18 @@ static uint8_t expand4to8[16]; static void vga_bios_init(VGAState *s); static void vga_screen_dump(void *opaque, const char *filename); - + +static VGAState *xen_vga_state; + +void set_vga_acc(void) @@ -44,10 +55,37 @@ index 90bd544..b0f9f9c 100644 static void vga_dumb_update_retrace_info(VGAState *s) { (void) s; -@@ -2473,8 +2485,6 @@ static void vga_bios_init(VGAState *s) +@@ -1596,15 +1608,12 @@ static void vga_draw_graphic(VGAState *s, int full_update) + } + + depth = s->get_bpp(s); ++ guest_framebuffer = s->lfb_addr + (s->start_addr * 4); + 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); + s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth, +@@ -1632,7 +1641,8 @@ static void vga_draw_graphic(VGAState *s, int full_update) + s->ds->surface->data = s->vram_ptr + (s->start_addr * 4); + dpy_setdata(s->ds); + } +- ++ if (intel_output && is_buffer_shared(s->ds->surface)) ++ return; + s->rgb_to_pixel = + rgb_to_pixel_dup_table[get_depth_index(s->ds)]; + +@@ -2473,8 +2483,6 @@ static void vga_bios_init(VGAState *s) } - - + + -static VGAState *xen_vga_state; - /* Allocate video memory in the GPFN space */ @@ -55,10 +93,10 @@ index 90bd544..b0f9f9c 100644 { diff --git a/intel.c b/intel.c new file mode 100644 -index 0000000..4c5f773 +index 0000000..8a20756 --- /dev/null +++ b/intel.c -@@ -0,0 +1,494 @@ +@@ -0,0 +1,405 @@ +#include +#include +#include @@ -94,7 +132,7 @@ index 0000000..4c5f773 + +extern int vga_passthrough; +uint32_t guest_framebuffer; -+ ++int intel_output; +static int display = 0; + +static int mmio_fd = -1; @@ -107,14 +145,11 @@ index 0000000..4c5f773 +static int IntelX = 1280; +static int IntelY = 1024; +static DisplayState *lds = NULL; -+static uint8_t *old_data = NULL; +static uint32_t intel_fb_base, intel_mmio_base; +static uint32_t map_s, map_d, map_size; +static int refresh; + -+static void set_data_mappings(void); -+static void unset_data_mappings(int mapping); -+static void set_data_pointer(void); ++static void set_data_pointer(DisplaySurface *surf); +static void intel_resize(DisplayState *ds); + +static inline unsigned int intel_get_reg(unsigned int reg) @@ -137,26 +172,6 @@ index 0000000..4c5f773 + return *dspastride; +} + -+static inline unsigned int intel_get_offset(DisplaySurface *ds, int x, int y) -+{ -+ return (y * ds->width + x) * 4; -+} -+ -+static void intel_update_linear(DisplaySurface *ds, int x, int y, int w, int h) -+{ -+ int i, bpp = ds->pf.depth / 8; -+ unsigned char *s, *d; -+ s = ds->data; -+ d = (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)); -+ s += (ds->linesize * y) + bpp * x; -+ d += (ds->linesize * y) + bpp * x; -+ for (i = 0; i < h; i++) { -+ memcpy(d, s, w * bpp); -+ s += ds->linesize; -+ d += ds->linesize; -+ } -+} -+ +static void intel_force_linear(int linesize) +{ + unsigned int *dspacntr = (unsigned int *)(intel_mmio + REG_DR_DSPACNTR); @@ -220,16 +235,11 @@ index 0000000..4c5f773 + *dspbcntr |= (1 << 31); + *pipebconf |= pipeb; + } ++ if (linesize) IntelPitch = linesize; + + usleep(20000); +} + -+static void intel_update(DisplayState *ds, int x, int y, int w, int h) -+{ -+ if (intel_have_focus && !old_data && !map_size) -+ intel_update_linear(ds->surface, x, y, w, h); -+} -+ +static void set_fb_mapping(void) +{ + DisplaySurface *surf = lds->surface; @@ -237,8 +247,8 @@ index 0000000..4c5f773 + unsigned long nr_pfn; + + unset_vga_acc(); -+ fprintf(stderr, "set_fb_mapping: %x %x\n", (intel_fb_base + intel_get_reg(REG_DR_DSPASURF)), guest_framebuffer); -+ nr_pfn = (surf->linesize * surf->height) >> TARGET_PAGE_BITS; ++ INTEL_DEBUG("set_fb_mapping: %x %x\n", (intel_fb_base + intel_get_reg(REG_DR_DSPASURF)), guest_framebuffer); ++ nr_pfn = (ds_get_linesize(lds) * ds_get_height(lds)) >> TARGET_PAGE_BITS; + + rc = xc_domain_memory_mapping(xc_handle, + domid, @@ -250,6 +260,8 @@ index 0000000..4c5f773 + fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc); + return; + } ++ memcpy((uint8_t *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)), ++ ds_get_data(lds), ds_get_linesize(lds) * ds_get_height(lds)); + map_s = ((intel_fb_base + intel_get_reg(REG_DR_DSPASURF)) >> TARGET_PAGE_BITS); + map_d = (guest_framebuffer >> TARGET_PAGE_BITS); + map_size = nr_pfn; @@ -259,7 +271,7 @@ index 0000000..4c5f773 +{ + int rc; + -+ fprintf(stderr, "unset_fb_mapping: %x %x\n", map_d, map_s); ++ INTEL_DEBUG("unset_fb_mapping: %x %x\n", map_d, map_s); + + rc = xc_domain_memory_mapping(xc_handle, + domid, @@ -273,118 +285,48 @@ index 0000000..4c5f773 + } + + set_vga_acc(); ++ memcpy(ds_get_data(lds), ++ (uint8_t *) (intel_mem + intel_get_reg(REG_DR_DSPASURF)), ++ ds_get_linesize(lds) * ds_get_height(lds)); + map_s = 0; + map_d = 0; + map_size = 0; +} + -+static void intel_setdata(DisplayState *ds) ++ ++static void intel_update(DisplayState *ds, int x, int y, int w, int h) +{ -+ if (map_size) -+ unset_fb_mapping(); -+ set_fb_mapping(); ++ /* do nothing */ +} + -+static void intel_resize_shared(DisplayState *ds, int w, int h, int depth, int linesize, void *pixels) ++static void intel_resize(DisplayState *ds) +{ -+ DisplaySurface *surf = ds->surface; -+ -+ if (!intel_have_focus) { -+ surf->width = w; -+ surf->height = h; -+ intel_resize(ds); -+ return; ++ INTEL_DEBUG("intel_resize: shared=%d\n", is_buffer_shared(ds->surface)); ++ if (intel_have_focus) { ++ if (!is_buffer_shared(ds->surface) && !is_linear()) ++ intel_force_linear(0); ++ else if (!is_linear() || IntelPitch != ds_get_linesize(lds)) ++ intel_force_linear(ds_get_linesize(lds)); + } -+ if (depth == 32 && w == IntelX && h == IntelY) -+ surf->flags = QEMU_ALLOCATED_FLAG; -+ else -+ surf->flags &= ~QEMU_ALLOCATED_FLAG; -+ if (surf->flags & QEMU_ALLOCATED_FLAG) { -+ surf->width = w; -+ surf->height = h; -+ surf->pf.depth = 32; -+ surf->linesize = linesize; -+ /* adjust linesize */ -+ intel_force_linear(linesize); -+ set_data_mappings(); -+ if (refresh) { -+ memcpy(surf->data, pixels, surf->linesize * surf->height); -+ refresh = 0; ++ if (!is_buffer_shared(ds->surface)) ++ return; ++ if (intel_have_focus) { ++ if (!map_size) { ++ set_fb_mapping(); + } -+ surf->data = pixels; -+ intel_setdata(ds); + } else { -+ surf->width = w; -+ surf->height = h; -+ intel_resize(ds); ++ if (map_size) { ++ unset_fb_mapping(); ++ } + } +} + -+static void intel_resize(DisplayState *ds) ++static void intel_setdata(DisplayState *ds) +{ -+ DisplaySurface *surf = ds->surface; -+ int old_linesize = surf->linesize; -+ -+ if (surf->pf.depth == 32 && surf->width == IntelX && surf->height == IntelY) -+ surf->flags = QEMU_ALLOCATED_FLAG; -+ else -+ surf->flags &= ~QEMU_ALLOCATED_FLAG; -+ -+ if (is_buffer_shared(surf)) -+ { -+ INTEL_DEBUG("intel_resize_shared: enable shared buffer, linesize %d\n", -+ surf->linesize); -+ intel_force_linear(surf->linesize); -+ set_data_mappings(); -+ if (refresh) -+ { -+ // Pixels doesn't exist anymore ?? -+ //memcpy(surf->data, pixels, surf->linesize * surf->height); -+ refresh = 0; -+ } -+ intel_setdata(ds); -+ return; -+ } -+ -+ INTEL_DEBUG("intel_resize: no shared buffer, linesize=%d\n", surf->linesize); -+ surf->linesize = intel_get_pitch(); -+ if (map_size) { -+ unset_fb_mapping(); -+ unset_data_mappings(1); -+ } -+ if (intel_have_focus && !is_linear()) { -+ intel_force_linear(0); -+ } -+ surf->flags &= ~QEMU_ALLOCATED_FLAG; -+ if (intel_have_focus && !old_data && -+ surf->width * surf->height <= IntelX * IntelY) -+ set_data_mappings(); -+ else if (intel_have_focus && old_data && -+ surf->width * surf->height > IntelX * IntelY) -+ unset_data_mappings(0); -+ if (!old_data) { -+ qemu_free(surf->data); -+ surf->data = qemu_mallocz(surf->height * surf->linesize); -+ } else { -+ INTEL_DEBUG("intel_resize: set_data_pointer\n"); -+ set_data_pointer(); -+ } -+ if (intel_have_focus) -+ memset((unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)), 0x0, IntelX * IntelY); -+ if (refresh) { -+ if (old_data) { -+ unsigned char *s, *d; -+ int i; -+ s = old_data; -+ d = surf->data; -+ for (i = 0; i < surf->height; i++) { -+ memcpy(d, s, surf->width * 4); -+ s += old_linesize; -+ d += surf->linesize; -+ } -+ } -+ refresh = 0; -+ } ++ if (!map_size) ++ return; ++ unset_fb_mapping(); ++ set_fb_mapping(); +} + +static void intel_refresh(DisplayState *ds) @@ -431,59 +373,22 @@ index 0000000..4c5f773 + INTEL_DEBUG("Map intel mmio 0x%x\n", intel_mmio_base); + intel_mmio = mmap(NULL, 4 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, + mmio_fd, intel_mmio_base); -+ if (intel_mem == MAP_FAILED) ++ if (intel_mmio == MAP_FAILED) + { + perror("mmap"); + exit(1); + } +} + -+static void set_data_pointer(void) ++static void set_data_pointer(DisplaySurface *surf) +{ -+ DisplaySurface *surf = lds->surface; -+ + surf->data = (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)); ++ memset(surf->data, 0x00, surf->linesize * IntelY); + surf->data = surf->data + + surf->linesize * ((IntelY - surf->height) / 2) + + 4 * ((IntelX - surf->width) / 2); +} + -+static void set_data_mappings(void) -+{ -+ INTEL_DEBUG("set_data_mappings\n"); -+ if (!old_data) -+ old_data = lds->surface->data; -+ set_data_pointer(); -+} -+ -+static void unset_data_mappings(int mapping) -+{ -+ DisplaySurface *surf = lds->surface; -+ if (!old_data) -+ return; -+ if (mapping) { -+ uint8_t * buffer_pointer = surf->data; -+ surf->data = old_data; -+ old_data = NULL; -+ surf->data = realloc(surf->data, surf->linesize * surf->height); -+ memcpy(surf->data, -+ (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)), -+ surf->linesize * surf->height); -+ memcpy(buffer_pointer, -+ surf->data, -+ surf->linesize * surf->height); -+ } else { -+ uint8_t * buffer_pointer = surf->data; -+ surf->data = old_data; -+ old_data = NULL; -+ surf->data = realloc(surf->data, surf->linesize * surf->height); -+ memcpy(surf->data, -+ buffer_pointer, -+ surf->linesize * surf->height); -+ } -+ INTEL_DEBUG("unset_data_mappings %d: success\n", mapping); -+} -+ +static int intel_getfocus(void) +{ + return intel_have_focus; @@ -496,28 +401,13 @@ index 0000000..4c5f773 + + INTEL_DEBUG("intel_focus %d\n", focus); + intel_have_focus = focus; -+ if (focus) { -+ if (!is_linear()) { -+ IntelPitch = intel_get_reg(REG_DR_DSPASTRIDE); -+ IntelX = ((intel_get_reg(REG_DE_PIPEASRC) >> 16) & 0xfff) + 1; -+ IntelY = (intel_get_reg(REG_DE_PIPEASRC) & 0xfff) + 1; -+ INTEL_DEBUG("Resolution is %dx%d\n", IntelX, IntelY); -+ } -+ refresh = 1; -+ lds->listeners->dpy_resize = intel_resize; -+ lds->listeners->dpy_setdata = intel_setdata; -+ vga_hw_invalidate(); -+ } else { -+ if (map_size) { -+ unset_fb_mapping(); -+ unset_data_mappings(1); -+ } else if (old_data) { -+ unset_data_mappings(0); -+ } -+ lds->listeners->dpy_resize = NULL; -+ lds->listeners->dpy_setdata = NULL; -+ lds->surface->flags &= ~QEMU_ALLOCATED_FLAG; ++ if (intel_have_focus) { ++ IntelPitch = intel_get_reg(REG_DR_DSPASTRIDE); ++ IntelX = ((intel_get_reg(REG_DE_PIPEASRC) >> 16) & 0xfff) + 1; ++ IntelY = (intel_get_reg(REG_DE_PIPEASRC) & 0xfff) + 1; + } ++ vga_hw_invalidate(); ++ vga_hw_update(); +} + +int intel_enter(void) @@ -532,29 +422,88 @@ index 0000000..4c5f773 + return 1; +} + -+void intel_display_init(DisplayState *ds) ++static DisplaySurface* intel_create_displaysurface(int width, int height) ++{ ++ DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface)); ++ if (surface == NULL) { ++ fprintf(stderr, "sdl_create_displaysurface: malloc failed\n"); ++ exit(1); ++ } ++ ++ surface->width = width; ++ surface->height = height; ++ ++ INTEL_DEBUG("intel_create_displaysurface: focus=%d %d %d\n", intel_have_focus, width, height); ++ if (intel_have_focus) { ++ surface->pf = qemu_default_pixelformat(32); ++ surface->flags = QEMU_ALLOCATED_FLAG | INTEL_MAPPED_FLAG; ++ surface->linesize = IntelPitch; ++ set_data_pointer(surface); ++ } else { ++ surface->data = qemu_mallocz(width * height * 4); ++ surface->linesize = width * 4; ++ surface->pf = qemu_default_pixelformat(32); ++ surface->flags = QEMU_ALLOCATED_FLAG; ++ } ++ ++ return surface; ++} ++ ++static void intel_free_displaysurface(DisplaySurface *surface) +{ -+ DisplaySurface *surf = ds->surface; ++ if (surface == NULL) ++ return; ++ if ((!(surface->flags & INTEL_MAPPED_FLAG)) && (surface->flags & QEMU_ALLOCATED_FLAG)) ++ qemu_free(surface->data); ++ qemu_free(surface); ++} + -+ INTEL_DEBUG("\n"); ++static DisplaySurface* intel_resize_displaysurface(DisplaySurface *surface, int width, int height) ++{ ++ intel_free_displaysurface(surface); ++ return intel_create_displaysurface(width, height); ++} ++ ++void intel_display_init(DisplayState *ds) ++{ ++ DisplayChangeListener *dcl; ++ DisplayAllocator *da; + + intel_init_mapping(); + + INTEL_DEBUG("Frambuffer is at 0x%x\n", intel_get_reg(REG_DR_DSPASURF)); + -+ surf->flags = 0; -+ surf->width = 640; -+ surf->height = 480; -+ surf->pf.depth = 32; -+ intel_resize(ds); -+ lds = ds; ++ dcl = qemu_mallocz(sizeof(DisplayChangeListener)); ++ if (!dcl) ++ exit(1); ++ dcl->dpy_update = intel_update; ++ dcl->dpy_resize = intel_resize; ++ dcl->dpy_setdata = intel_setdata; ++ dcl->dpy_refresh = intel_refresh; ++ register_displaychangelistener(ds, dcl); ++ ++ da = qemu_mallocz(sizeof(DisplayAllocator)); ++ if (!da) ++ exit(1); ++ da->create_displaysurface = intel_create_displaysurface; ++ da->resize_displaysurface = intel_resize_displaysurface; ++ da->free_displaysurface = intel_free_displaysurface; ++ if (register_displayallocator(ds, da) != da) { ++ fprintf(stderr, "intel_display_init: could not register DisplayAllocator\n"); ++ exit(1); ++ } else { ++ DisplaySurface *surf; ++ surf = intel_create_displaysurface(ds_get_width(ds), ds_get_height(ds)); ++ defaultallocator_free_displaysurface(ds->surface); ++ ds->surface = surf; ++ dpy_resize(ds); ++ } + -+ ds->listeners->dpy_update = intel_update; -+ ds->listeners->dpy_resize = intel_resize; -+ ds->listeners->dpy_refresh = intel_refresh; ++ intel_output = 1; ++ lds = ds; +} diff --git a/vl.c b/vl.c -index 0ffe1ec..d6379a9 100644 +index 18c2a8a..bb83e19 100644 --- a/vl.c +++ b/vl.c @@ -235,6 +235,7 @@ int win2k_install_hack = 0; @@ -570,18 +519,18 @@ index 0ffe1ec..d6379a9 100644 QEMU_OPTION_vga_passthrough, QEMU_OPTION_dom0_input, + QEMU_OPTION_intel, - + /* Debug/Expert options: */ QEMU_OPTION_serial, @@ -4468,6 +4470,7 @@ static const QEMUOption qemu_options[] = { { "vcpus", HAS_ARG, QEMU_OPTION_vcpus }, { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough }, { "dom0-input", 1, QEMU_OPTION_dom0_input }, -+ { "intel", 0, QEMU_OPTION_dom0_input }, ++ { "intel", 0, QEMU_OPTION_intel }, #if defined(CONFIG_XEN) && !defined(CONFIG_DM) { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, { "xen-create", 0, QEMU_OPTION_xen_create }, -@@ -5307,6 +5310,9 @@ int main(int argc, char **argv, char **envp) +@@ -5306,6 +5309,9 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_dom0_input: dom0_input = optarg; break; @@ -591,6 +540,50 @@ index 0ffe1ec..d6379a9 100644 case QEMU_OPTION_direct_pci: direct_pci = optarg; break; +@@ -5908,26 +5914,26 @@ int main(int argc, char **argv, char **envp) + curses_display_init(ds, full_screen); + } else + #endif +- { +- 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); +- } ++ if (intel) ++ intel_display_init(ds); ++ 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); ++ } + #if defined(CONFIG_SDL) +- if (sdl || !vnc_display) +- sdl_display_init(ds, full_screen, no_frame, opengl_enabled); ++ if (sdl || !vnc_display) ++ sdl_display_init(ds, full_screen, no_frame, opengl_enabled); + #elif defined(CONFIG_COCOA) +- if (sdl || !vnc_display) +- cocoa_display_init(ds, full_screen); ++ if (sdl || !vnc_display) ++ cocoa_display_init(ds, full_screen); + #endif +- } + } + dpy_resize(ds); + diff --git a/xen-hooks.mak b/xen-hooks.mak index f243df1..55dd477 100644 --- a/xen-hooks.mak @@ -600,6 +593,6 @@ index f243df1..55dd477 100644 OBJS += dom0_driver.o OBJS += hid-linux.o +OBJS += intel.o - + ifdef CONFIG_STUBDOM CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \