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