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