[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel][RFC] Dynamic modes support for PV xenfb (included)
Did everyone agree this version is good to go? I'll check it in if Dan and Markus will ack it. -- Keir On 28/1/08 00:48, "Pat Campbell" <plc@xxxxxxxxxx> wrote: > Enough of the implementation has changed so I decided to go through > another RFC cycle. > > What this patch does > Allows PV framebuffer to be resized via xrandr or fbset and to start > up the GUI at higher than 800x600 > > What is new in this iteration: > 1. No longer extending pd[] for extra memory > 2. New kernel xenfb.videomem param > 3. Added new events for extended FB memory mapping > 4. Extending FB memory via gntdev, supports up to 20MB > on 64 bit guest, 40MB for a 32 bit guest. Uses a two > level grant table. > 5. xenkbd exported func to set pointer screen geometry > 6. Removed "wart" from fbif.h > > New kernel xenfb param: > videomem array, FB size in MB, max scanline length > vm config ie: > extra="xenfb.videomem=5,1024 " > > Setup instructions: > 1. Apply xen-fbfront-resize.patch to the Xen 3.2 PV guest kernel source, > make and install > 2. Add modes line to guest xorg.conf and adjust monitor section if > necessary > 3. Add extra kernel param to guest config file and set into xenstore > 4. Apply xen-fbback-resize.patch to xen-unstable tip, make and install > Really only need the new qemu-dm to be installed > > Screen should start out at 800x600 in the console and then switch to > whatever resolution you specified in xorg.conf for the GUI. Switching > to the console will revert screen to 800x600. > > X11 fbdev will use the builtin resolution of 800x600 if alternate modes are > not specified in xorg.conf. > > xorg.conf settings I used: > > Section "Monitor" > HorizSync 30-65 > Identifier "Monitor[0]" > ModelName "XEN PV" > VendorName "XEN" > VertRefresh 43-75 > UseModes "Modes[0]" > EndSection > > Section "Modes" > Identifier "Modes[0]" > Modeline "1024x768" 79.52 1024 1080 1192 1360 768 769 772 801 > Modeline "800x600" 47.53 800 840 920 1040 600 601 604 626 > Modeline "640x480" 29.84 640 664 728 816 480 481 484 501 > EndSection > > Section "Screen" > SubSection "Display" > Depth 24 > Modes "1024x768" "800x600" "640x480" > EndSubSection > Device "Device[0]" > Identifier "Screen[0]" > Monitor "Monitor[0]" > EndSection > > Will appreciate any feedback > > Pat > > diff -r 1c826ea72a80 tools/ioemu/hw/xenfb.c > --- a/tools/ioemu/hw/xenfb.c Wed Jan 23 15:42:52 2008 +0000 > +++ b/tools/ioemu/hw/xenfb.c Thu Jan 24 08:26:55 2008 -0700 > @@ -8,6 +8,7 @@ > #include <xen/io/fbif.h> > #include <xen/io/kbdif.h> > #include <xen/io/protocols.h> > +#include <xen/grant_table.h> > #include <stdbool.h> > #include <xen/event_channel.h> > #include <sys/mman.h> > @@ -45,6 +46,7 @@ struct xenfb { > struct xs_handle *xsh; /* xs daemon handle */ > struct xenfb_device fb, kbd; > void *pixels; /* guest framebuffer data */ > + void *old_pixels; /* guest FB data before remapping to extended */ > size_t fb_len; /* size of framebuffer */ > int row_stride; /* width of one row in framebuffer */ > int depth; /* colour depth of guest framebuffer */ > @@ -52,7 +54,9 @@ struct xenfb { > int height; /* pixel height of guest framebuffer */ > int abs_pointer_wanted; /* Whether guest supports absolute pointer */ > int button_state; /* Last seen pointer button state */ > - char protocol[64]; /* frontend protocol */ > + char protocol[64]; /* frontend protocol */ > + int otherend_bsize; /* frontend bit size */ > + int gnttabdev; > }; > > /* Functions for frontend/backend state machine*/ > @@ -78,6 +82,8 @@ static void xenfb_invalidate(void *opaqu > static void xenfb_invalidate(void *opaque); > static void xenfb_screen_dump(void *opaque, const char *name); > static int xenfb_register_console(struct xenfb *xenfb); > +static void xenfb_map_extended_fb(struct xenfb *xenfb, int, int, int); > +static int xenfb_send_map_extended_done(struct xenfb *xenfb); > > /* > * Tables to map from scancode to Linux input layer keycode. > @@ -261,9 +267,19 @@ struct xenfb *xenfb_new(int domid, Displ > if (!xenfb->xsh) > goto fail; > > + xenfb->gnttabdev = xc_gnttab_open(); > + if (xenfb->gnttabdev == -1) { > + fprintf(stderr, "FB: Can't open gnttab device\n"); > + } > + > xenfb->ds = ds; > xenfb_device_set_domain(&xenfb->fb, domid); > xenfb_device_set_domain(&xenfb->kbd, domid); > + > + /* Indicate we have the frame buffer resize feature, requires grant tables > */ > + if (xenfb->gnttabdev > 0) { > + xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "feature-resize", "1"); > + } > > fprintf(stderr, "FB: Waiting for KBD backend creation\n"); > xenfb_wait_for_backend(&xenfb->kbd, xenfb_backend_created_kbd); > @@ -320,6 +336,58 @@ static void xenfb_copy_mfns(int mode, in > > for (i = 0; i < count; i++) > dst[i] = (mode == 32) ? src32[i] : src64[i]; > +} > + > +static void xenfb_map_extended_fb(struct xenfb *xenfb, int > extended_mem_length, > + int gref_cnt, int gref) > +{ > + int n_fbmfns; > + unsigned long *fbmfns = NULL; > + void *page; > + int i; > + int ep_gref; > + int amt; > + int index; > + void *pixels; > + int *grefs; > + > + grefs = xc_gnttab_map_grant_ref (xenfb->gnttabdev, > + xenfb->fb.otherend_id, > + gref, 0); > + if (NULL == grefs) { > + fprintf(stderr,"FB: Can't map to grant refs\n"); > + return; > + } > + n_fbmfns = (extended_mem_length + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE; > + fbmfns = malloc(sizeof(unsigned long) * n_fbmfns); > + if (fbmfns) { > + ep_gref = PAGE_SIZE/(xenfb->otherend_bsize/8); > + amt = index = 0; > + for(i = 0; i < gref_cnt; i++) { > + page = xc_gnttab_map_grant_ref (xenfb->gnttabdev, > + xenfb->fb.otherend_id, > + grefs[i], 0); > + if (page) { > + index = i * ep_gref; > + amt = ep_gref; > + if (n_fbmfns - index < ep_gref) > + amt = n_fbmfns - index; > + xenfb_copy_mfns(xenfb->otherend_bsize, amt, &fbmfns[index], page); > + xc_gnttab_munmap(xenfb->gnttabdev, page, 1); > + } > + else > + goto gref_error; > + } > + pixels = xc_map_foreign_pages(xenfb->xc, xenfb->fb.otherend_id, > + PROT_READ | PROT_WRITE, fbmfns, n_fbmfns); > + if (pixels) { > + xenfb->old_pixels = xenfb->pixels; > + xenfb->pixels = pixels; > + } > + free(fbmfns); > + } > +gref_error: > + xc_gnttab_munmap(xenfb->gnttabdev, grefs, 1); > } > > static int xenfb_map_fb(struct xenfb *xenfb, int domid) > @@ -377,6 +445,7 @@ static int xenfb_map_fb(struct xenfb *xe > #endif > } > > + xenfb->otherend_bsize = mode; > n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE; > n_fbdirs = n_fbmfns * mode / 8; > n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE; > @@ -456,6 +525,10 @@ static void xenfb_detach_dom(struct xenf > munmap(xenfb->pixels, xenfb->fb_len); > xenfb->pixels = NULL; > } > + if (xenfb->old_pixels) { > + munmap(xenfb->old_pixels, xenfb->fb_len); > + xenfb->old_pixels = NULL; > + } > } > > /* Remove the backend area in xenbus since the framebuffer really is > @@ -473,6 +546,9 @@ void xenfb_shutdown(struct xenfb *xenfb) > xc_evtchn_close(xenfb->evt_xch); > if (xenfb->xsh) > xs_daemon_close(xenfb->xsh); > + if (xenfb->gnttabdev > 0) > + xc_gnttab_close(xenfb->gnttabdev); > + > free(xenfb); > } > > @@ -510,6 +586,21 @@ static void xenfb_on_fb_event(struct xen > } > xenfb_guest_copy(xenfb, x, y, w, h); > break; > + case XENFB_TYPE_RESIZE: > + xenfb->width = event->resize.width; > + xenfb->height = event->resize.height; > + xenfb->row_stride = event->resize.stride; > + dpy_resize(xenfb->ds, xenfb->width, xenfb->height); > + break; > + case XENFB_TYPE_MAP_EXTENDED: > + if (xenfb->gnttabdev > 0) { > + xenfb_map_extended_fb(xenfb, > + event->map_extended.extended_mem_length, > + event->map_extended.gref_cnt, > + event->map_extended.gref); > + } > + xenfb_send_map_extended_done(xenfb); > + break; > } > } > mb(); /* ensure we're done with ring contents */ > @@ -554,6 +645,41 @@ static int xenfb_on_state_change(struct > } > return 0; > } > + > +/* Send an event to the framebuffer frontend driver */ > +static int xenfb_fb_event(struct xenfb *xenfb, > + union xenfb_in_event *event) > +{ > + uint32_t prod; > + struct xenfb_page *page = xenfb->fb.page; > + > + if (xenfb->fb.state != XenbusStateConnected) > + return 0; > + > + prod = page->in_prod; > + if (prod - page->in_cons == XENFB_IN_RING_LEN) { > + errno = EAGAIN; > + return -1; > + } > + > + mb(); /* ensure ring space available */ > + XENFB_IN_RING_REF(page, prod) = *event; > + wmb(); /* ensure ring contents visible */ > + page->in_prod = prod + 1; > + return xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port); > +} > + > +/* Send extended memory map done event to fb driver */ > +static int xenfb_send_map_extended_done(struct xenfb *xenfb) > +{ > + union xenfb_in_event event; > + > + memset(&event, 0, XENFB_IN_EVENT_SIZE); > + event.type = XENFB_TYPE_MAP_EXTENDED_DONE; > + > + return xenfb_fb_event(xenfb, &event); > +} > + > > /* Send an event to the keyboard frontend driver */ > static int xenfb_kbd_event(struct xenfb *xenfb, > diff -r 1c826ea72a80 xen/include/public/io/fbif.h > --- a/xen/include/public/io/fbif.h Wed Jan 23 15:42:52 2008 +0000 > +++ b/xen/include/public/io/fbif.h Thu Jan 24 08:26:55 2008 -0700 > @@ -29,8 +29,9 @@ > /* Out events (frontend -> backend) */ > > /* > - * Out events may be sent only when requested by backend, and receipt > - * of an unknown out event is an error. > + * Out event update is sent only when requested by backend > + * Events resize and map_extended are frontend generated > + * It is an error to send any unknown event types > */ > > /* Event type 1 currently not used */ > @@ -50,12 +51,44 @@ struct xenfb_update > int32_t height; /* rect height */ > }; > > +/* > + * Framebuffer resize notification event > + * Capable backend sets feature-resize in xenstore. > + */ > +#define XENFB_TYPE_RESIZE 3 > + > +struct xenfb_resize > +{ > + uint8_t type; /* XENFB_TYPE_RESIZE */ > + int32_t width; /* width in pixels */ > + int32_t height; /* height in pixels */ > + int32_t stride; /* stride in bytes */ > + int32_t depth; /* future */ > +}; > + > +/* > + * Framebuffer map extended memory event > + * Backend maps extended frame buffer memory > + * for larger screen resolution support > + */ > +#define XENFB_TYPE_MAP_EXTENDED 4 > + > +struct xenfb_map_extended > +{ > + uint8_t type; /* XENFB_TYPE_MAP_EXTENDED */ > + int32_t extended_mem_length; /* extended frame buffer len (in bytes) > */ > + int32_t gref_cnt; /* number of mapping refernces used */ > + int32_t gref; /* reference to mapping references */ > +}; > + > #define XENFB_OUT_EVENT_SIZE 40 > > union xenfb_out_event > { > uint8_t type; > struct xenfb_update update; > + struct xenfb_resize resize; > + struct xenfb_map_extended map_extended; > char pad[XENFB_OUT_EVENT_SIZE]; > }; > > @@ -63,14 +96,26 @@ union xenfb_out_event > > /* > * Frontends should ignore unknown in events. > - * No in events currently defined. > */ > + > +/* > + * Framebuffer map extended memory done event > + * Frontend ends foreign access to extended memory > + * grant table references > + */ > +#define XENFB_TYPE_MAP_EXTENDED_DONE 1 > + > +struct xenfb_map_extended_done > +{ > + uint8_t type; /* XENFB_TYPE_MAP_EXTENDED_DONE */ > +}; > > #define XENFB_IN_EVENT_SIZE 40 > > union xenfb_in_event > { > uint8_t type; > + struct xenfb_map_extended_done map_extended_done; > char pad[XENFB_IN_EVENT_SIZE]; > }; > > @@ -115,16 +160,6 @@ struct xenfb_page > unsigned long pd[2]; > }; > > -/* > - * Wart: xenkbd needs to know resolution. Put it here until a better > - * solution is found, but don't leak it to the backend. > - */ > -#ifdef __KERNEL__ > -#define XENFB_WIDTH 800 > -#define XENFB_HEIGHT 600 > -#define XENFB_DEPTH 32 > -#endif > - > #endif > > /* > diff -r 1c826ea72a80 xen/include/public/io/kbdif.h > --- a/xen/include/public/io/kbdif.h Wed Jan 23 15:42:52 2008 +0000 > +++ b/xen/include/public/io/kbdif.h Thu Jan 24 08:26:55 2008 -0700 > @@ -119,6 +119,10 @@ struct xenkbd_page > uint32_t out_cons, out_prod; > }; > > +#ifdef __KERNEL__ > +void xenkbd_set_ptr_geometry(int xres, int yres); > +#endif > + > #endif > > /* > diff -r 947e0701cf7a drivers/xen/fbfront/xenfb.c > --- a/drivers/xen/fbfront/xenfb.c Tue Jan 22 21:52:44 2008 +0000 > +++ b/drivers/xen/fbfront/xenfb.c Thu Jan 24 08:27:06 2008 -0700 > @@ -27,7 +27,9 @@ > #include <linux/mutex.h> > #include <asm/hypervisor.h> > #include <xen/evtchn.h> > +#include <xen/gnttab.h> > #include <xen/interface/io/fbif.h> > +#include <xen/interface/io/kbdif.h> > #include <xen/interface/io/protocols.h> > #include <xen/xenbus.h> > #include <linux/kthread.h> > @@ -62,6 +64,18 @@ struct xenfb_info > struct xenfb_page *page; > unsigned long *mfns; > int update_wanted; /* XENFB_TYPE_UPDATE wanted */ > + int feature_resize; /* Backend has resize feature */ > + int resize_dpy; > + int xres, yres; /* current resolution */ > + int fb_size; /* fb size in bytes */ > + int fb_width; /* fb mem width in pixels */ > + int fb_stride; /* fb stride in bytes */ > + int extended_mem; /* fb is using extended mem */ > + > + grant_ref_t gref_head; > + uint32_t gref_cnt; /* number of grant refernces used */ > + int * grefs; /* references for mfns */ > + int gref; /* reference to mfn references */ > > struct xenbus_device *xbdev; > }; > @@ -129,20 +143,49 @@ struct xenfb_info > * > * Oh well, we wont be updating the writes to this page anytime soon. > */ > +static int videomem[2] = {0}; > +static int videomem_cnt = 0; > +module_param_array(videomem, int, &videomem_cnt, 0); > +MODULE_PARM_DESC(videomem, > + "Size of video memory in MB and width in pixels, default = (2,800)"); > + > +#define XENFB_WIDTH 800 > +#define XENFB_HEIGHT 600 > +#define XENFB_DEPTH 32 > +#define MB_ (1024*1024) > +#define XENFB_PIXCLOCK 9025 /* Xorg "1280x1024" 110.80 to FB 1000000/110.80 > */ > +#define XENFB_MAX_GREF_CNT 10 /* enough for 32 bit:41MB 64 bit:20MB > extended frame buffer */ > +#define XENFB_MAX_FB_MEM (PAGE_SIZE/sizeof(long) * PAGE_SIZE * > XENFB_MAX_GREF_CNT) > +#define XENFB_DEFAULT_FB_LEN (XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8) > > static int xenfb_fps = 20; > -static unsigned long xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH > / 8; > +static unsigned long xenfb_mem_len = 0; > > static int xenfb_remove(struct xenbus_device *); > static void xenfb_init_shared_page(struct xenfb_info *); > static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info > *); > static void xenfb_disconnect_backend(struct xenfb_info *); > +static void xenfb_refresh(struct xenfb_info *info, int x1, int y1, int w, int > h); > + > +static void xenfb_send_event(struct xenfb_info *info, > + union xenfb_out_event *event) > +{ > + __u32 prod; > + > + prod = info->page->out_prod; > + /* caller ensures !xenfb_queue_full() */ > + mb(); /* ensure ring space available */ > + XENFB_OUT_RING_REF(info->page, prod) = *event; > + wmb(); /* ensure ring contents visible */ > + info->page->out_prod = prod + 1; > + > + notify_remote_via_irq(info->irq); > +} > > static void xenfb_do_update(struct xenfb_info *info, > int x, int y, int w, int h) > { > union xenfb_out_event event; > - __u32 prod; > > event.type = XENFB_TYPE_UPDATE; > event.update.x = x; > @@ -150,14 +193,31 @@ static void xenfb_do_update(struct xenfb > event.update.width = w; > event.update.height = h; > > - prod = info->page->out_prod; > - /* caller ensures !xenfb_queue_full() */ > - mb(); /* ensure ring space available */ > - XENFB_OUT_RING_REF(info->page, prod) = event; > - wmb(); /* ensure ring contents visible */ > - info->page->out_prod = prod + 1; > - > - notify_remote_via_irq(info->irq); > + xenfb_send_event(info, &event); > +} > + > +static void xenfb_do_resize(struct xenfb_info *info) > +{ > + union xenfb_out_event event; > + > + event.type = XENFB_TYPE_RESIZE; > + event.resize.width = info->xres; > + event.resize.height = info->yres; > + event.resize.stride = info->fb_stride; > + > + xenfb_send_event(info, &event); > +} > + > +static void xenfb_do_map_extended(struct xenfb_info *info) > +{ > + union xenfb_out_event event; > + > + event.type = XENFB_TYPE_MAP_EXTENDED; > + event.map_extended.extended_mem_length = info->fb_size; > + event.map_extended.gref_cnt = info->gref_cnt; > + event.map_extended.gref = info->gref; > + > + xenfb_send_event(info, &event); > } > > static int xenfb_queue_full(struct xenfb_info *info) > @@ -209,6 +269,16 @@ static void xenfb_update_screen(struct x > xenfb_do_update(info, x1, y1, x2 - x1, y2 - y1); > } > > +static void xenfb_resize_screen(struct xenfb_info *info) > +{ > + if (xenfb_queue_full(info)) > + return; > + > + info->resize_dpy = 0; > + xenfb_do_resize(info); > + xenfb_refresh(info, 0, 0, info->xres, info->yres); > +} > + > static int xenfb_thread(void *data) > { > struct xenfb_info *info = data; > @@ -217,6 +287,9 @@ static int xenfb_thread(void *data) > if (info->dirty) { > info->dirty = 0; > xenfb_update_screen(info); > + } > + if (info->resize_dpy) { > + xenfb_resize_screen(info); > } > wait_event_interruptible(info->wq, > kthread_should_stop() || info->dirty); > @@ -413,6 +486,47 @@ static int xenfb_mmap(struct fb_info *fb > return 0; > } > > +static int > +xenfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) > +{ > + struct xenfb_info *xenfb_info; > + > + xenfb_info = info->par; > + > + if (!xenfb_info->feature_resize || !xenfb_info->extended_mem) { > + if (var->xres == XENFB_WIDTH && var->yres == XENFB_HEIGHT > + && var->bits_per_pixel == xenfb_info->page->depth) { > + return 0; > + } > + return -EINVAL; > + } > + if (var->bits_per_pixel == xenfb_info->page->depth && > + xenfb_info->fb_width >= var->xres && > + xenfb_mem_len >= (var->xres * var->yres * (xenfb_info->page->depth / 8))) > { > + var->xres_virtual = var->xres; > + var->yres_virtual = var->yres; > + return 0; > + } > + return -EINVAL; > +} > + > +static int xenfb_set_par(struct fb_info *info) > +{ > + struct xenfb_info *xenfb_info; > + > + xenfb_info = info->par; > + > + if (xenfb_info->xres != info->var.xres || > + xenfb_info->yres != info->var.yres) { > + xenfb_info->resize_dpy = 1; > + xenfb_info->xres = info->var.xres_virtual = info->var.xres; > + xenfb_info->yres = info->var.yres_virtual = info->var.yres; > + info->fix.line_length = xenfb_info->fb_stride; > + xenkbd_set_ptr_geometry(xenfb_info->xres, xenfb_info->yres); > + } > + return 0; > +} > + > static struct fb_ops xenfb_fb_ops = { > .owner = THIS_MODULE, > .fb_setcolreg = xenfb_setcolreg, > @@ -420,23 +534,47 @@ static struct fb_ops xenfb_fb_ops = { > .fb_copyarea = xenfb_copyarea, > .fb_imageblit = xenfb_imageblit, > .fb_mmap = xenfb_mmap, > + .fb_check_var = xenfb_check_var, > + .fb_set_par = xenfb_set_par, > }; > > static irqreturn_t xenfb_event_handler(int rq, void *dev_id, > struct pt_regs *regs) > { > - /* > - * No in events recognized, simply ignore them all. > - * If you need to recognize some, see xenbkd's input_handler() > - * for how to do that. > - */ > struct xenfb_info *info = dev_id; > struct xenfb_page *page = info->page; > > - if (page->in_cons != page->in_prod) { > - info->page->in_cons = info->page->in_prod; > - notify_remote_via_irq(info->irq); > - } > + __u32 cons, prod; > + int i; > + > + prod = page->in_prod; > + if (prod == page->out_cons) > + return IRQ_HANDLED; > + rmb(); /* ensure we see ring contents up to prod */ > + for (cons = page->in_cons; cons != prod; cons++) { > + union xenfb_in_event *event; > + event = &XENFB_IN_RING_REF(page, cons); > + > + switch (event->type) { > + case XENFB_TYPE_MAP_EXTENDED_DONE: > + gnttab_end_foreign_access_ref(info->gref); > + gnttab_release_grant_reference( &info->gref_head, info->gref); > + > + for ( i = 0; i < info->gref_cnt; i++) { > + gnttab_end_foreign_access_ref(info->grefs[i]); > + gnttab_release_grant_reference( &info->gref_head, info->grefs[i]); > + } > + /* Map was being done during a resume, need to get the screen > resized */ > + if (info->xres != XENFB_WIDTH || info->yres != XENFB_HEIGHT) > { > + info->resize_dpy = 1; > + } > + break; > + } > + } > + mb(); /* ensure we got ring contents */ > + page->in_cons = cons; > + notify_remote_via_irq(info->irq); > + > return IRQ_HANDLED; > } > > @@ -457,10 +595,24 @@ static int __devinit xenfb_probe(struct > xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure"); > return -ENOMEM; > } > + > + info->fb_size = XENFB_DEFAULT_FB_LEN; > + info->fb_width = XENFB_WIDTH; > + if (videomem_cnt == 2 && (videomem[0] * MB_) >= XENFB_DEFAULT_FB_LEN && > + (videomem[0] * MB_) <= XENFB_MAX_FB_MEM && > + videomem[1] >= XENFB_WIDTH) { > + info->fb_size = videomem[0] * MB_; > + info->fb_width = videomem[1]; > + info->extended_mem = 1; > + } > + xenfb_mem_len = info->fb_size; > + > dev->dev.driver_data = info; > info->xbdev = dev; > info->irq = -1; > info->x1 = info->y1 = INT_MAX; > + info->xres = XENFB_WIDTH; > + info->yres = XENFB_HEIGHT; > spin_lock_init(&info->dirty_lock); > mutex_init(&info->mm_lock); > init_waitqueue_head(&info->wq); > @@ -485,6 +637,11 @@ static int __devinit xenfb_probe(struct > if (!info->mfns) > goto error_nomem; > > + info->grefs = vmalloc(sizeof(int) * (XENFB_MAX_GREF_CNT + 1)); > + if (!info->grefs) > + goto error_nomem; > + memset(info->grefs, 0, sizeof(int) * (XENFB_MAX_GREF_CNT + 1)); > + > /* set up shared page */ > info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); > if (!info->page) > @@ -504,9 +661,10 @@ static int __devinit xenfb_probe(struct > fb_info->screen_base = info->fb; > > fb_info->fbops = &xenfb_fb_ops; > - fb_info->var.xres_virtual = fb_info->var.xres = info->page->width; > - fb_info->var.yres_virtual = fb_info->var.yres = info->page->height; > + fb_info->var.xres_virtual = fb_info->var.xres = info->xres; > + fb_info->var.yres_virtual = fb_info->var.yres = info->yres; > fb_info->var.bits_per_pixel = info->page->depth; > + fb_info->var.pixclock = XENFB_PIXCLOCK; > > fb_info->var.red = (struct fb_bitfield){16, 8, 0}; > fb_info->var.green = (struct fb_bitfield){8, 8, 0}; > @@ -592,6 +750,7 @@ static int xenfb_remove(struct xenbus_de > vfree(info->mfns); > kfree(info->pages); > vfree(info->fb); > + vfree(info->grefs); > kfree(info); > > return 0; > @@ -600,6 +759,7 @@ static void xenfb_init_shared_page(struc > static void xenfb_init_shared_page(struct xenfb_info *info) > { > int i; > + int epd = PAGE_SIZE/sizeof(info->mfns[0]); > > for (i = 0; i < info->nr_pages; i++) > info->pages[i] = vmalloc_to_page(info->fb + i * PAGE_SIZE); > @@ -612,10 +772,32 @@ static void xenfb_init_shared_page(struc > info->page->width = XENFB_WIDTH; > info->page->height = XENFB_HEIGHT; > info->page->depth = XENFB_DEPTH; > - info->page->line_length = (info->page->depth / 8) * info->page->width; > - info->page->mem_length = xenfb_mem_len; > + info->page->line_length = (info->page->depth / 8) * XENFB_WIDTH; > + info->page->mem_length = XENFB_DEFAULT_FB_LEN; > info->page->in_cons = info->page->in_prod = 0; > info->page->out_cons = info->page->out_prod = 0; > + > + if (info->extended_mem) { > + info->fb_stride = (info->page->depth / 8) * info->fb_width; > + if (gnttab_alloc_grant_references(XENFB_MAX_GREF_CNT + 1, &info->gref_head) > == 0) { > + info->gref = gnttab_claim_grant_reference(&info->gref_head); > + gnttab_grant_foreign_access_ref( > + info->gref, > + info->xbdev->otherend_id, > + vmalloc_to_mfn(info->grefs), 0); > + for (i = 0; i * epd < info->nr_pages; i++) { > + info->grefs[i] = gnttab_claim_grant_reference(&info->gref_head); > + gnttab_grant_foreign_access_ref( info->grefs[i], > + info->xbdev->otherend_id, > + vmalloc_to_mfn(&info->mfns[i * epd]), 0); > + } > + info->gref_cnt = i; > + gnttab_free_grant_references(info->gref_head); > + } > + if (!info->gref_cnt) { > + info->extended_mem = 0; > + } > + } > } > > static int xenfb_connect_backend(struct xenbus_device *dev, > @@ -710,6 +892,15 @@ static void xenfb_backend_changed(struct > val = 0; > if (val) > info->update_wanted = 1; > + > + if (xenbus_scanf(XBT_NIL, dev->otherend, > + "feature-resize", "%d", &val) < 0) > + val = 0; > + info->feature_resize = val; > + > + if (info->feature_resize && info->extended_mem) { > + xenfb_do_map_extended(info); > + } > break; > > case XenbusStateClosing: > @@ -744,6 +935,8 @@ static int __init xenfb_init(void) > if (is_initial_xendomain()) > return -ENODEV; > > + xenkbd_set_ptr_geometry(XENFB_WIDTH, XENFB_HEIGHT); > + > return xenbus_register_frontend(&xenfb); > } > > diff -r 947e0701cf7a drivers/xen/fbfront/xenkbd.c > --- a/drivers/xen/fbfront/xenkbd.c Tue Jan 22 21:52:44 2008 +0000 > +++ b/drivers/xen/fbfront/xenkbd.c Thu Jan 24 08:27:06 2008 -0700 > @@ -40,6 +40,10 @@ static int xenkbd_remove(struct xenbus_d > static int xenkbd_remove(struct xenbus_device *); > static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info > *); > static void xenkbd_disconnect_backend(struct xenkbd_info *); > + > +static int max_abs_xres; > +static int max_abs_yres; > +static struct input_dev *mouse_ptr; > > /* > * Note: if you need to send out events, see xenfb_do_update() for how > @@ -163,8 +167,8 @@ int __devinit xenkbd_probe(struct xenbus > for (i = BTN_LEFT; i <= BTN_TASK; i++) > set_bit(i, ptr->keybit); > ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); > - input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); > - input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); > + input_set_abs_params(ptr, ABS_X, 0, max_abs_xres, 0, 0); > + input_set_abs_params(ptr, ABS_Y, 0, max_abs_yres, 0, 0); > > ret = input_register_device(ptr); > if (ret) { > @@ -172,7 +176,7 @@ int __devinit xenkbd_probe(struct xenbus > xenbus_dev_fatal(dev, ret, "input_register_device(ptr)"); > goto error; > } > - info->ptr = ptr; > + mouse_ptr = info->ptr = ptr; > > ret = xenkbd_connect_backend(dev, info); > if (ret < 0) > @@ -338,6 +342,18 @@ static void __exit xenkbd_cleanup(void) > return xenbus_unregister_driver(&xenkbd); > } > > +void xenkbd_set_ptr_geometry(int xres, int yres) > +{ > + max_abs_xres = xres; > + max_abs_yres = yres; > + if (mouse_ptr) { > + input_set_abs_params(mouse_ptr, ABS_X, 0, max_abs_xres, 0, 0); > + input_set_abs_params(mouse_ptr, ABS_Y, 0, max_abs_yres, 0, 0); > + input_event(mouse_ptr, EV_SYN, SYN_CONFIG, 0); > + } > +} > +EXPORT_SYMBOL(xenkbd_set_ptr_geometry); > + > module_init(xenkbd_init); > module_exit(xenkbd_cleanup); > > diff -r 947e0701cf7a include/xen/interface/io/fbif.h > --- a/include/xen/interface/io/fbif.h Tue Jan 22 21:52:44 2008 +0000 > +++ b/include/xen/interface/io/fbif.h Thu Jan 24 08:27:06 2008 -0700 > @@ -29,8 +29,9 @@ > /* Out events (frontend -> backend) */ > > /* > - * Out events may be sent only when requested by backend, and receipt > - * of an unknown out event is an error. > + * Out event update is sent only when requested by backend > + * Events resize and map_extended are frontend generated > + * It is an error to send any unknown event types > */ > > /* Event type 1 currently not used */ > @@ -50,12 +51,44 @@ struct xenfb_update > int32_t height; /* rect height */ > }; > > +/* > + * Framebuffer resize notification event > + * Capable backend sets feature-resize in xenstore. > + */ > +#define XENFB_TYPE_RESIZE 3 > + > +struct xenfb_resize > +{ > + uint8_t type; /* XENFB_TYPE_RESIZE */ > + int32_t width; /* width in pixels */ > + int32_t height; /* height in pixels */ > + int32_t stride; /* stride in bytes */ > + int32_t depth; /* future */ > +}; > + > +/* > + * Framebuffer map extended memory event > + * Backend maps extended frame buffer memory > + * for larger screen resolution support > + */ > +#define XENFB_TYPE_MAP_EXTENDED 4 > + > +struct xenfb_map_extended > +{ > + uint8_t type; /* XENFB_TYPE_MAP_EXTENDED */ > + int32_t extended_mem_length; /* extended frame buffer len (in bytes) > */ > + int32_t gref_cnt; /* number of mapping refernces used */ > + int32_t gref; /* reference to mapping references */ > +}; > + > #define XENFB_OUT_EVENT_SIZE 40 > > union xenfb_out_event > { > uint8_t type; > struct xenfb_update update; > + struct xenfb_resize resize; > + struct xenfb_map_extended map_extended; > char pad[XENFB_OUT_EVENT_SIZE]; > }; > > @@ -63,14 +96,26 @@ union xenfb_out_event > > /* > * Frontends should ignore unknown in events. > - * No in events currently defined. > */ > + > +/* > + * Framebuffer map extended memory done event > + * Frontend ends foreign access to extended memory > + * grant table references > + */ > +#define XENFB_TYPE_MAP_EXTENDED_DONE 1 > + > +struct xenfb_map_extended_done > +{ > + uint8_t type; /* XENFB_TYPE_MAP_EXTENDED_DONE */ > +}; > > #define XENFB_IN_EVENT_SIZE 40 > > union xenfb_in_event > { > uint8_t type; > + struct xenfb_map_extended_done map_extended_done; > char pad[XENFB_IN_EVENT_SIZE]; > }; > > @@ -115,16 +160,6 @@ struct xenfb_page > unsigned long pd[2]; > }; > > -/* > - * Wart: xenkbd needs to know resolution. Put it here until a better > - * solution is found, but don't leak it to the backend. > - */ > -#ifdef __KERNEL__ > -#define XENFB_WIDTH 800 > -#define XENFB_HEIGHT 600 > -#define XENFB_DEPTH 32 > -#endif > - > #endif > > /* > diff -r 947e0701cf7a include/xen/interface/io/kbdif.h > --- a/include/xen/interface/io/kbdif.h Tue Jan 22 21:52:44 2008 +0000 > +++ b/include/xen/interface/io/kbdif.h Thu Jan 24 08:27:06 2008 -0700 > @@ -119,6 +119,10 @@ struct xenkbd_page > uint32_t out_cons, out_prod; > }; > > +#ifdef __KERNEL__ > +void xenkbd_set_ptr_geometry(int xres, int yres); > +#endif > + > #endif > > /* > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxxxxxxxx > http://lists.xensource.com/xen-devel _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |