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