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