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