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