xref: /qemu/hw/display/xenfb.c (revision 6a7b47a7)
1 /*
2  *  xen paravirt framebuffer backend
3  *
4  *  Copyright IBM, Corp. 2005-2006
5  *  Copyright Red Hat, Inc. 2006-2008
6  *
7  *  Authors:
8  *       Anthony Liguori <aliguori@us.ibm.com>,
9  *       Markus Armbruster <armbru@redhat.com>,
10  *       Daniel P. Berrange <berrange@redhat.com>,
11  *       Pat Campbell <plc@novell.com>,
12  *       Gerd Hoffmann <kraxel@redhat.com>
13  *
14  *  This program is free software; you can redistribute it and/or modify
15  *  it under the terms of the GNU General Public License as published by
16  *  the Free Software Foundation; under version 2 of the License.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License along
24  *  with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26 
27 #include "qemu/osdep.h"
28 
29 #include "hw/hw.h"
30 #include "ui/console.h"
31 #include "sysemu/char.h"
32 #include "hw/xen/xen_backend.h"
33 
34 #include <xen/event_channel.h>
35 #include <xen/io/fbif.h>
36 #include <xen/io/kbdif.h>
37 #include <xen/io/protocols.h>
38 
39 #include "trace.h"
40 
41 #ifndef BTN_LEFT
42 #define BTN_LEFT 0x110 /* from <linux/input.h> */
43 #endif
44 
45 /* -------------------------------------------------------------------- */
46 
47 struct common {
48     struct XenDevice  xendev;  /* must be first */
49     void              *page;
50     QemuConsole       *con;
51 };
52 
53 struct XenInput {
54     struct common c;
55     int abs_pointer_wanted; /* Whether guest supports absolute pointer */
56     int button_state;       /* Last seen pointer button state */
57     int extended;
58     QEMUPutMouseEntry *qmouse;
59 };
60 
61 #define UP_QUEUE 8
62 
63 struct XenFB {
64     struct common     c;
65     size_t            fb_len;
66     int               row_stride;
67     int               depth;
68     int               width;
69     int               height;
70     int               offset;
71     void              *pixels;
72     int               fbpages;
73     int               feature_update;
74     int               bug_trigger;
75     int               have_console;
76     int               do_resize;
77 
78     struct {
79 	int x,y,w,h;
80     } up_rects[UP_QUEUE];
81     int               up_count;
82     int               up_fullscreen;
83 };
84 
85 /* -------------------------------------------------------------------- */
86 
87 static int common_bind(struct common *c)
88 {
89     uint64_t val;
90     xen_pfn_t mfn;
91 
92     if (xenstore_read_fe_uint64(&c->xendev, "page-ref", &val) == -1)
93 	return -1;
94     mfn = (xen_pfn_t)val;
95     assert(val == mfn);
96 
97     if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1)
98 	return -1;
99 
100     c->page = xenforeignmemory_map(xen_fmem, c->xendev.dom,
101                                    PROT_READ | PROT_WRITE, 1, &mfn, NULL);
102     if (c->page == NULL)
103 	return -1;
104 
105     xen_be_bind_evtchn(&c->xendev);
106     xen_be_printf(&c->xendev, 1, "ring mfn %"PRI_xen_pfn", remote-port %d, local-port %d\n",
107 		  mfn, c->xendev.remote_port, c->xendev.local_port);
108 
109     return 0;
110 }
111 
112 static void common_unbind(struct common *c)
113 {
114     xen_be_unbind_evtchn(&c->xendev);
115     if (c->page) {
116         xenforeignmemory_unmap(xen_fmem, c->page, 1);
117 	c->page = NULL;
118     }
119 }
120 
121 /* -------------------------------------------------------------------- */
122 
123 #if 0
124 /*
125  * These two tables are not needed any more, but left in here
126  * intentionally as documentation, to show how scancode2linux[]
127  * was generated.
128  *
129  * Tables to map from scancode to Linux input layer keycode.
130  * Scancodes are hardware-specific.  These maps assumes a
131  * standard AT or PS/2 keyboard which is what QEMU feeds us.
132  */
133 const unsigned char atkbd_set2_keycode[512] = {
134 
135      0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
136      0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
137      0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
138      0, 49, 48, 35, 34, 21,  7,184,  0,  0, 50, 36, 22,  8,  9,185,
139      0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
140      0, 89, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0, 85,
141      0, 86, 91, 90, 92,  0, 14, 94,  0, 79,124, 75, 71,121,  0,  0,
142     82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
143 
144       0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
145     217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
146     173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
147     159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
148     157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
149     226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
150       0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
151     110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
152 
153 };
154 
155 const unsigned char atkbd_unxlate_table[128] = {
156 
157       0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
158      21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
159      35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
160      50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
161      11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
162     114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
163      71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
164      19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
165 
166 };
167 #endif
168 
169 /*
170  * for (i = 0; i < 128; i++) {
171  *     scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
172  *     scancode2linux[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
173  * }
174  */
175 static const unsigned char scancode2linux[512] = {
176       0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
177      16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
178      32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
179      48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
180      64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
181      80, 81, 82, 83, 99,  0, 86, 87, 88,117,  0,  0, 95,183,184,185,
182       0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
183      93,  0,  0, 89,  0,  0, 85, 91, 90, 92,  0, 94,  0,124,121,  0,
184 
185       0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
186     165,  0,  0,  0,  0,  0,  0,  0,  0,163,  0,  0, 96, 97,  0,  0,
187     113,140,164,  0,166,  0,  0,  0,  0,  0,255,  0,  0,  0,114,  0,
188     115,  0,150,  0,  0, 98,255, 99,100,  0,  0,  0,  0,  0,  0,  0,
189       0,  0,  0,  0,  0,119,119,102,103,104,  0,105,112,106,118,107,
190     108,109,110,111,  0,  0,  0,  0,  0,  0,  0,125,126,127,116,142,
191       0,  0,  0,143,  0,217,156,173,128,159,158,157,155,226,  0,112,
192       0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
193 };
194 
195 /* Send an event to the keyboard frontend driver */
196 static int xenfb_kbd_event(struct XenInput *xenfb,
197 			   union xenkbd_in_event *event)
198 {
199     struct xenkbd_page *page = xenfb->c.page;
200     uint32_t prod;
201 
202     if (xenfb->c.xendev.be_state != XenbusStateConnected)
203 	return 0;
204     if (!page)
205         return 0;
206 
207     prod = page->in_prod;
208     if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
209 	errno = EAGAIN;
210 	return -1;
211     }
212 
213     xen_mb();		/* ensure ring space available */
214     XENKBD_IN_RING_REF(page, prod) = *event;
215     xen_wmb();		/* ensure ring contents visible */
216     page->in_prod = prod + 1;
217     return xen_be_send_notify(&xenfb->c.xendev);
218 }
219 
220 /* Send a keyboard (or mouse button) event */
221 static int xenfb_send_key(struct XenInput *xenfb, bool down, int keycode)
222 {
223     union xenkbd_in_event event;
224 
225     memset(&event, 0, XENKBD_IN_EVENT_SIZE);
226     event.type = XENKBD_TYPE_KEY;
227     event.key.pressed = down ? 1 : 0;
228     event.key.keycode = keycode;
229 
230     return xenfb_kbd_event(xenfb, &event);
231 }
232 
233 /* Send a relative mouse movement event */
234 static int xenfb_send_motion(struct XenInput *xenfb,
235 			     int rel_x, int rel_y, int rel_z)
236 {
237     union xenkbd_in_event event;
238 
239     memset(&event, 0, XENKBD_IN_EVENT_SIZE);
240     event.type = XENKBD_TYPE_MOTION;
241     event.motion.rel_x = rel_x;
242     event.motion.rel_y = rel_y;
243     event.motion.rel_z = rel_z;
244 
245     return xenfb_kbd_event(xenfb, &event);
246 }
247 
248 /* Send an absolute mouse movement event */
249 static int xenfb_send_position(struct XenInput *xenfb,
250 			       int abs_x, int abs_y, int z)
251 {
252     union xenkbd_in_event event;
253 
254     memset(&event, 0, XENKBD_IN_EVENT_SIZE);
255     event.type = XENKBD_TYPE_POS;
256     event.pos.abs_x = abs_x;
257     event.pos.abs_y = abs_y;
258     event.pos.rel_z = z;
259 
260     return xenfb_kbd_event(xenfb, &event);
261 }
262 
263 /*
264  * Send a key event from the client to the guest OS
265  * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
266  * We have to turn this into a Linux Input layer keycode.
267  *
268  * Extra complexity from the fact that with extended scancodes
269  * (like those produced by arrow keys) this method gets called
270  * twice, but we only want to send a single event. So we have to
271  * track the '0xe0' scancode state & collapse the extended keys
272  * as needed.
273  *
274  * Wish we could just send scancodes straight to the guest which
275  * already has code for dealing with this...
276  */
277 static void xenfb_key_event(void *opaque, int scancode)
278 {
279     struct XenInput *xenfb = opaque;
280     int down = 1;
281 
282     if (scancode == 0xe0) {
283 	xenfb->extended = 1;
284 	return;
285     } else if (scancode & 0x80) {
286 	scancode &= 0x7f;
287 	down = 0;
288     }
289     if (xenfb->extended) {
290 	scancode |= 0x80;
291 	xenfb->extended = 0;
292     }
293     xenfb_send_key(xenfb, down, scancode2linux[scancode]);
294 }
295 
296 /*
297  * Send a mouse event from the client to the guest OS
298  *
299  * The QEMU mouse can be in either relative, or absolute mode.
300  * Movement is sent separately from button state, which has to
301  * be encoded as virtual key events. We also don't actually get
302  * given any button up/down events, so have to track changes in
303  * the button state.
304  */
305 static void xenfb_mouse_event(void *opaque,
306 			      int dx, int dy, int dz, int button_state)
307 {
308     struct XenInput *xenfb = opaque;
309     DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
310     int dw = surface_width(surface);
311     int dh = surface_height(surface);
312     int i;
313 
314     trace_xenfb_mouse_event(opaque, dx, dy, dz, button_state,
315                             xenfb->abs_pointer_wanted);
316     if (xenfb->abs_pointer_wanted)
317 	xenfb_send_position(xenfb,
318 			    dx * (dw - 1) / 0x7fff,
319 			    dy * (dh - 1) / 0x7fff,
320 			    dz);
321     else
322 	xenfb_send_motion(xenfb, dx, dy, dz);
323 
324     for (i = 0 ; i < 8 ; i++) {
325 	int lastDown = xenfb->button_state & (1 << i);
326 	int down = button_state & (1 << i);
327 	if (down == lastDown)
328 	    continue;
329 
330 	if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
331 	    return;
332     }
333     xenfb->button_state = button_state;
334 }
335 
336 static int input_init(struct XenDevice *xendev)
337 {
338     xenstore_write_be_int(xendev, "feature-abs-pointer", 1);
339     return 0;
340 }
341 
342 static int input_initialise(struct XenDevice *xendev)
343 {
344     struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
345     int rc;
346 
347     if (!in->c.con) {
348         xen_be_printf(xendev, 1, "ds not set (yet)\n");
349         return -1;
350     }
351 
352     rc = common_bind(&in->c);
353     if (rc != 0)
354 	return rc;
355 
356     qemu_add_kbd_event_handler(xenfb_key_event, in);
357     return 0;
358 }
359 
360 static void input_connected(struct XenDevice *xendev)
361 {
362     struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
363 
364     if (xenstore_read_fe_int(xendev, "request-abs-pointer",
365                              &in->abs_pointer_wanted) == -1) {
366         in->abs_pointer_wanted = 0;
367     }
368 
369     if (in->qmouse) {
370         qemu_remove_mouse_event_handler(in->qmouse);
371     }
372     trace_xenfb_input_connected(xendev, in->abs_pointer_wanted);
373     in->qmouse = qemu_add_mouse_event_handler(xenfb_mouse_event, in,
374 					      in->abs_pointer_wanted,
375 					      "Xen PVFB Mouse");
376 }
377 
378 static void input_disconnect(struct XenDevice *xendev)
379 {
380     struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
381 
382     if (in->qmouse) {
383 	qemu_remove_mouse_event_handler(in->qmouse);
384 	in->qmouse = NULL;
385     }
386     qemu_add_kbd_event_handler(NULL, NULL);
387     common_unbind(&in->c);
388 }
389 
390 static void input_event(struct XenDevice *xendev)
391 {
392     struct XenInput *xenfb = container_of(xendev, struct XenInput, c.xendev);
393     struct xenkbd_page *page = xenfb->c.page;
394 
395     /* We don't understand any keyboard events, so just ignore them. */
396     if (page->out_prod == page->out_cons)
397 	return;
398     page->out_cons = page->out_prod;
399     xen_be_send_notify(&xenfb->c.xendev);
400 }
401 
402 /* -------------------------------------------------------------------- */
403 
404 static void xenfb_copy_mfns(int mode, int count, xen_pfn_t *dst, void *src)
405 {
406     uint32_t *src32 = src;
407     uint64_t *src64 = src;
408     int i;
409 
410     for (i = 0; i < count; i++)
411 	dst[i] = (mode == 32) ? src32[i] : src64[i];
412 }
413 
414 static int xenfb_map_fb(struct XenFB *xenfb)
415 {
416     struct xenfb_page *page = xenfb->c.page;
417     char *protocol = xenfb->c.xendev.protocol;
418     int n_fbdirs;
419     xen_pfn_t *pgmfns = NULL;
420     xen_pfn_t *fbmfns = NULL;
421     void *map, *pd;
422     int mode, ret = -1;
423 
424     /* default to native */
425     pd = page->pd;
426     mode = sizeof(unsigned long) * 8;
427 
428     if (!protocol) {
429 	/*
430 	 * Undefined protocol, some guesswork needed.
431 	 *
432 	 * Old frontends which don't set the protocol use
433 	 * one page directory only, thus pd[1] must be zero.
434 	 * pd[1] of the 32bit struct layout and the lower
435 	 * 32 bits of pd[0] of the 64bit struct layout have
436 	 * the same location, so we can check that ...
437 	 */
438 	uint32_t *ptr32 = NULL;
439 	uint32_t *ptr64 = NULL;
440 #if defined(__i386__)
441 	ptr32 = (void*)page->pd;
442 	ptr64 = ((void*)page->pd) + 4;
443 #elif defined(__x86_64__)
444 	ptr32 = ((void*)page->pd) - 4;
445 	ptr64 = (void*)page->pd;
446 #endif
447 	if (ptr32) {
448 	    if (ptr32[1] == 0) {
449 		mode = 32;
450 		pd   = ptr32;
451 	    } else {
452 		mode = 64;
453 		pd   = ptr64;
454 	    }
455 	}
456 #if defined(__x86_64__)
457     } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) {
458 	/* 64bit dom0, 32bit domU */
459 	mode = 32;
460 	pd   = ((void*)page->pd) - 4;
461 #elif defined(__i386__)
462     } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_64) == 0) {
463 	/* 32bit dom0, 64bit domU */
464 	mode = 64;
465 	pd   = ((void*)page->pd) + 4;
466 #endif
467     }
468 
469     if (xenfb->pixels) {
470         munmap(xenfb->pixels, xenfb->fbpages * XC_PAGE_SIZE);
471         xenfb->pixels = NULL;
472     }
473 
474     xenfb->fbpages = DIV_ROUND_UP(xenfb->fb_len, XC_PAGE_SIZE);
475     n_fbdirs = xenfb->fbpages * mode / 8;
476     n_fbdirs = DIV_ROUND_UP(n_fbdirs, XC_PAGE_SIZE);
477 
478     pgmfns = g_malloc0(sizeof(xen_pfn_t) * n_fbdirs);
479     fbmfns = g_malloc0(sizeof(xen_pfn_t) * xenfb->fbpages);
480 
481     xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
482     map = xenforeignmemory_map(xen_fmem, xenfb->c.xendev.dom,
483                                PROT_READ, n_fbdirs, pgmfns, NULL);
484     if (map == NULL)
485 	goto out;
486     xenfb_copy_mfns(mode, xenfb->fbpages, fbmfns, map);
487     xenforeignmemory_unmap(xen_fmem, map, n_fbdirs);
488 
489     xenfb->pixels = xenforeignmemory_map(xen_fmem, xenfb->c.xendev.dom,
490             PROT_READ, xenfb->fbpages, fbmfns, NULL);
491     if (xenfb->pixels == NULL)
492 	goto out;
493 
494     ret = 0; /* all is fine */
495 
496 out:
497     g_free(pgmfns);
498     g_free(fbmfns);
499     return ret;
500 }
501 
502 static int xenfb_configure_fb(struct XenFB *xenfb, size_t fb_len_lim,
503 			      int width, int height, int depth,
504 			      size_t fb_len, int offset, int row_stride)
505 {
506     size_t mfn_sz = sizeof(*((struct xenfb_page *)0)->pd);
507     size_t pd_len = sizeof(((struct xenfb_page *)0)->pd) / mfn_sz;
508     size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz;
509     size_t fb_len_max = fb_pages * XC_PAGE_SIZE;
510     int max_width, max_height;
511 
512     if (fb_len_lim > fb_len_max) {
513 	xen_be_printf(&xenfb->c.xendev, 0, "fb size limit %zu exceeds %zu, corrected\n",
514 		      fb_len_lim, fb_len_max);
515 	fb_len_lim = fb_len_max;
516     }
517     if (fb_len_lim && fb_len > fb_len_lim) {
518 	xen_be_printf(&xenfb->c.xendev, 0, "frontend fb size %zu limited to %zu\n",
519 		      fb_len, fb_len_lim);
520 	fb_len = fb_len_lim;
521     }
522     if (depth != 8 && depth != 16 && depth != 24 && depth != 32) {
523 	xen_be_printf(&xenfb->c.xendev, 0, "can't handle frontend fb depth %d\n",
524 		      depth);
525 	return -1;
526     }
527     if (row_stride <= 0 || row_stride > fb_len) {
528 	xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend stride %d\n", row_stride);
529 	return -1;
530     }
531     max_width = row_stride / (depth / 8);
532     if (width < 0 || width > max_width) {
533 	xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend width %d limited to %d\n",
534 		      width, max_width);
535 	width = max_width;
536     }
537     if (offset < 0 || offset >= fb_len) {
538 	xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend offset %d (max %zu)\n",
539 		      offset, fb_len - 1);
540 	return -1;
541     }
542     max_height = (fb_len - offset) / row_stride;
543     if (height < 0 || height > max_height) {
544 	xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend height %d limited to %d\n",
545 		      height, max_height);
546 	height = max_height;
547     }
548     xenfb->fb_len = fb_len;
549     xenfb->row_stride = row_stride;
550     xenfb->depth = depth;
551     xenfb->width = width;
552     xenfb->height = height;
553     xenfb->offset = offset;
554     xenfb->up_fullscreen = 1;
555     xenfb->do_resize = 1;
556     xen_be_printf(&xenfb->c.xendev, 1, "framebuffer %dx%dx%d offset %d stride %d\n",
557 		  width, height, depth, offset, row_stride);
558     return 0;
559 }
560 
561 /* A convenient function for munging pixels between different depths */
562 #define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB)                        \
563     for (line = y ; line < (y+h) ; line++) {				\
564 	SRC_T *src = (SRC_T *)(xenfb->pixels				\
565 			       + xenfb->offset				\
566 			       + (line * xenfb->row_stride)		\
567 			       + (x * xenfb->depth / 8));		\
568 	DST_T *dst = (DST_T *)(data					\
569 			       + (line * linesize)			\
570 			       + (x * bpp / 8));			\
571 	int col;							\
572 	const int RSS = 32 - (RSB + GSB + BSB);				\
573 	const int GSS = 32 - (GSB + BSB);				\
574 	const int BSS = 32 - (BSB);					\
575 	const uint32_t RSM = (~0U) << (32 - RSB);			\
576 	const uint32_t GSM = (~0U) << (32 - GSB);			\
577 	const uint32_t BSM = (~0U) << (32 - BSB);			\
578 	const int RDS = 32 - (RDB + GDB + BDB);				\
579 	const int GDS = 32 - (GDB + BDB);				\
580 	const int BDS = 32 - (BDB);					\
581 	const uint32_t RDM = (~0U) << (32 - RDB);			\
582 	const uint32_t GDM = (~0U) << (32 - GDB);			\
583 	const uint32_t BDM = (~0U) << (32 - BDB);			\
584 	for (col = x ; col < (x+w) ; col++) {				\
585 	    uint32_t spix = *src;					\
586 	    *dst = (((spix << RSS) & RSM & RDM) >> RDS) |		\
587 		(((spix << GSS) & GSM & GDM) >> GDS) |			\
588 		(((spix << BSS) & BSM & BDM) >> BDS);			\
589 	    src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8);	\
590 	    dst = (DST_T *) ((unsigned long) dst + bpp / 8);		\
591 	}								\
592     }
593 
594 
595 /*
596  * This copies data from the guest framebuffer region, into QEMU's
597  * displaysurface. qemu uses 16 or 32 bpp.  In case the pv framebuffer
598  * uses something else we must convert and copy, otherwise we can
599  * supply the buffer directly and no thing here.
600  */
601 static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
602 {
603     DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
604     int line, oops = 0;
605     int bpp = surface_bits_per_pixel(surface);
606     int linesize = surface_stride(surface);
607     uint8_t *data = surface_data(surface);
608 
609     if (!is_buffer_shared(surface)) {
610         switch (xenfb->depth) {
611         case 8:
612             if (bpp == 16) {
613                 BLT(uint8_t, uint16_t,   3, 3, 2,   5, 6, 5);
614             } else if (bpp == 32) {
615                 BLT(uint8_t, uint32_t,   3, 3, 2,   8, 8, 8);
616             } else {
617                 oops = 1;
618             }
619             break;
620         case 24:
621             if (bpp == 16) {
622                 BLT(uint32_t, uint16_t,  8, 8, 8,   5, 6, 5);
623             } else if (bpp == 32) {
624                 BLT(uint32_t, uint32_t,  8, 8, 8,   8, 8, 8);
625             } else {
626                 oops = 1;
627             }
628             break;
629         default:
630             oops = 1;
631 	}
632     }
633     if (oops) /* should not happen */
634         xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n",
635                       __FUNCTION__, xenfb->depth, bpp);
636 
637     dpy_gfx_update(xenfb->c.con, x, y, w, h);
638 }
639 
640 #ifdef XENFB_TYPE_REFRESH_PERIOD
641 static int xenfb_queue_full(struct XenFB *xenfb)
642 {
643     struct xenfb_page *page = xenfb->c.page;
644     uint32_t cons, prod;
645 
646     if (!page)
647         return 1;
648 
649     prod = page->in_prod;
650     cons = page->in_cons;
651     return prod - cons == XENFB_IN_RING_LEN;
652 }
653 
654 static void xenfb_send_event(struct XenFB *xenfb, union xenfb_in_event *event)
655 {
656     uint32_t prod;
657     struct xenfb_page *page = xenfb->c.page;
658 
659     prod = page->in_prod;
660     /* caller ensures !xenfb_queue_full() */
661     xen_mb();                   /* ensure ring space available */
662     XENFB_IN_RING_REF(page, prod) = *event;
663     xen_wmb();                  /* ensure ring contents visible */
664     page->in_prod = prod + 1;
665 
666     xen_be_send_notify(&xenfb->c.xendev);
667 }
668 
669 static void xenfb_send_refresh_period(struct XenFB *xenfb, int period)
670 {
671     union xenfb_in_event event;
672 
673     memset(&event, 0, sizeof(event));
674     event.type = XENFB_TYPE_REFRESH_PERIOD;
675     event.refresh_period.period = period;
676     xenfb_send_event(xenfb, &event);
677 }
678 #endif
679 
680 /*
681  * Periodic update of display.
682  * Also transmit the refresh interval to the frontend.
683  *
684  * Never ever do any qemu display operations
685  * (resize, screen update) outside this function.
686  * Our screen might be inactive.  When asked for
687  * an update we know it is active.
688  */
689 static void xenfb_update(void *opaque)
690 {
691     struct XenFB *xenfb = opaque;
692     DisplaySurface *surface;
693     int i;
694 
695     if (xenfb->c.xendev.be_state != XenbusStateConnected)
696         return;
697 
698     if (!xenfb->feature_update) {
699 	/* we don't get update notifications, thus use the
700 	 * sledge hammer approach ... */
701 	xenfb->up_fullscreen = 1;
702     }
703 
704     /* resize if needed */
705     if (xenfb->do_resize) {
706         pixman_format_code_t format;
707 
708         xenfb->do_resize = 0;
709         switch (xenfb->depth) {
710         case 16:
711         case 32:
712             /* console.c supported depth -> buffer can be used directly */
713             format = qemu_default_pixman_format(xenfb->depth, true);
714             surface = qemu_create_displaysurface_from
715                 (xenfb->width, xenfb->height, format,
716                  xenfb->row_stride, xenfb->pixels + xenfb->offset);
717             break;
718         default:
719             /* we must convert stuff */
720             surface = qemu_create_displaysurface(xenfb->width, xenfb->height);
721             break;
722         }
723         dpy_gfx_replace_surface(xenfb->c.con, surface);
724         xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n",
725                       xenfb->width, xenfb->height, xenfb->depth,
726                       is_buffer_shared(surface) ? " (shared)" : "");
727         xenfb->up_fullscreen = 1;
728     }
729 
730     /* run queued updates */
731     if (xenfb->up_fullscreen) {
732 	xen_be_printf(&xenfb->c.xendev, 3, "update: fullscreen\n");
733 	xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
734     } else if (xenfb->up_count) {
735 	xen_be_printf(&xenfb->c.xendev, 3, "update: %d rects\n", xenfb->up_count);
736 	for (i = 0; i < xenfb->up_count; i++)
737 	    xenfb_guest_copy(xenfb,
738 			     xenfb->up_rects[i].x,
739 			     xenfb->up_rects[i].y,
740 			     xenfb->up_rects[i].w,
741 			     xenfb->up_rects[i].h);
742     } else {
743 	xen_be_printf(&xenfb->c.xendev, 3, "update: nothing\n");
744     }
745     xenfb->up_count = 0;
746     xenfb->up_fullscreen = 0;
747 }
748 
749 static void xenfb_update_interval(void *opaque, uint64_t interval)
750 {
751     struct XenFB *xenfb = opaque;
752 
753     if (xenfb->feature_update) {
754 #ifdef XENFB_TYPE_REFRESH_PERIOD
755         if (xenfb_queue_full(xenfb)) {
756             return;
757         }
758         xenfb_send_refresh_period(xenfb, interval);
759 #endif
760     }
761 }
762 
763 /* QEMU display state changed, so refresh the framebuffer copy */
764 static void xenfb_invalidate(void *opaque)
765 {
766     struct XenFB *xenfb = opaque;
767     xenfb->up_fullscreen = 1;
768 }
769 
770 static void xenfb_handle_events(struct XenFB *xenfb)
771 {
772     uint32_t prod, cons, out_cons;
773     struct xenfb_page *page = xenfb->c.page;
774 
775     prod = page->out_prod;
776     out_cons = page->out_cons;
777     if (prod - out_cons > XENFB_OUT_RING_LEN) {
778         return;
779     }
780     xen_rmb();		/* ensure we see ring contents up to prod */
781     for (cons = out_cons; cons != prod; cons++) {
782 	union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
783         uint8_t type = event->type;
784 	int x, y, w, h;
785 
786 	switch (type) {
787 	case XENFB_TYPE_UPDATE:
788 	    if (xenfb->up_count == UP_QUEUE)
789 		xenfb->up_fullscreen = 1;
790 	    if (xenfb->up_fullscreen)
791 		break;
792 	    x = MAX(event->update.x, 0);
793 	    y = MAX(event->update.y, 0);
794 	    w = MIN(event->update.width, xenfb->width - x);
795 	    h = MIN(event->update.height, xenfb->height - y);
796 	    if (w < 0 || h < 0) {
797                 xen_be_printf(&xenfb->c.xendev, 1, "bogus update ignored\n");
798 		break;
799 	    }
800 	    if (x != event->update.x ||
801                 y != event->update.y ||
802 		w != event->update.width ||
803 		h != event->update.height) {
804                 xen_be_printf(&xenfb->c.xendev, 1, "bogus update clipped\n");
805 	    }
806 	    if (w == xenfb->width && h > xenfb->height / 2) {
807 		/* scroll detector: updated more than 50% of the lines,
808 		 * don't bother keeping track of the rectangles then */
809 		xenfb->up_fullscreen = 1;
810 	    } else {
811 		xenfb->up_rects[xenfb->up_count].x = x;
812 		xenfb->up_rects[xenfb->up_count].y = y;
813 		xenfb->up_rects[xenfb->up_count].w = w;
814 		xenfb->up_rects[xenfb->up_count].h = h;
815 		xenfb->up_count++;
816 	    }
817 	    break;
818 #ifdef XENFB_TYPE_RESIZE
819 	case XENFB_TYPE_RESIZE:
820 	    if (xenfb_configure_fb(xenfb, xenfb->fb_len,
821 				   event->resize.width,
822 				   event->resize.height,
823 				   event->resize.depth,
824 				   xenfb->fb_len,
825 				   event->resize.offset,
826 				   event->resize.stride) < 0)
827 		break;
828 	    xenfb_invalidate(xenfb);
829 	    break;
830 #endif
831 	}
832     }
833     xen_mb();		/* ensure we're done with ring contents */
834     page->out_cons = cons;
835 }
836 
837 static int fb_init(struct XenDevice *xendev)
838 {
839 #ifdef XENFB_TYPE_RESIZE
840     xenstore_write_be_int(xendev, "feature-resize", 1);
841 #endif
842     return 0;
843 }
844 
845 static int fb_initialise(struct XenDevice *xendev)
846 {
847     struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
848     struct xenfb_page *fb_page;
849     int videoram;
850     int rc;
851 
852     if (xenstore_read_fe_int(xendev, "videoram", &videoram) == -1)
853 	videoram = 0;
854 
855     rc = common_bind(&fb->c);
856     if (rc != 0)
857 	return rc;
858 
859     fb_page = fb->c.page;
860     rc = xenfb_configure_fb(fb, videoram * 1024 * 1024U,
861 			    fb_page->width, fb_page->height, fb_page->depth,
862 			    fb_page->mem_length, 0, fb_page->line_length);
863     if (rc != 0)
864 	return rc;
865 
866     rc = xenfb_map_fb(fb);
867     if (rc != 0)
868 	return rc;
869 
870 #if 0  /* handled in xen_init_display() for now */
871     if (!fb->have_console) {
872         fb->c.ds = graphic_console_init(xenfb_update,
873                                         xenfb_invalidate,
874                                         NULL,
875                                         NULL,
876                                         fb);
877         fb->have_console = 1;
878     }
879 #endif
880 
881     if (xenstore_read_fe_int(xendev, "feature-update", &fb->feature_update) == -1)
882 	fb->feature_update = 0;
883     if (fb->feature_update)
884 	xenstore_write_be_int(xendev, "request-update", 1);
885 
886     xen_be_printf(xendev, 1, "feature-update=%d, videoram=%d\n",
887 		  fb->feature_update, videoram);
888     return 0;
889 }
890 
891 static void fb_disconnect(struct XenDevice *xendev)
892 {
893     struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
894 
895     /*
896      * FIXME: qemu can't un-init gfx display (yet?).
897      *   Replacing the framebuffer with anonymous shared memory
898      *   instead.  This releases the guest pages and keeps qemu happy.
899      */
900     xenforeignmemory_unmap(xen_fmem, fb->pixels, fb->fbpages);
901     fb->pixels = mmap(fb->pixels, fb->fbpages * XC_PAGE_SIZE,
902                       PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON,
903                       -1, 0);
904     if (fb->pixels == MAP_FAILED) {
905         xen_be_printf(xendev, 0,
906                 "Couldn't replace the framebuffer with anonymous memory errno=%d\n",
907                 errno);
908     }
909     common_unbind(&fb->c);
910     fb->feature_update = 0;
911     fb->bug_trigger    = 0;
912 }
913 
914 static void fb_frontend_changed(struct XenDevice *xendev, const char *node)
915 {
916     struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
917 
918     /*
919      * Set state to Connected *again* once the frontend switched
920      * to connected.  We must trigger the watch a second time to
921      * workaround a frontend bug.
922      */
923     if (fb->bug_trigger == 0 && strcmp(node, "state") == 0 &&
924         xendev->fe_state == XenbusStateConnected &&
925         xendev->be_state == XenbusStateConnected) {
926         xen_be_printf(xendev, 2, "re-trigger connected (frontend bug)\n");
927         xen_be_set_state(xendev, XenbusStateConnected);
928         fb->bug_trigger = 1; /* only once */
929     }
930 }
931 
932 static void fb_event(struct XenDevice *xendev)
933 {
934     struct XenFB *xenfb = container_of(xendev, struct XenFB, c.xendev);
935 
936     xenfb_handle_events(xenfb);
937     xen_be_send_notify(&xenfb->c.xendev);
938 }
939 
940 /* -------------------------------------------------------------------- */
941 
942 struct XenDevOps xen_kbdmouse_ops = {
943     .size       = sizeof(struct XenInput),
944     .init       = input_init,
945     .initialise = input_initialise,
946     .connected  = input_connected,
947     .disconnect = input_disconnect,
948     .event      = input_event,
949 };
950 
951 struct XenDevOps xen_framebuffer_ops = {
952     .size       = sizeof(struct XenFB),
953     .init       = fb_init,
954     .initialise = fb_initialise,
955     .disconnect = fb_disconnect,
956     .event      = fb_event,
957     .frontend_changed = fb_frontend_changed,
958 };
959 
960 static const GraphicHwOps xenfb_ops = {
961     .invalidate  = xenfb_invalidate,
962     .gfx_update  = xenfb_update,
963     .update_interval = xenfb_update_interval,
964 };
965 
966 /*
967  * FIXME/TODO: Kill this.
968  * Temporary needed while DisplayState reorganization is in flight.
969  */
970 void xen_init_display(int domid)
971 {
972     struct XenDevice *xfb, *xin;
973     struct XenFB *fb;
974     struct XenInput *in;
975     int i = 0;
976 
977 wait_more:
978     i++;
979     main_loop_wait(true);
980     xfb = xen_be_find_xendev("vfb", domid, 0);
981     xin = xen_be_find_xendev("vkbd", domid, 0);
982     if (!xfb || !xin) {
983         if (i < 256) {
984             usleep(10000);
985             goto wait_more;
986         }
987         xen_be_printf(NULL, 1, "displaystate setup failed\n");
988         return;
989     }
990 
991     /* vfb */
992     fb = container_of(xfb, struct XenFB, c.xendev);
993     fb->c.con = graphic_console_init(NULL, 0, &xenfb_ops, fb);
994     fb->have_console = 1;
995 
996     /* vkbd */
997     in = container_of(xin, struct XenInput, c.xendev);
998     in->c.con = fb->c.con;
999 
1000     /* retry ->init() */
1001     xen_be_check_state(xin);
1002     xen_be_check_state(xfb);
1003 }
1004