da5297b4989952d188ee0c6f8359bdb9a5619a9d
[sdk/emulator/qemu.git] / hw / xenfb.c
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 <xs.h>
39 #include <xenctrl.h>
40 #include <xen/event_channel.h>
41 #include <xen/io/xenbus.h>
42 #include <xen/io/fbif.h>
43 #include <xen/io/kbdif.h>
44 #include <xen/io/protocols.h>
45
46 #include "hw.h"
47 #include "sysemu.h"
48 #include "console.h"
49 #include "qemu-char.h"
50 #include "xen_backend.h"
51
52 #ifndef BTN_LEFT
53 #define BTN_LEFT 0x110 /* from <linux/input.h> */
54 #endif
55
56 /* -------------------------------------------------------------------- */
57
58 struct common {
59     struct XenDevice  xendev;  /* must be first */
60     void              *page;
61     DisplayState      *ds;
62 };
63
64 struct XenInput {
65     struct common c;
66     int abs_pointer_wanted; /* Whether guest supports absolute pointer */
67     int button_state;       /* Last seen pointer button state */
68     int extended;
69     QEMUPutMouseEntry *qmouse;
70 };
71
72 #define UP_QUEUE 8
73
74 struct XenFB {
75     struct common     c;
76     size_t            fb_len;
77     int               row_stride;
78     int               depth;
79     int               width;
80     int               height;
81     int               offset;
82     void              *pixels;
83     int               fbpages;
84     int               feature_update;
85     int               refresh_period;
86     int               bug_trigger;
87     int               have_console;
88     int               do_resize;
89
90     struct {
91         int x,y,w,h;
92     } up_rects[UP_QUEUE];
93     int               up_count;
94     int               up_fullscreen;
95 };
96
97 /* -------------------------------------------------------------------- */
98
99 static int common_bind(struct common *c)
100 {
101     int mfn;
102
103     if (xenstore_read_fe_int(&c->xendev, "page-ref", &mfn) == -1)
104         return -1;
105     if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1)
106         return -1;
107
108     c->page = xc_map_foreign_range(xen_xc, c->xendev.dom,
109                                    XC_PAGE_SIZE,
110                                    PROT_READ | PROT_WRITE, mfn);
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 %d, 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         munmap(c->page, XC_PAGE_SIZE);
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     int dw = ds_get_width(xenfb->c.ds);
326     int dh = ds_get_height(xenfb->c.ds);
327     int i;
328
329     if (xenfb->abs_pointer_wanted)
330         xenfb_send_position(xenfb,
331                             dx * (dw - 1) / 0x7fff,
332                             dy * (dh - 1) / 0x7fff,
333                             dz);
334     else
335         xenfb_send_motion(xenfb, dx, dy, dz);
336
337     for (i = 0 ; i < 8 ; i++) {
338         int lastDown = xenfb->button_state & (1 << i);
339         int down = button_state & (1 << i);
340         if (down == lastDown)
341             continue;
342
343         if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
344             return;
345     }
346     xenfb->button_state = button_state;
347 }
348
349 static int input_init(struct XenDevice *xendev)
350 {
351     struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
352
353     if (!in->c.ds) {
354         xen_be_printf(xendev, 1, "ds not set (yet)\n");
355         return -1;
356     }
357
358     xenstore_write_be_int(xendev, "feature-abs-pointer", 1);
359     return 0;
360 }
361
362 static int input_connect(struct XenDevice *xendev)
363 {
364     struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
365     int rc;
366
367     if (xenstore_read_fe_int(xendev, "request-abs-pointer",
368                              &in->abs_pointer_wanted) == -1)
369         in->abs_pointer_wanted = 0;
370
371     rc = common_bind(&in->c);
372     if (rc != 0)
373         return rc;
374
375     qemu_add_kbd_event_handler(xenfb_key_event, in);
376     in->qmouse = qemu_add_mouse_event_handler(xenfb_mouse_event, in,
377                                               in->abs_pointer_wanted,
378                                               "Xen PVFB Mouse");
379     return 0;
380 }
381
382 static void input_disconnect(struct XenDevice *xendev)
383 {
384     struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
385
386     if (in->qmouse) {
387         qemu_remove_mouse_event_handler(in->qmouse);
388         in->qmouse = NULL;
389     }
390     qemu_add_kbd_event_handler(NULL, NULL);
391     common_unbind(&in->c);
392 }
393
394 static void input_event(struct XenDevice *xendev)
395 {
396     struct XenInput *xenfb = container_of(xendev, struct XenInput, c.xendev);
397     struct xenkbd_page *page = xenfb->c.page;
398
399     /* We don't understand any keyboard events, so just ignore them. */
400     if (page->out_prod == page->out_cons)
401         return;
402     page->out_cons = page->out_prod;
403     xen_be_send_notify(&xenfb->c.xendev);
404 }
405
406 /* -------------------------------------------------------------------- */
407
408 static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
409 {
410     uint32_t *src32 = src;
411     uint64_t *src64 = src;
412     int i;
413
414     for (i = 0; i < count; i++)
415         dst[i] = (mode == 32) ? src32[i] : src64[i];
416 }
417
418 static int xenfb_map_fb(struct XenFB *xenfb)
419 {
420     struct xenfb_page *page = xenfb->c.page;
421     char *protocol = xenfb->c.xendev.protocol;
422     int n_fbdirs;
423     unsigned long *pgmfns = NULL;
424     unsigned long *fbmfns = NULL;
425     void *map, *pd;
426     int mode, ret = -1;
427
428     /* default to native */
429     pd = page->pd;
430     mode = sizeof(unsigned long) * 8;
431
432     if (!protocol) {
433         /*
434          * Undefined protocol, some guesswork needed.
435          *
436          * Old frontends which don't set the protocol use
437          * one page directory only, thus pd[1] must be zero.
438          * pd[1] of the 32bit struct layout and the lower
439          * 32 bits of pd[0] of the 64bit struct layout have
440          * the same location, so we can check that ...
441          */
442         uint32_t *ptr32 = NULL;
443         uint32_t *ptr64 = NULL;
444 #if defined(__i386__)
445         ptr32 = (void*)page->pd;
446         ptr64 = ((void*)page->pd) + 4;
447 #elif defined(__x86_64__)
448         ptr32 = ((void*)page->pd) - 4;
449         ptr64 = (void*)page->pd;
450 #endif
451         if (ptr32) {
452             if (ptr32[1] == 0) {
453                 mode = 32;
454                 pd   = ptr32;
455             } else {
456                 mode = 64;
457                 pd   = ptr64;
458             }
459         }
460 #if defined(__x86_64__)
461     } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) {
462         /* 64bit dom0, 32bit domU */
463         mode = 32;
464         pd   = ((void*)page->pd) - 4;
465 #elif defined(__i386__)
466     } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_64) == 0) {
467         /* 32bit dom0, 64bit domU */
468         mode = 64;
469         pd   = ((void*)page->pd) + 4;
470 #endif
471     }
472
473     if (xenfb->pixels) {
474         munmap(xenfb->pixels, xenfb->fbpages * XC_PAGE_SIZE);
475         xenfb->pixels = NULL;
476     }
477
478     xenfb->fbpages = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
479     n_fbdirs = xenfb->fbpages * mode / 8;
480     n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
481
482     pgmfns = qemu_mallocz(sizeof(unsigned long) * n_fbdirs);
483     fbmfns = qemu_mallocz(sizeof(unsigned long) * xenfb->fbpages);
484
485     xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
486     map = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
487                                PROT_READ, pgmfns, n_fbdirs);
488     if (map == NULL)
489         goto out;
490     xenfb_copy_mfns(mode, xenfb->fbpages, fbmfns, map);
491     munmap(map, n_fbdirs * XC_PAGE_SIZE);
492
493     xenfb->pixels = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
494                                          PROT_READ | PROT_WRITE, fbmfns, xenfb->fbpages);
495     if (xenfb->pixels == NULL)
496         goto out;
497
498     ret = 0; /* all is fine */
499
500 out:
501     qemu_free(pgmfns);
502     qemu_free(fbmfns);
503     return ret;
504 }
505
506 static int xenfb_configure_fb(struct XenFB *xenfb, size_t fb_len_lim,
507                               int width, int height, int depth,
508                               size_t fb_len, int offset, int row_stride)
509 {
510     size_t mfn_sz = sizeof(*((struct xenfb_page *)0)->pd);
511     size_t pd_len = sizeof(((struct xenfb_page *)0)->pd) / mfn_sz;
512     size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz;
513     size_t fb_len_max = fb_pages * XC_PAGE_SIZE;
514     int max_width, max_height;
515
516     if (fb_len_lim > fb_len_max) {
517         xen_be_printf(&xenfb->c.xendev, 0, "fb size limit %zu exceeds %zu, corrected\n",
518                       fb_len_lim, fb_len_max);
519         fb_len_lim = fb_len_max;
520     }
521     if (fb_len_lim && fb_len > fb_len_lim) {
522         xen_be_printf(&xenfb->c.xendev, 0, "frontend fb size %zu limited to %zu\n",
523                       fb_len, fb_len_lim);
524         fb_len = fb_len_lim;
525     }
526     if (depth != 8 && depth != 16 && depth != 24 && depth != 32) {
527         xen_be_printf(&xenfb->c.xendev, 0, "can't handle frontend fb depth %d\n",
528                       depth);
529         return -1;
530     }
531     if (row_stride <= 0 || row_stride > fb_len) {
532         xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend stride %d\n", row_stride);
533         return -1;
534     }
535     max_width = row_stride / (depth / 8);
536     if (width < 0 || width > max_width) {
537         xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend width %d limited to %d\n",
538                       width, max_width);
539         width = max_width;
540     }
541     if (offset < 0 || offset >= fb_len) {
542         xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend offset %d (max %zu)\n",
543                       offset, fb_len - 1);
544         return -1;
545     }
546     max_height = (fb_len - offset) / row_stride;
547     if (height < 0 || height > max_height) {
548         xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend height %d limited to %d\n",
549                       height, max_height);
550         height = max_height;
551     }
552     xenfb->fb_len = fb_len;
553     xenfb->row_stride = row_stride;
554     xenfb->depth = depth;
555     xenfb->width = width;
556     xenfb->height = height;
557     xenfb->offset = offset;
558     xenfb->up_fullscreen = 1;
559     xenfb->do_resize = 1;
560     xen_be_printf(&xenfb->c.xendev, 1, "framebuffer %dx%dx%d offset %d stride %d\n",
561                   width, height, depth, offset, row_stride);
562     return 0;
563 }
564
565 /* A convenient function for munging pixels between different depths */
566 #define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB)                        \
567     for (line = y ; line < (y+h) ; line++) {                            \
568         SRC_T *src = (SRC_T *)(xenfb->pixels                            \
569                                + xenfb->offset                          \
570                                + (line * xenfb->row_stride)             \
571                                + (x * xenfb->depth / 8));               \
572         DST_T *dst = (DST_T *)(data                                     \
573                                + (line * linesize)                      \
574                                + (x * bpp / 8));                        \
575         int col;                                                        \
576         const int RSS = 32 - (RSB + GSB + BSB);                         \
577         const int GSS = 32 - (GSB + BSB);                               \
578         const int BSS = 32 - (BSB);                                     \
579         const uint32_t RSM = (~0U) << (32 - RSB);                       \
580         const uint32_t GSM = (~0U) << (32 - GSB);                       \
581         const uint32_t BSM = (~0U) << (32 - BSB);                       \
582         const int RDS = 32 - (RDB + GDB + BDB);                         \
583         const int GDS = 32 - (GDB + BDB);                               \
584         const int BDS = 32 - (BDB);                                     \
585         const uint32_t RDM = (~0U) << (32 - RDB);                       \
586         const uint32_t GDM = (~0U) << (32 - GDB);                       \
587         const uint32_t BDM = (~0U) << (32 - BDB);                       \
588         for (col = x ; col < (x+w) ; col++) {                           \
589             uint32_t spix = *src;                                       \
590             *dst = (((spix << RSS) & RSM & RDM) >> RDS) |               \
591                 (((spix << GSS) & GSM & GDM) >> GDS) |                  \
592                 (((spix << BSS) & BSM & BDM) >> BDS);                   \
593             src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8);   \
594             dst = (DST_T *) ((unsigned long) dst + bpp / 8);            \
595         }                                                               \
596     }
597
598
599 /*
600  * This copies data from the guest framebuffer region, into QEMU's
601  * displaysurface. qemu uses 16 or 32 bpp.  In case the pv framebuffer
602  * uses something else we must convert and copy, otherwise we can
603  * supply the buffer directly and no thing here.
604  */
605 static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
606 {
607     int line, oops = 0;
608     int bpp = ds_get_bits_per_pixel(xenfb->c.ds);
609     int linesize = ds_get_linesize(xenfb->c.ds);
610     uint8_t *data = ds_get_data(xenfb->c.ds);
611
612     if (!is_buffer_shared(xenfb->c.ds->surface)) {
613         switch (xenfb->depth) {
614         case 8:
615             if (bpp == 16) {
616                 BLT(uint8_t, uint16_t,   3, 3, 2,   5, 6, 5);
617             } else if (bpp == 32) {
618                 BLT(uint8_t, uint32_t,   3, 3, 2,   8, 8, 8);
619             } else {
620                 oops = 1;
621             }
622             break;
623         case 24:
624             if (bpp == 16) {
625                 BLT(uint32_t, uint16_t,  8, 8, 8,   5, 6, 5);
626             } else if (bpp == 32) {
627                 BLT(uint32_t, uint32_t,  8, 8, 8,   8, 8, 8);
628             } else {
629                 oops = 1;
630             }
631             break;
632         default:
633             oops = 1;
634         }
635     }
636     if (oops) /* should not happen */
637         xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n",
638                       __FUNCTION__, xenfb->depth, bpp);
639
640     dpy_update(xenfb->c.ds, x, y, w, h);
641 }
642
643 #ifdef XENFB_TYPE_REFRESH_PERIOD
644 static int xenfb_queue_full(struct XenFB *xenfb)
645 {
646     struct xenfb_page *page = xenfb->c.page;
647     uint32_t cons, prod;
648
649     if (!page)
650         return 1;
651
652     prod = page->in_prod;
653     cons = page->in_cons;
654     return prod - cons == XENFB_IN_RING_LEN;
655 }
656
657 static void xenfb_send_event(struct XenFB *xenfb, union xenfb_in_event *event)
658 {
659     uint32_t prod;
660     struct xenfb_page *page = xenfb->c.page;
661
662     prod = page->in_prod;
663     /* caller ensures !xenfb_queue_full() */
664     xen_mb();                   /* ensure ring space available */
665     XENFB_IN_RING_REF(page, prod) = *event;
666     xen_wmb();                  /* ensure ring contents visible */
667     page->in_prod = prod + 1;
668
669     xen_be_send_notify(&xenfb->c.xendev);
670 }
671
672 static void xenfb_send_refresh_period(struct XenFB *xenfb, int period)
673 {
674     union xenfb_in_event event;
675
676     memset(&event, 0, sizeof(event));
677     event.type = XENFB_TYPE_REFRESH_PERIOD;
678     event.refresh_period.period = period;
679     xenfb_send_event(xenfb, &event);
680 }
681 #endif
682
683 /*
684  * Periodic update of display.
685  * Also transmit the refresh interval to the frontend.
686  *
687  * Never ever do any qemu display operations
688  * (resize, screen update) outside this function.
689  * Our screen might be inactive.  When asked for
690  * an update we know it is active.
691  */
692 static void xenfb_update(void *opaque)
693 {
694     struct XenFB *xenfb = opaque;
695     int i;
696
697     if (xenfb->c.xendev.be_state != XenbusStateConnected)
698         return;
699
700     if (xenfb->feature_update) {
701 #ifdef XENFB_TYPE_REFRESH_PERIOD
702         struct DisplayChangeListener *l;
703         int period = 99999999;
704         int idle = 1;
705
706         if (xenfb_queue_full(xenfb))
707             return;
708
709         for (l = xenfb->c.ds->listeners; l != NULL; l = l->next) {
710             if (l->idle)
711                 continue;
712             idle = 0;
713             if (!l->gui_timer_interval) {
714                 if (period > GUI_REFRESH_INTERVAL)
715                     period = GUI_REFRESH_INTERVAL;
716             } else {
717                 if (period > l->gui_timer_interval)
718                     period = l->gui_timer_interval;
719             }
720         }
721         if (idle)
722             period = XENFB_NO_REFRESH;
723
724         if (xenfb->refresh_period != period) {
725             xenfb_send_refresh_period(xenfb, period);
726             xenfb->refresh_period = period;
727             xen_be_printf(&xenfb->c.xendev, 1, "refresh period: %d\n", period);
728         }
729 #else
730         ; /* nothing */
731 #endif
732     } else {
733         /* we don't get update notifications, thus use the
734          * sledge hammer approach ... */
735         xenfb->up_fullscreen = 1;
736     }
737
738     /* resize if needed */
739     if (xenfb->do_resize) {
740         xenfb->do_resize = 0;
741         switch (xenfb->depth) {
742         case 16:
743         case 32:
744             /* console.c supported depth -> buffer can be used directly */
745             qemu_free_displaysurface(xenfb->c.ds);
746             xenfb->c.ds->surface = qemu_create_displaysurface_from
747                 (xenfb->width, xenfb->height, xenfb->depth,
748                  xenfb->row_stride, xenfb->pixels + xenfb->offset);
749             break;
750         default:
751             /* we must convert stuff */
752             qemu_resize_displaysurface(xenfb->c.ds, xenfb->width, xenfb->height);
753             break;
754         }
755         xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n",
756                       xenfb->width, xenfb->height, xenfb->depth,
757                       is_buffer_shared(xenfb->c.ds->surface) ? " (shared)" : "");
758         dpy_resize(xenfb->c.ds);
759         xenfb->up_fullscreen = 1;
760     }
761
762     /* run queued updates */
763     if (xenfb->up_fullscreen) {
764         xen_be_printf(&xenfb->c.xendev, 3, "update: fullscreen\n");
765         xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
766     } else if (xenfb->up_count) {
767         xen_be_printf(&xenfb->c.xendev, 3, "update: %d rects\n", xenfb->up_count);
768         for (i = 0; i < xenfb->up_count; i++)
769             xenfb_guest_copy(xenfb,
770                              xenfb->up_rects[i].x,
771                              xenfb->up_rects[i].y,
772                              xenfb->up_rects[i].w,
773                              xenfb->up_rects[i].h);
774     } else {
775         xen_be_printf(&xenfb->c.xendev, 3, "update: nothing\n");
776     }
777     xenfb->up_count = 0;
778     xenfb->up_fullscreen = 0;
779 }
780
781 /* QEMU display state changed, so refresh the framebuffer copy */
782 static void xenfb_invalidate(void *opaque)
783 {
784     struct XenFB *xenfb = opaque;
785     xenfb->up_fullscreen = 1;
786 }
787
788 static void xenfb_handle_events(struct XenFB *xenfb)
789 {
790     uint32_t prod, cons;
791     struct xenfb_page *page = xenfb->c.page;
792
793     prod = page->out_prod;
794     if (prod == page->out_cons)
795         return;
796     xen_rmb();          /* ensure we see ring contents up to prod */
797     for (cons = page->out_cons; cons != prod; cons++) {
798         union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
799         int x, y, w, h;
800
801         switch (event->type) {
802         case XENFB_TYPE_UPDATE:
803             if (xenfb->up_count == UP_QUEUE)
804                 xenfb->up_fullscreen = 1;
805             if (xenfb->up_fullscreen)
806                 break;
807             x = MAX(event->update.x, 0);
808             y = MAX(event->update.y, 0);
809             w = MIN(event->update.width, xenfb->width - x);
810             h = MIN(event->update.height, xenfb->height - y);
811             if (w < 0 || h < 0) {
812                 xen_be_printf(&xenfb->c.xendev, 1, "bogus update ignored\n");
813                 break;
814             }
815             if (x != event->update.x ||
816                 y != event->update.y ||
817                 w != event->update.width ||
818                 h != event->update.height) {
819                 xen_be_printf(&xenfb->c.xendev, 1, "bogus update clipped\n");
820             }
821             if (w == xenfb->width && h > xenfb->height / 2) {
822                 /* scroll detector: updated more than 50% of the lines,
823                  * don't bother keeping track of the rectangles then */
824                 xenfb->up_fullscreen = 1;
825             } else {
826                 xenfb->up_rects[xenfb->up_count].x = x;
827                 xenfb->up_rects[xenfb->up_count].y = y;
828                 xenfb->up_rects[xenfb->up_count].w = w;
829                 xenfb->up_rects[xenfb->up_count].h = h;
830                 xenfb->up_count++;
831             }
832             break;
833 #ifdef XENFB_TYPE_RESIZE
834         case XENFB_TYPE_RESIZE:
835             if (xenfb_configure_fb(xenfb, xenfb->fb_len,
836                                    event->resize.width,
837                                    event->resize.height,
838                                    event->resize.depth,
839                                    xenfb->fb_len,
840                                    event->resize.offset,
841                                    event->resize.stride) < 0)
842                 break;
843             xenfb_invalidate(xenfb);
844             break;
845 #endif
846         }
847     }
848     xen_mb();           /* ensure we're done with ring contents */
849     page->out_cons = cons;
850 }
851
852 static int fb_init(struct XenDevice *xendev)
853 {
854     struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
855
856     fb->refresh_period = -1;
857
858 #ifdef XENFB_TYPE_RESIZE
859     xenstore_write_be_int(xendev, "feature-resize", 1);
860 #endif
861     return 0;
862 }
863
864 static int fb_connect(struct XenDevice *xendev)
865 {
866     struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
867     struct xenfb_page *fb_page;
868     int videoram;
869     int rc;
870
871     if (xenstore_read_fe_int(xendev, "videoram", &videoram) == -1)
872         videoram = 0;
873
874     rc = common_bind(&fb->c);
875     if (rc != 0)
876         return rc;
877
878     fb_page = fb->c.page;
879     rc = xenfb_configure_fb(fb, videoram * 1024 * 1024U,
880                             fb_page->width, fb_page->height, fb_page->depth,
881                             fb_page->mem_length, 0, fb_page->line_length);
882     if (rc != 0)
883         return rc;
884
885     rc = xenfb_map_fb(fb);
886     if (rc != 0)
887         return rc;
888
889 #if 0  /* handled in xen_init_display() for now */
890     if (!fb->have_console) {
891         fb->c.ds = graphic_console_init(xenfb_update,
892                                         xenfb_invalidate,
893                                         NULL,
894                                         NULL,
895                                         fb);
896         fb->have_console = 1;
897     }
898 #endif
899
900     if (xenstore_read_fe_int(xendev, "feature-update", &fb->feature_update) == -1)
901         fb->feature_update = 0;
902     if (fb->feature_update)
903         xenstore_write_be_int(xendev, "request-update", 1);
904
905     xen_be_printf(xendev, 1, "feature-update=%d, videoram=%d\n",
906                   fb->feature_update, videoram);
907     return 0;
908 }
909
910 static void fb_disconnect(struct XenDevice *xendev)
911 {
912     struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
913
914     /*
915      * FIXME: qemu can't un-init gfx display (yet?).
916      *   Replacing the framebuffer with anonymous shared memory
917      *   instead.  This releases the guest pages and keeps qemu happy.
918      */
919     fb->pixels = mmap(fb->pixels, fb->fbpages * XC_PAGE_SIZE,
920                       PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON,
921                       -1, 0);
922     common_unbind(&fb->c);
923     fb->feature_update = 0;
924     fb->bug_trigger    = 0;
925 }
926
927 static void fb_frontend_changed(struct XenDevice *xendev, const char *node)
928 {
929     struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
930
931     /*
932      * Set state to Connected *again* once the frontend switched
933      * to connected.  We must trigger the watch a second time to
934      * workaround a frontend bug.
935      */
936     if (fb->bug_trigger == 0 && strcmp(node, "state") == 0 &&
937         xendev->fe_state == XenbusStateConnected &&
938         xendev->be_state == XenbusStateConnected) {
939         xen_be_printf(xendev, 2, "re-trigger connected (frontend bug)\n");
940         xen_be_set_state(xendev, XenbusStateConnected);
941         fb->bug_trigger = 1; /* only once */
942     }
943 }
944
945 static void fb_event(struct XenDevice *xendev)
946 {
947     struct XenFB *xenfb = container_of(xendev, struct XenFB, c.xendev);
948
949     xenfb_handle_events(xenfb);
950     xen_be_send_notify(&xenfb->c.xendev);
951 }
952
953 /* -------------------------------------------------------------------- */
954
955 struct XenDevOps xen_kbdmouse_ops = {
956     .size       = sizeof(struct XenInput),
957     .init       = input_init,
958     .connect    = input_connect,
959     .disconnect = input_disconnect,
960     .event      = input_event,
961 };
962
963 struct XenDevOps xen_framebuffer_ops = {
964     .size       = sizeof(struct XenFB),
965     .init       = fb_init,
966     .connect    = fb_connect,
967     .disconnect = fb_disconnect,
968     .event      = fb_event,
969     .frontend_changed = fb_frontend_changed,
970 };
971
972 /*
973  * FIXME/TODO: Kill this.
974  * Temporary needed while DisplayState reorganization is in flight.
975  */
976 void xen_init_display(int domid)
977 {
978     struct XenDevice *xfb, *xin;
979     struct XenFB *fb;
980     struct XenInput *in;
981     int i = 0;
982
983 wait_more:
984     i++;
985     main_loop_wait(true);
986     xfb = xen_be_find_xendev("vfb", domid, 0);
987     xin = xen_be_find_xendev("vkbd", domid, 0);
988     if (!xfb || !xin) {
989         if (i < 256) {
990             usleep(10000);
991             goto wait_more;
992         }
993         xen_be_printf(NULL, 1, "displaystate setup failed\n");
994         return;
995     }
996
997     /* vfb */
998     fb = container_of(xfb, struct XenFB, c.xendev);
999     fb->c.ds = graphic_console_init(xenfb_update,
1000                                     xenfb_invalidate,
1001                                     NULL,
1002                                     NULL,
1003                                     fb);
1004     fb->have_console = 1;
1005
1006     /* vkbd */
1007     in = container_of(xin, struct XenInput, c.xendev);
1008     in->c.ds = fb->c.ds;
1009
1010     /* retry ->init() */
1011     xen_be_check_state(xin);
1012     xen_be_check_state(xfb);
1013 }