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