2008-01-12 02:32:53 +01:00
|
|
|
diff -r 15cfd1f8fa38 tools/ioemu/hw/xenfb.c
|
|
|
|
--- a/tools/ioemu/hw/xenfb.c Tue Jan 08 16:45:08 2008 +0000
|
2008-02-02 01:58:27 +01:00
|
|
|
+++ b/tools/ioemu/hw/xenfb.c Thu Jan 17 12:16:49 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,9 @@ static void xenfb_invalidate(void *opaqu
|
2008-01-12 02:32:53 +01:00
|
|
|
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 int xenfb_send_resize(struct xenfb *xenfb, int width, int height);
|
2008-02-02 01:58:27 +01:00
|
|
|
+static void xenfb_map_extended_fb(struct xenfb *xenfb, int, int, int);
|
|
|
|
+static int xenfb_send_map_extended_done(struct xenfb *xenfb);
|
2008-01-12 02:32:53 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Tables to map from scancode to Linux input layer keycode.
|
2008-02-02 01:58:27 +01:00
|
|
|
@@ -261,9 +268,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");
|
|
|
|
+ }
|
|
|
|
+
|
2008-01-12 02:32:53 +01:00
|
|
|
xenfb->ds = ds;
|
|
|
|
xenfb_device_set_domain(&xenfb->fb, domid);
|
|
|
|
xenfb_device_set_domain(&xenfb->kbd, domid);
|
|
|
|
+
|
2008-02-02 01:58:27 +01:00
|
|
|
+ /* 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");
|
|
|
|
+ }
|
2008-01-12 02:32:53 +01:00
|
|
|
|
|
|
|
fprintf(stderr, "FB: Waiting for KBD backend creation\n");
|
|
|
|
xenfb_wait_for_backend(&xenfb->kbd, xenfb_backend_created_kbd);
|
2008-02-02 01:58:27 +01:00
|
|
|
@@ -320,6 +337,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 +446,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 +526,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 +547,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 +587,22 @@ static void xenfb_on_fb_event(struct xen
|
2008-01-12 02:32:53 +01:00
|
|
|
}
|
|
|
|
xenfb_guest_copy(xenfb, x, y, w, h);
|
|
|
|
break;
|
|
|
|
+ case XENFB_TYPE_RESIZE:
|
|
|
|
+ xenfb->width = event->resize.width;
|
|
|
|
+ xenfb->height = event->resize.height;
|
2008-02-02 01:58:27 +01:00
|
|
|
+ xenfb->row_stride = event->resize.stride;
|
2008-01-12 02:32:53 +01:00
|
|
|
+ dpy_resize(xenfb->ds, xenfb->width, xenfb->height);
|
|
|
|
+ xenfb_send_resize(xenfb, xenfb->width, xenfb->height);
|
2008-02-02 01:58:27 +01:00
|
|
|
+ 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);
|
2008-01-12 02:32:53 +01:00
|
|
|
+ break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mb(); /* ensure we're done with ring contents */
|
2008-02-02 01:58:27 +01:00
|
|
|
@@ -555,6 +648,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 a extended memory map done event to kbd 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,
|
|
|
|
union xenkbd_in_event *event)
|
|
|
|
@@ -601,6 +729,19 @@ static int xenfb_send_motion(struct xenf
|
2008-01-12 02:32:53 +01:00
|
|
|
event.motion.rel_x = rel_x;
|
|
|
|
event.motion.rel_y = rel_y;
|
|
|
|
event.motion.rel_z = rel_z;
|
|
|
|
+
|
|
|
|
+ return xenfb_kbd_event(xenfb, &event);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Send a resize event to kbd driver */
|
|
|
|
+static int xenfb_send_resize(struct xenfb *xenfb, int width, int height)
|
|
|
|
+{
|
|
|
|
+ union xenkbd_in_event event;
|
|
|
|
+
|
|
|
|
+ memset(&event, 0, XENKBD_IN_EVENT_SIZE);
|
2008-02-02 01:58:27 +01:00
|
|
|
+ event.type = XENKBD_TYPE_FBRESIZE;
|
|
|
|
+ event.fbresize.width = width;
|
|
|
|
+ event.fbresize.height = height;
|
2008-01-12 02:32:53 +01:00
|
|
|
|
|
|
|
return xenfb_kbd_event(xenfb, &event);
|
|
|
|
}
|
|
|
|
diff -r 15cfd1f8fa38 xen/include/public/io/fbif.h
|
|
|
|
--- a/xen/include/public/io/fbif.h Tue Jan 08 16:45:08 2008 +0000
|
2008-02-02 01:58:27 +01:00
|
|
|
+++ b/xen/include/public/io/fbif.h Thu Jan 17 08:16:28 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
|
2008-01-12 02:32:53 +01:00
|
|
|
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 */
|
2008-02-02 01:58:27 +01:00
|
|
|
+ int32_t width; /* width in pixels */
|
|
|
|
+ int32_t height; /* height in pixels */
|
|
|
|
+ int32_t stride; /* stride in pixels */
|
|
|
|
+ int32_t depth; /* future */
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Framebuffer map extended memory event
|
|
|
|
+ * Causes backend to map 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 */
|
2008-01-12 02:32:53 +01:00
|
|
|
+};
|
|
|
|
+
|
|
|
|
#define XENFB_OUT_EVENT_SIZE 40
|
|
|
|
|
|
|
|
union xenfb_out_event
|
|
|
|
{
|
|
|
|
uint8_t type;
|
|
|
|
struct xenfb_update update;
|
|
|
|
+ struct xenfb_resize resize;
|
2008-02-02 01:58:27 +01:00
|
|
|
+ struct xenfb_map_extended map_extended;
|
2008-01-12 02:32:53 +01:00
|
|
|
char pad[XENFB_OUT_EVENT_SIZE];
|
|
|
|
};
|
|
|
|
|
2008-02-02 01:58:27 +01:00
|
|
|
@@ -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
|
|
|
|
+ * Causes fronted to end 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];
|
|
|
|
};
|
|
|
|
|
|
|
|
@@ -116,8 +161,9 @@ struct xenfb_page
|
2008-01-12 02:32:53 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
- * Wart: xenkbd needs to know resolution. Put it here until a better
|
|
|
|
- * solution is found, but don't leak it to the backend.
|
|
|
|
+ * Wart: xenkbd needs to know resolution of initial frame buffer. Put
|
|
|
|
+ * it here until a better solution is found, but don't leak it to
|
|
|
|
+ * the backend.
|
|
|
|
*/
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#define XENFB_WIDTH 800
|
|
|
|
diff -r 15cfd1f8fa38 xen/include/public/io/kbdif.h
|
|
|
|
--- a/xen/include/public/io/kbdif.h Tue Jan 08 16:45:08 2008 +0000
|
2008-02-02 01:58:27 +01:00
|
|
|
+++ b/xen/include/public/io/kbdif.h Thu Jan 17 10:43:35 2008 -0700
|
|
|
|
@@ -44,6 +44,12 @@
|
2008-01-12 02:32:53 +01:00
|
|
|
* request-abs-update in xenstore.
|
|
|
|
*/
|
|
|
|
#define XENKBD_TYPE_POS 4
|
|
|
|
+/*
|
2008-02-02 01:58:27 +01:00
|
|
|
+ * Frame buffer resize event. Adjusts absolute max X and Y axis
|
|
|
|
+ * values in input ptr device. Necessary for proper scaling
|
|
|
|
+ * when the screen resolution changes
|
2008-01-12 02:32:53 +01:00
|
|
|
+ */
|
2008-02-02 01:58:27 +01:00
|
|
|
+#define XENKBD_TYPE_FBRESIZE 5
|
2008-01-12 02:32:53 +01:00
|
|
|
|
|
|
|
struct xenkbd_motion
|
|
|
|
{
|
2008-02-02 01:58:27 +01:00
|
|
|
@@ -68,6 +74,12 @@ struct xenkbd_position
|
2008-01-12 02:32:53 +01:00
|
|
|
int32_t abs_z; /* absolute Z position (wheel) */
|
|
|
|
};
|
|
|
|
|
2008-02-02 01:58:27 +01:00
|
|
|
+struct xenkbd_fbresize
|
2008-01-12 02:32:53 +01:00
|
|
|
+{
|
2008-02-02 01:58:27 +01:00
|
|
|
+ uint8_t type; /* XENKBD_TYPE_FBRESIZE */
|
2008-01-12 02:32:53 +01:00
|
|
|
+ int32_t width; /* frame buffer width in pixels */
|
|
|
|
+ int32_t height; /* frame buffer height in pixels */
|
|
|
|
+};
|
|
|
|
#define XENKBD_IN_EVENT_SIZE 40
|
|
|
|
|
|
|
|
union xenkbd_in_event
|
2008-02-02 01:58:27 +01:00
|
|
|
@@ -76,6 +88,7 @@ union xenkbd_in_event
|
2008-01-12 02:32:53 +01:00
|
|
|
struct xenkbd_motion motion;
|
|
|
|
struct xenkbd_key key;
|
|
|
|
struct xenkbd_position pos;
|
2008-02-02 01:58:27 +01:00
|
|
|
+ struct xenkbd_fbresize fbresize;
|
2008-01-12 02:32:53 +01:00
|
|
|
char pad[XENKBD_IN_EVENT_SIZE];
|
|
|
|
};
|
|
|
|
|