Blob Blame History Raw
diff -ruNp xen-3.1.0-src.orig/tools/xenfb/oldxenfb.c xen-3.1.0-src.new/tools/xenfb/oldxenfb.c
--- xen-3.1.0-src.orig/tools/xenfb/oldxenfb.c	2007-09-25 00:40:35.000000000 -0400
+++ xen-3.1.0-src.new/tools/xenfb/oldxenfb.c	2007-09-25 00:45:47.000000000 -0400
@@ -7,9 +7,9 @@
 #include <xen/io/xenbus.h>
 #include "oldxenfb.h"
 #include "oldxenkbd.h"
+#include <xen/io/protocols.h>
 #include <sys/select.h>
 #include <stdbool.h>
-#include <xen/linux/evtchn.h>
 #include <xen/event_channel.h>
 #include <sys/mman.h>
 #include <errno.h>
@@ -40,6 +40,7 @@ struct xenfb_private {
 	struct xs_handle *xsh;	/* xs daemon handle */
 	struct xenfb_device fb, kbd;
 	size_t fb_len;		/* size of framebuffer */
+	char protocol[64];	/* frontend protocol */
 };
 
 static void xenfb_detach_dom(struct xenfb_private *);
@@ -243,36 +244,71 @@ int xenfb_switch_to_old_protocol(char **
 	abort();
 }
 
+static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
+{
+	uint32_t *src32 = src;
+	uint64_t *src64 = src;
+	int i;
+
+	for (i = 0; i < count; i++)
+		dst[i] = (mode == 32) ? src32[i] : src64[i];
+}
+
 static int xenfb_map_fb(struct xenfb_private *xenfb, int domid)
 {
 	struct xenfb_page *page = xenfb->fb.page;
 	int n_fbmfns;
 	int n_fbdirs;
-	unsigned long *fbmfns;
+	unsigned long *pgmfns = NULL;
+	unsigned long *fbmfns = NULL;
+	void *map;
+	int mode, ret = -1;
+
+	if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_NATIVE))
+	    mode = sizeof(unsigned long) * 8;
+	else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32))
+	    mode = 32;
+	else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64))
+	    mode = 64;
+	else
+	    return -1;
 
 	n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
-	n_fbdirs = n_fbmfns * sizeof(unsigned long);
+	n_fbdirs = n_fbmfns * mode / 8;
 	n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
 
+	pgmfns = malloc(sizeof(unsigned long) * n_fbdirs);
+	fbmfns = malloc(sizeof(unsigned long) * n_fbmfns);
+	if (!pgmfns || !fbmfns)
+		goto out;
+
 	/*
 	 * Bug alert: xc_map_foreign_batch() can fail partly and
 	 * return a non-null value.  This is a design flaw.  When it
 	 * happens, we happily continue here, and later crash on
 	 * access.
 	 */
-	fbmfns = xc_map_foreign_batch(xenfb->xc, domid,
-			PROT_READ, page->pd, n_fbdirs);
-	if (fbmfns == NULL)
-		return -1;
+	xenfb_copy_mfns(mode, n_fbdirs, pgmfns, page->pd);
+	map = xc_map_foreign_batch(xenfb->xc, domid,
+				   PROT_READ, pgmfns, n_fbdirs);
+	if (map == NULL)
+		goto out;
+	xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map);
+	munmap(map, n_fbdirs * XC_PAGE_SIZE);
 
 	xenfb->pub.pixels = xc_map_foreign_batch(xenfb->xc, domid,
 				PROT_READ | PROT_WRITE, fbmfns, n_fbmfns);
-	if (xenfb->pub.pixels == NULL) {
-		munmap(fbmfns, n_fbdirs * XC_PAGE_SIZE);
-		return -1;
-	}
+	if (xenfb->pub.pixels == NULL)
+		goto out;
 
-	return munmap(fbmfns, n_fbdirs * XC_PAGE_SIZE);
+	ret = 0; /* all is fine */
+
+ out:
+	if (pgmfns)
+		free(pgmfns);
+	if (fbmfns)
+		free(fbmfns);
+	return ret;
 }
 
 static int xenfb_bind(struct xenfb_device *dev)
@@ -373,7 +409,7 @@ int xenfb_attach_dom(struct xenfb *xenfb
 {
 	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
 	struct xs_handle *xsh = xenfb->xsh;
-	int val, serrno;
+	int serrno;
 	struct xenfb_page *fb_page;
 	union xenfb_in_event event;
 
@@ -392,6 +428,10 @@ int xenfb_attach_dom(struct xenfb *xenfb
 	if (xenfb_bind(&xenfb->kbd) < 0)
 		goto error;
 
+	if (xenfb_xs_scanf1(xsh, xenfb->fb.otherend, "protocol", "%63s",
+			    xenfb->protocol) < 0)
+		xenfb->protocol[0] = '\0';
+
 	/* TODO check for permitted ranges */
 	fb_page = xenfb->fb.page;
 	xenfb->pub.depth = fb_page->depth;
@@ -430,10 +470,10 @@ static void xenfb_detach_dom(struct xenf
 	}
 }
 
-static void xenfb_on_fb_event(struct xenfb_private *xenfb)
+static void xenfb_on_fb_event32(struct xenfb_private *xenfb)
 {
 	uint32_t prod, cons;
-	struct xenfb_page *page = xenfb->fb.page;
+	struct xenfb_page32 *page = xenfb->fb.page;
 
 	prod = page->out_prod;
 	if (prod == page->out_cons)
@@ -456,6 +496,50 @@ static void xenfb_on_fb_event(struct xen
 	xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
 }
 
+static void xenfb_on_fb_event64(struct xenfb_private *xenfb)
+{
+	uint32_t prod, cons;
+	struct xenfb_page64 *page = xenfb->fb.page;
+
+	prod = page->out_prod;
+	if (prod == page->out_cons)
+		return;
+	rmb();			/* ensure we see ring contents up to prod */
+	for (cons = page->out_cons; cons != prod; cons++) {
+		union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
+
+		switch (event->type) {
+		case XENFB_TYPE_UPDATE:
+                    if (xenfb->pub.update)
+			xenfb->pub.update(&xenfb->pub,
+					  event->update.x, event->update.y,
+					  event->update.width, event->update.height);
+                    break;
+		}
+	}
+	mb();			/* ensure we're done with ring contents */
+	page->out_cons = cons;
+	xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
+}
+
+static void xenfb_on_fb_event(struct xenfb_private *xenfb)
+{
+	int mode;
+	if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_NATIVE))
+	    mode = sizeof(unsigned long) * 8;
+	else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32))
+	    mode = 32;
+	else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64))
+	    mode = 64;
+	else
+	    return;
+
+	if (mode == 32)
+		xenfb_on_fb_event32(xenfb);
+	else
+		xenfb_on_fb_event64(xenfb);
+}
+
 static void xenfb_on_kbd_event(struct xenfb_private *xenfb)
 {
 	struct xenkbd_info *page = xenfb->kbd.page;
@@ -541,11 +625,11 @@ int xenfb_select_fds(struct xenfb *xenfb
 	return fd1 > fd2 ? fd1 + 1 : fd2 + 1;
 }
 
-static int xenfb_fb_event(struct xenfb_private *xenfb,
-			  union xenfb_in_event *event)
+static int xenfb_fb_event32(struct xenfb_private *xenfb,
+			    union xenfb_in_event *event)
 {
 	uint32_t prod;
-	struct xenfb_page *page = xenfb->fb.page;
+	struct xenfb_page32 *page = xenfb->fb.page;
 
 	prod = page->in_prod;
 	if (prod - page->in_cons == XENFB_IN_RING_LEN) {
@@ -560,6 +644,44 @@ static int xenfb_fb_event(struct xenfb_p
 	return xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
 }
 
+static int xenfb_fb_event64(struct xenfb_private *xenfb,
+			    union xenfb_in_event *event)
+{
+	uint32_t prod;
+	struct xenfb_page64 *page = xenfb->fb.page;
+
+	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);
+}
+
+static int xenfb_fb_event(struct xenfb_private *xenfb,
+			   union xenfb_in_event *event)
+{
+	int mode;
+	if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_NATIVE))
+	    mode = sizeof(unsigned long) * 8;
+	else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32))
+	    mode = 32;
+	else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64))
+	    mode = 64;
+	else
+	    return -1;
+
+	if (mode == 32)
+		return xenfb_fb_event32(xenfb, event);
+	else
+		return xenfb_fb_event64(xenfb, event);
+}
+
 static int xenfb_kbd_event(struct xenfb_private *xenfb,
 			   union xenkbd_in_event *event)
 {
diff -ruNp xen-3.1.0-src.orig/tools/xenfb/oldxenfb.h xen-3.1.0-src.new/tools/xenfb/oldxenfb.h
--- xen-3.1.0-src.orig/tools/xenfb/oldxenfb.h	2007-09-25 00:40:35.000000000 -0400
+++ xen-3.1.0-src.new/tools/xenfb/oldxenfb.h	2007-09-25 00:38:30.000000000 -0400
@@ -98,6 +98,32 @@ struct xenfb_page
 
 	unsigned long pd[2];	/* FIXME rename to pgdir? */
 	/* FIXME pd[1] unused at this time, shrink? */
+};
+struct xenfb_page32
+{
+	__u16 width;         /* the width of the framebuffer (in pixels) */
+	__u16 height;        /* the height of the framebuffer (in pixels) */
+	__u32 line_length;   /* the length of a row of pixels (in bytes) */
+	__u32 mem_length;    /* the length of the framebuffer (in bytes) */
+	__u8 depth;          /* the depth of a pixel (in bits) */
+
+        __u32 pd[2];	/* FIXME rename to pgdir? */
+	/* FIXME pd[1] unused at this time, shrink? */
+
+	__u32 in_cons, in_prod;
+	__u32 out_cons, out_prod;
+};
+
+struct xenfb_page64
+{
+	__u16 width;         /* the width of the framebuffer (in pixels) */
+	__u16 height;        /* the height of the framebuffer (in pixels) */
+	__u32 line_length;   /* the length of a row of pixels (in bytes) */
+	__u32 mem_length;    /* the length of the framebuffer (in bytes) */
+	__u8 depth;          /* the depth of a pixel (in bits) */
+
+	__u64 pd[2];	/* FIXME rename to pgdir? */
+	/* FIXME pd[1] unused at this time, shrink? */
 
 	__u32 in_cons, in_prod;
 	__u32 out_cons, out_prod;