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