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