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