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