Statistics
| Branch: | Revision:

root / hw / display / xenfb.c @ 61fcb628

History | View | Annotate | Download (29.6 kB)

1
/*
2
 *  xen paravirt framebuffer backend
3
 *
4
 *  Copyright IBM, Corp. 2005-2006
5
 *  Copyright Red Hat, Inc. 2006-2008
6
 *
7
 *  Authors:
8
 *       Anthony Liguori <aliguori@us.ibm.com>,
9
 *       Markus Armbruster <armbru@redhat.com>,
10
 *       Daniel P. Berrange <berrange@redhat.com>,
11
 *       Pat Campbell <plc@novell.com>,
12
 *       Gerd Hoffmann <kraxel@redhat.com>
13
 *
14
 *  This program is free software; you can redistribute it and/or modify
15
 *  it under the terms of the GNU General Public License as published by
16
 *  the Free Software Foundation; under version 2 of the License.
17
 *
18
 *  This program is distributed in the hope that it will be useful,
19
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 *  GNU General Public License for more details.
22
 *
23
 *  You should have received a copy of the GNU General Public License along
24
 *  with this program; if not, see <http://www.gnu.org/licenses/>.
25
 */
26

    
27
#include <stdarg.h>
28
#include <stdlib.h>
29
#include <sys/types.h>
30
#include <fcntl.h>
31
#include <unistd.h>
32
#include <sys/mman.h>
33
#include <errno.h>
34
#include <stdio.h>
35
#include <string.h>
36
#include <time.h>
37

    
38
#include "hw/hw.h"
39
#include "ui/console.h"
40
#include "sysemu/char.h"
41
#include "hw/xen/xen_backend.h"
42

    
43
#include <xen/event_channel.h>
44
#include <xen/io/fbif.h>
45
#include <xen/io/kbdif.h>
46
#include <xen/io/protocols.h>
47

    
48
#ifndef BTN_LEFT
49
#define BTN_LEFT 0x110 /* from <linux/input.h> */
50
#endif
51

    
52
/* -------------------------------------------------------------------- */
53

    
54
struct common {
55
    struct XenDevice  xendev;  /* must be first */
56
    void              *page;
57
    QemuConsole       *con;
58
};
59

    
60
struct XenInput {
61
    struct common c;
62
    int abs_pointer_wanted; /* Whether guest supports absolute pointer */
63
    int button_state;       /* Last seen pointer button state */
64
    int extended;
65
    QEMUPutMouseEntry *qmouse;
66
};
67

    
68
#define UP_QUEUE 8
69

    
70
struct XenFB {
71
    struct common     c;
72
    size_t            fb_len;
73
    int               row_stride;
74
    int               depth;
75
    int               width;
76
    int               height;
77
    int               offset;
78
    void              *pixels;
79
    int               fbpages;
80
    int               feature_update;
81
    int               bug_trigger;
82
    int               have_console;
83
    int               do_resize;
84

    
85
    struct {
86
        int x,y,w,h;
87
    } up_rects[UP_QUEUE];
88
    int               up_count;
89
    int               up_fullscreen;
90
};
91

    
92
/* -------------------------------------------------------------------- */
93

    
94
static int common_bind(struct common *c)
95
{
96
    int mfn;
97

    
98
    if (xenstore_read_fe_int(&c->xendev, "page-ref", &mfn) == -1)
99
        return -1;
100
    if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1)
101
        return -1;
102

    
103
    c->page = xc_map_foreign_range(xen_xc, c->xendev.dom,
104
                                   XC_PAGE_SIZE,
105
                                   PROT_READ | PROT_WRITE, mfn);
106
    if (c->page == NULL)
107
        return -1;
108

    
109
    xen_be_bind_evtchn(&c->xendev);
110
    xen_be_printf(&c->xendev, 1, "ring mfn %d, remote-port %d, local-port %d\n",
111
                  mfn, c->xendev.remote_port, c->xendev.local_port);
112

    
113
    return 0;
114
}
115

    
116
static void common_unbind(struct common *c)
117
{
118
    xen_be_unbind_evtchn(&c->xendev);
119
    if (c->page) {
120
        munmap(c->page, XC_PAGE_SIZE);
121
        c->page = NULL;
122
    }
123
}
124

    
125
/* -------------------------------------------------------------------- */
126

    
127
#if 0
128
/*
129
 * These two tables are not needed any more, but left in here
130
 * intentionally as documentation, to show how scancode2linux[]
131
 * was generated.
132
 *
133
 * Tables to map from scancode to Linux input layer keycode.
134
 * Scancodes are hardware-specific.  These maps assumes a
135
 * standard AT or PS/2 keyboard which is what QEMU feeds us.
136
 */
137
const unsigned char atkbd_set2_keycode[512] = {
138

139
     0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
140
     0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
141
     0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
142
     0, 49, 48, 35, 34, 21,  7,184,  0,  0, 50, 36, 22,  8,  9,185,
143
     0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
144
     0, 89, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0, 85,
145
     0, 86, 91, 90, 92,  0, 14, 94,  0, 79,124, 75, 71,121,  0,  0,
146
    82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
147

148
      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
149
    217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
150
    173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
151
    159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
152
    157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
153
    226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
154
      0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
155
    110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
156

157
};
158

159
const unsigned char atkbd_unxlate_table[128] = {
160

161
      0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
162
     21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
163
     35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
164
     50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
165
     11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
166
    114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
167
     71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
168
     19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
169

170
};
171
#endif
172

    
173
/*
174
 * for (i = 0; i < 128; i++) {
175
 *     scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
176
 *     scancode2linux[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
177
 * }
178
 */
179
static const unsigned char scancode2linux[512] = {
180
      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
181
     16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
182
     32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
183
     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
184
     64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
185
     80, 81, 82, 83, 99,  0, 86, 87, 88,117,  0,  0, 95,183,184,185,
186
      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
187
     93,  0,  0, 89,  0,  0, 85, 91, 90, 92,  0, 94,  0,124,121,  0,
188

    
189
      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
190
    165,  0,  0,  0,  0,  0,  0,  0,  0,163,  0,  0, 96, 97,  0,  0,
191
    113,140,164,  0,166,  0,  0,  0,  0,  0,255,  0,  0,  0,114,  0,
192
    115,  0,150,  0,  0, 98,255, 99,100,  0,  0,  0,  0,  0,  0,  0,
193
      0,  0,  0,  0,  0,119,119,102,103,104,  0,105,112,106,118,107,
194
    108,109,110,111,  0,  0,  0,  0,  0,  0,  0,125,126,127,116,142,
195
      0,  0,  0,143,  0,217,156,173,128,159,158,157,155,226,  0,112,
196
      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
197
};
198

    
199
/* Send an event to the keyboard frontend driver */
200
static int xenfb_kbd_event(struct XenInput *xenfb,
201
                           union xenkbd_in_event *event)
202
{
203
    struct xenkbd_page *page = xenfb->c.page;
204
    uint32_t prod;
205

    
206
    if (xenfb->c.xendev.be_state != XenbusStateConnected)
207
        return 0;
208
    if (!page)
209
        return 0;
210

    
211
    prod = page->in_prod;
212
    if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
213
        errno = EAGAIN;
214
        return -1;
215
    }
216

    
217
    xen_mb();                /* ensure ring space available */
218
    XENKBD_IN_RING_REF(page, prod) = *event;
219
    xen_wmb();                /* ensure ring contents visible */
220
    page->in_prod = prod + 1;
221
    return xen_be_send_notify(&xenfb->c.xendev);
222
}
223

    
224
/* Send a keyboard (or mouse button) event */
225
static int xenfb_send_key(struct XenInput *xenfb, bool down, int keycode)
226
{
227
    union xenkbd_in_event event;
228

    
229
    memset(&event, 0, XENKBD_IN_EVENT_SIZE);
230
    event.type = XENKBD_TYPE_KEY;
231
    event.key.pressed = down ? 1 : 0;
232
    event.key.keycode = keycode;
233

    
234
    return xenfb_kbd_event(xenfb, &event);
235
}
236

    
237
/* Send a relative mouse movement event */
238
static int xenfb_send_motion(struct XenInput *xenfb,
239
                             int rel_x, int rel_y, int rel_z)
240
{
241
    union xenkbd_in_event event;
242

    
243
    memset(&event, 0, XENKBD_IN_EVENT_SIZE);
244
    event.type = XENKBD_TYPE_MOTION;
245
    event.motion.rel_x = rel_x;
246
    event.motion.rel_y = rel_y;
247
#if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030207
248
    event.motion.rel_z = rel_z;
249
#endif
250

    
251
    return xenfb_kbd_event(xenfb, &event);
252
}
253

    
254
/* Send an absolute mouse movement event */
255
static int xenfb_send_position(struct XenInput *xenfb,
256
                               int abs_x, int abs_y, int z)
257
{
258
    union xenkbd_in_event event;
259

    
260
    memset(&event, 0, XENKBD_IN_EVENT_SIZE);
261
    event.type = XENKBD_TYPE_POS;
262
    event.pos.abs_x = abs_x;
263
    event.pos.abs_y = abs_y;
264
#if __XEN_LATEST_INTERFACE_VERSION__ == 0x00030207
265
    event.pos.abs_z = z;
266
#endif
267
#if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030208
268
    event.pos.rel_z = z;
269
#endif
270

    
271
    return xenfb_kbd_event(xenfb, &event);
272
}
273

    
274
/*
275
 * Send a key event from the client to the guest OS
276
 * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
277
 * We have to turn this into a Linux Input layer keycode.
278
 *
279
 * Extra complexity from the fact that with extended scancodes
280
 * (like those produced by arrow keys) this method gets called
281
 * twice, but we only want to send a single event. So we have to
282
 * track the '0xe0' scancode state & collapse the extended keys
283
 * as needed.
284
 *
285
 * Wish we could just send scancodes straight to the guest which
286
 * already has code for dealing with this...
287
 */
288
static void xenfb_key_event(void *opaque, int scancode)
289
{
290
    struct XenInput *xenfb = opaque;
291
    int down = 1;
292

    
293
    if (scancode == 0xe0) {
294
        xenfb->extended = 1;
295
        return;
296
    } else if (scancode & 0x80) {
297
        scancode &= 0x7f;
298
        down = 0;
299
    }
300
    if (xenfb->extended) {
301
        scancode |= 0x80;
302
        xenfb->extended = 0;
303
    }
304
    xenfb_send_key(xenfb, down, scancode2linux[scancode]);
305
}
306

    
307
/*
308
 * Send a mouse event from the client to the guest OS
309
 *
310
 * The QEMU mouse can be in either relative, or absolute mode.
311
 * Movement is sent separately from button state, which has to
312
 * be encoded as virtual key events. We also don't actually get
313
 * given any button up/down events, so have to track changes in
314
 * the button state.
315
 */
316
static void xenfb_mouse_event(void *opaque,
317
                              int dx, int dy, int dz, int button_state)
318
{
319
    struct XenInput *xenfb = opaque;
320
    DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
321
    int dw = surface_width(surface);
322
    int dh = surface_height(surface);
323
    int i;
324

    
325
    if (xenfb->abs_pointer_wanted)
326
        xenfb_send_position(xenfb,
327
                            dx * (dw - 1) / 0x7fff,
328
                            dy * (dh - 1) / 0x7fff,
329
                            dz);
330
    else
331
        xenfb_send_motion(xenfb, dx, dy, dz);
332

    
333
    for (i = 0 ; i < 8 ; i++) {
334
        int lastDown = xenfb->button_state & (1 << i);
335
        int down = button_state & (1 << i);
336
        if (down == lastDown)
337
            continue;
338

    
339
        if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
340
            return;
341
    }
342
    xenfb->button_state = button_state;
343
}
344

    
345
static int input_init(struct XenDevice *xendev)
346
{
347
    xenstore_write_be_int(xendev, "feature-abs-pointer", 1);
348
    return 0;
349
}
350

    
351
static int input_initialise(struct XenDevice *xendev)
352
{
353
    struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
354
    int rc;
355

    
356
    if (!in->c.con) {
357
        xen_be_printf(xendev, 1, "ds not set (yet)\n");
358
        return -1;
359
    }
360

    
361
    rc = common_bind(&in->c);
362
    if (rc != 0)
363
        return rc;
364

    
365
    qemu_add_kbd_event_handler(xenfb_key_event, in);
366
    return 0;
367
}
368

    
369
static void input_connected(struct XenDevice *xendev)
370
{
371
    struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
372

    
373
    if (xenstore_read_fe_int(xendev, "request-abs-pointer",
374
                             &in->abs_pointer_wanted) == -1) {
375
        in->abs_pointer_wanted = 0;
376
    }
377

    
378
    if (in->qmouse) {
379
        qemu_remove_mouse_event_handler(in->qmouse);
380
    }
381
    in->qmouse = qemu_add_mouse_event_handler(xenfb_mouse_event, in,
382
                                              in->abs_pointer_wanted,
383
                                              "Xen PVFB Mouse");
384
}
385

    
386
static void input_disconnect(struct XenDevice *xendev)
387
{
388
    struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
389

    
390
    if (in->qmouse) {
391
        qemu_remove_mouse_event_handler(in->qmouse);
392
        in->qmouse = NULL;
393
    }
394
    qemu_add_kbd_event_handler(NULL, NULL);
395
    common_unbind(&in->c);
396
}
397

    
398
static void input_event(struct XenDevice *xendev)
399
{
400
    struct XenInput *xenfb = container_of(xendev, struct XenInput, c.xendev);
401
    struct xenkbd_page *page = xenfb->c.page;
402

    
403
    /* We don't understand any keyboard events, so just ignore them. */
404
    if (page->out_prod == page->out_cons)
405
        return;
406
    page->out_cons = page->out_prod;
407
    xen_be_send_notify(&xenfb->c.xendev);
408
}
409

    
410
/* -------------------------------------------------------------------- */
411

    
412
static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
413
{
414
    uint32_t *src32 = src;
415
    uint64_t *src64 = src;
416
    int i;
417

    
418
    for (i = 0; i < count; i++)
419
        dst[i] = (mode == 32) ? src32[i] : src64[i];
420
}
421

    
422
static int xenfb_map_fb(struct XenFB *xenfb)
423
{
424
    struct xenfb_page *page = xenfb->c.page;
425
    char *protocol = xenfb->c.xendev.protocol;
426
    int n_fbdirs;
427
    unsigned long *pgmfns = NULL;
428
    unsigned long *fbmfns = NULL;
429
    void *map, *pd;
430
    int mode, ret = -1;
431

    
432
    /* default to native */
433
    pd = page->pd;
434
    mode = sizeof(unsigned long) * 8;
435

    
436
    if (!protocol) {
437
        /*
438
         * Undefined protocol, some guesswork needed.
439
         *
440
         * Old frontends which don't set the protocol use
441
         * one page directory only, thus pd[1] must be zero.
442
         * pd[1] of the 32bit struct layout and the lower
443
         * 32 bits of pd[0] of the 64bit struct layout have
444
         * the same location, so we can check that ...
445
         */
446
        uint32_t *ptr32 = NULL;
447
        uint32_t *ptr64 = NULL;
448
#if defined(__i386__)
449
        ptr32 = (void*)page->pd;
450
        ptr64 = ((void*)page->pd) + 4;
451
#elif defined(__x86_64__)
452
        ptr32 = ((void*)page->pd) - 4;
453
        ptr64 = (void*)page->pd;
454
#endif
455
        if (ptr32) {
456
            if (ptr32[1] == 0) {
457
                mode = 32;
458
                pd   = ptr32;
459
            } else {
460
                mode = 64;
461
                pd   = ptr64;
462
            }
463
        }
464
#if defined(__x86_64__)
465
    } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) {
466
        /* 64bit dom0, 32bit domU */
467
        mode = 32;
468
        pd   = ((void*)page->pd) - 4;
469
#elif defined(__i386__)
470
    } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_64) == 0) {
471
        /* 32bit dom0, 64bit domU */
472
        mode = 64;
473
        pd   = ((void*)page->pd) + 4;
474
#endif
475
    }
476

    
477
    if (xenfb->pixels) {
478
        munmap(xenfb->pixels, xenfb->fbpages * XC_PAGE_SIZE);
479
        xenfb->pixels = NULL;
480
    }
481

    
482
    xenfb->fbpages = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
483
    n_fbdirs = xenfb->fbpages * mode / 8;
484
    n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
485

    
486
    pgmfns = g_malloc0(sizeof(unsigned long) * n_fbdirs);
487
    fbmfns = g_malloc0(sizeof(unsigned long) * xenfb->fbpages);
488

    
489
    xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
490
    map = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
491
                               PROT_READ, pgmfns, n_fbdirs);
492
    if (map == NULL)
493
        goto out;
494
    xenfb_copy_mfns(mode, xenfb->fbpages, fbmfns, map);
495
    munmap(map, n_fbdirs * XC_PAGE_SIZE);
496

    
497
    xenfb->pixels = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
498
                                         PROT_READ | PROT_WRITE, fbmfns, xenfb->fbpages);
499
    if (xenfb->pixels == NULL)
500
        goto out;
501

    
502
    ret = 0; /* all is fine */
503

    
504
out:
505
    g_free(pgmfns);
506
    g_free(fbmfns);
507
    return ret;
508
}
509

    
510
static int xenfb_configure_fb(struct XenFB *xenfb, size_t fb_len_lim,
511
                              int width, int height, int depth,
512
                              size_t fb_len, int offset, int row_stride)
513
{
514
    size_t mfn_sz = sizeof(*((struct xenfb_page *)0)->pd);
515
    size_t pd_len = sizeof(((struct xenfb_page *)0)->pd) / mfn_sz;
516
    size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz;
517
    size_t fb_len_max = fb_pages * XC_PAGE_SIZE;
518
    int max_width, max_height;
519

    
520
    if (fb_len_lim > fb_len_max) {
521
        xen_be_printf(&xenfb->c.xendev, 0, "fb size limit %zu exceeds %zu, corrected\n",
522
                      fb_len_lim, fb_len_max);
523
        fb_len_lim = fb_len_max;
524
    }
525
    if (fb_len_lim && fb_len > fb_len_lim) {
526
        xen_be_printf(&xenfb->c.xendev, 0, "frontend fb size %zu limited to %zu\n",
527
                      fb_len, fb_len_lim);
528
        fb_len = fb_len_lim;
529
    }
530
    if (depth != 8 && depth != 16 && depth != 24 && depth != 32) {
531
        xen_be_printf(&xenfb->c.xendev, 0, "can't handle frontend fb depth %d\n",
532
                      depth);
533
        return -1;
534
    }
535
    if (row_stride <= 0 || row_stride > fb_len) {
536
        xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend stride %d\n", row_stride);
537
        return -1;
538
    }
539
    max_width = row_stride / (depth / 8);
540
    if (width < 0 || width > max_width) {
541
        xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend width %d limited to %d\n",
542
                      width, max_width);
543
        width = max_width;
544
    }
545
    if (offset < 0 || offset >= fb_len) {
546
        xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend offset %d (max %zu)\n",
547
                      offset, fb_len - 1);
548
        return -1;
549
    }
550
    max_height = (fb_len - offset) / row_stride;
551
    if (height < 0 || height > max_height) {
552
        xen_be_printf(&xenfb->c.xendev, 0, "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_be_printf(&xenfb->c.xendev, 1, "framebuffer %dx%dx%d offset %d stride %d\n",
565
                  width, height, depth, offset, row_stride);
566
    return 0;
567
}
568

    
569
/* A convenient function for munging pixels between different depths */
570
#define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB)                        \
571
    for (line = y ; line < (y+h) ; line++) {                                \
572
        SRC_T *src = (SRC_T *)(xenfb->pixels                                \
573
                               + xenfb->offset                                \
574
                               + (line * xenfb->row_stride)                \
575
                               + (x * xenfb->depth / 8));                \
576
        DST_T *dst = (DST_T *)(data                                        \
577
                               + (line * linesize)                        \
578
                               + (x * bpp / 8));                        \
579
        int col;                                                        \
580
        const int RSS = 32 - (RSB + GSB + BSB);                                \
581
        const int GSS = 32 - (GSB + BSB);                                \
582
        const int BSS = 32 - (BSB);                                        \
583
        const uint32_t RSM = (~0U) << (32 - RSB);                        \
584
        const uint32_t GSM = (~0U) << (32 - GSB);                        \
585
        const uint32_t BSM = (~0U) << (32 - BSB);                        \
586
        const int RDS = 32 - (RDB + GDB + BDB);                                \
587
        const int GDS = 32 - (GDB + BDB);                                \
588
        const int BDS = 32 - (BDB);                                        \
589
        const uint32_t RDM = (~0U) << (32 - RDB);                        \
590
        const uint32_t GDM = (~0U) << (32 - GDB);                        \
591
        const uint32_t BDM = (~0U) << (32 - BDB);                        \
592
        for (col = x ; col < (x+w) ; col++) {                                \
593
            uint32_t spix = *src;                                        \
594
            *dst = (((spix << RSS) & RSM & RDM) >> RDS) |                \
595
                (((spix << GSS) & GSM & GDM) >> GDS) |                        \
596
                (((spix << BSS) & BSM & BDM) >> BDS);                        \
597
            src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8);        \
598
            dst = (DST_T *) ((unsigned long) dst + bpp / 8);                \
599
        }                                                                \
600
    }
601

    
602

    
603
/*
604
 * This copies data from the guest framebuffer region, into QEMU's
605
 * displaysurface. qemu uses 16 or 32 bpp.  In case the pv framebuffer
606
 * uses something else we must convert and copy, otherwise we can
607
 * supply the buffer directly and no thing here.
608
 */
609
static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
610
{
611
    DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
612
    int line, oops = 0;
613
    int bpp = surface_bits_per_pixel(surface);
614
    int linesize = surface_stride(surface);
615
    uint8_t *data = surface_data(surface);
616

    
617
    if (!is_buffer_shared(surface)) {
618
        switch (xenfb->depth) {
619
        case 8:
620
            if (bpp == 16) {
621
                BLT(uint8_t, uint16_t,   3, 3, 2,   5, 6, 5);
622
            } else if (bpp == 32) {
623
                BLT(uint8_t, uint32_t,   3, 3, 2,   8, 8, 8);
624
            } else {
625
                oops = 1;
626
            }
627
            break;
628
        case 24:
629
            if (bpp == 16) {
630
                BLT(uint32_t, uint16_t,  8, 8, 8,   5, 6, 5);
631
            } else if (bpp == 32) {
632
                BLT(uint32_t, uint32_t,  8, 8, 8,   8, 8, 8);
633
            } else {
634
                oops = 1;
635
            }
636
            break;
637
        default:
638
            oops = 1;
639
        }
640
    }
641
    if (oops) /* should not happen */
642
        xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n",
643
                      __FUNCTION__, xenfb->depth, bpp);
644

    
645
    dpy_gfx_update(xenfb->c.con, x, y, w, h);
646
}
647

    
648
#ifdef XENFB_TYPE_REFRESH_PERIOD
649
static int xenfb_queue_full(struct XenFB *xenfb)
650
{
651
    struct xenfb_page *page = xenfb->c.page;
652
    uint32_t cons, prod;
653

    
654
    if (!page)
655
        return 1;
656

    
657
    prod = page->in_prod;
658
    cons = page->in_cons;
659
    return prod - cons == XENFB_IN_RING_LEN;
660
}
661

    
662
static void xenfb_send_event(struct XenFB *xenfb, union xenfb_in_event *event)
663
{
664
    uint32_t prod;
665
    struct xenfb_page *page = xenfb->c.page;
666

    
667
    prod = page->in_prod;
668
    /* caller ensures !xenfb_queue_full() */
669
    xen_mb();                   /* ensure ring space available */
670
    XENFB_IN_RING_REF(page, prod) = *event;
671
    xen_wmb();                  /* ensure ring contents visible */
672
    page->in_prod = prod + 1;
673

    
674
    xen_be_send_notify(&xenfb->c.xendev);
675
}
676

    
677
static void xenfb_send_refresh_period(struct XenFB *xenfb, int period)
678
{
679
    union xenfb_in_event event;
680

    
681
    memset(&event, 0, sizeof(event));
682
    event.type = XENFB_TYPE_REFRESH_PERIOD;
683
    event.refresh_period.period = period;
684
    xenfb_send_event(xenfb, &event);
685
}
686
#endif
687

    
688
/*
689
 * Periodic update of display.
690
 * Also transmit the refresh interval to the frontend.
691
 *
692
 * Never ever do any qemu display operations
693
 * (resize, screen update) outside this function.
694
 * Our screen might be inactive.  When asked for
695
 * an update we know it is active.
696
 */
697
static void xenfb_update(void *opaque)
698
{
699
    struct XenFB *xenfb = opaque;
700
    DisplaySurface *surface;
701
    int i;
702

    
703
    if (xenfb->c.xendev.be_state != XenbusStateConnected)
704
        return;
705

    
706
    if (!xenfb->feature_update) {
707
        /* we don't get update notifications, thus use the
708
         * sledge hammer approach ... */
709
        xenfb->up_fullscreen = 1;
710
    }
711

    
712
    /* resize if needed */
713
    if (xenfb->do_resize) {
714
        xenfb->do_resize = 0;
715
        switch (xenfb->depth) {
716
        case 16:
717
        case 32:
718
            /* console.c supported depth -> buffer can be used directly */
719
            surface = qemu_create_displaysurface_from
720
                (xenfb->width, xenfb->height, xenfb->depth,
721
                 xenfb->row_stride, xenfb->pixels + xenfb->offset,
722
                 false);
723
            break;
724
        default:
725
            /* we must convert stuff */
726
            surface = qemu_create_displaysurface(xenfb->width, xenfb->height);
727
            break;
728
        }
729
        dpy_gfx_replace_surface(xenfb->c.con, surface);
730
        xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n",
731
                      xenfb->width, xenfb->height, xenfb->depth,
732
                      is_buffer_shared(surface) ? " (shared)" : "");
733
        xenfb->up_fullscreen = 1;
734
    }
735

    
736
    /* run queued updates */
737
    if (xenfb->up_fullscreen) {
738
        xen_be_printf(&xenfb->c.xendev, 3, "update: fullscreen\n");
739
        xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
740
    } else if (xenfb->up_count) {
741
        xen_be_printf(&xenfb->c.xendev, 3, "update: %d rects\n", xenfb->up_count);
742
        for (i = 0; i < xenfb->up_count; i++)
743
            xenfb_guest_copy(xenfb,
744
                             xenfb->up_rects[i].x,
745
                             xenfb->up_rects[i].y,
746
                             xenfb->up_rects[i].w,
747
                             xenfb->up_rects[i].h);
748
    } else {
749
        xen_be_printf(&xenfb->c.xendev, 3, "update: nothing\n");
750
    }
751
    xenfb->up_count = 0;
752
    xenfb->up_fullscreen = 0;
753
}
754

    
755
static void xenfb_update_interval(void *opaque, uint64_t interval)
756
{
757
    struct XenFB *xenfb = opaque;
758

    
759
    if (xenfb->feature_update) {
760
#ifdef XENFB_TYPE_REFRESH_PERIOD
761
        if (xenfb_queue_full(xenfb)) {
762
            return;
763
        }
764
        xenfb_send_refresh_period(xenfb, interval);
765
#endif
766
    }
767
}
768

    
769
/* QEMU display state changed, so refresh the framebuffer copy */
770
static void xenfb_invalidate(void *opaque)
771
{
772
    struct XenFB *xenfb = opaque;
773
    xenfb->up_fullscreen = 1;
774
}
775

    
776
static void xenfb_handle_events(struct XenFB *xenfb)
777
{
778
    uint32_t prod, cons;
779
    struct xenfb_page *page = xenfb->c.page;
780

    
781
    prod = page->out_prod;
782
    if (prod == page->out_cons)
783
        return;
784
    xen_rmb();                /* ensure we see ring contents up to prod */
785
    for (cons = page->out_cons; cons != prod; cons++) {
786
        union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
787
        int x, y, w, h;
788

    
789
        switch (event->type) {
790
        case XENFB_TYPE_UPDATE:
791
            if (xenfb->up_count == UP_QUEUE)
792
                xenfb->up_fullscreen = 1;
793
            if (xenfb->up_fullscreen)
794
                break;
795
            x = MAX(event->update.x, 0);
796
            y = MAX(event->update.y, 0);
797
            w = MIN(event->update.width, xenfb->width - x);
798
            h = MIN(event->update.height, xenfb->height - y);
799
            if (w < 0 || h < 0) {
800
                xen_be_printf(&xenfb->c.xendev, 1, "bogus update ignored\n");
801
                break;
802
            }
803
            if (x != event->update.x ||
804
                y != event->update.y ||
805
                w != event->update.width ||
806
                h != event->update.height) {
807
                xen_be_printf(&xenfb->c.xendev, 1, "bogus update clipped\n");
808
            }
809
            if (w == xenfb->width && h > xenfb->height / 2) {
810
                /* scroll detector: updated more than 50% of the lines,
811
                 * don't bother keeping track of the rectangles then */
812
                xenfb->up_fullscreen = 1;
813
            } else {
814
                xenfb->up_rects[xenfb->up_count].x = x;
815
                xenfb->up_rects[xenfb->up_count].y = y;
816
                xenfb->up_rects[xenfb->up_count].w = w;
817
                xenfb->up_rects[xenfb->up_count].h = h;
818
                xenfb->up_count++;
819
            }
820
            break;
821
#ifdef XENFB_TYPE_RESIZE
822
        case XENFB_TYPE_RESIZE:
823
            if (xenfb_configure_fb(xenfb, xenfb->fb_len,
824
                                   event->resize.width,
825
                                   event->resize.height,
826
                                   event->resize.depth,
827
                                   xenfb->fb_len,
828
                                   event->resize.offset,
829
                                   event->resize.stride) < 0)
830
                break;
831
            xenfb_invalidate(xenfb);
832
            break;
833
#endif
834
        }
835
    }
836
    xen_mb();                /* ensure we're done with ring contents */
837
    page->out_cons = cons;
838
}
839

    
840
static int fb_init(struct XenDevice *xendev)
841
{
842
#ifdef XENFB_TYPE_RESIZE
843
    xenstore_write_be_int(xendev, "feature-resize", 1);
844
#endif
845
    return 0;
846
}
847

    
848
static int fb_initialise(struct XenDevice *xendev)
849
{
850
    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
851
    struct xenfb_page *fb_page;
852
    int videoram;
853
    int rc;
854

    
855
    if (xenstore_read_fe_int(xendev, "videoram", &videoram) == -1)
856
        videoram = 0;
857

    
858
    rc = common_bind(&fb->c);
859
    if (rc != 0)
860
        return rc;
861

    
862
    fb_page = fb->c.page;
863
    rc = xenfb_configure_fb(fb, videoram * 1024 * 1024U,
864
                            fb_page->width, fb_page->height, fb_page->depth,
865
                            fb_page->mem_length, 0, fb_page->line_length);
866
    if (rc != 0)
867
        return rc;
868

    
869
    rc = xenfb_map_fb(fb);
870
    if (rc != 0)
871
        return rc;
872

    
873
#if 0  /* handled in xen_init_display() for now */
874
    if (!fb->have_console) {
875
        fb->c.ds = graphic_console_init(xenfb_update,
876
                                        xenfb_invalidate,
877
                                        NULL,
878
                                        NULL,
879
                                        fb);
880
        fb->have_console = 1;
881
    }
882
#endif
883

    
884
    if (xenstore_read_fe_int(xendev, "feature-update", &fb->feature_update) == -1)
885
        fb->feature_update = 0;
886
    if (fb->feature_update)
887
        xenstore_write_be_int(xendev, "request-update", 1);
888

    
889
    xen_be_printf(xendev, 1, "feature-update=%d, videoram=%d\n",
890
                  fb->feature_update, videoram);
891
    return 0;
892
}
893

    
894
static void fb_disconnect(struct XenDevice *xendev)
895
{
896
    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
897

    
898
    /*
899
     * FIXME: qemu can't un-init gfx display (yet?).
900
     *   Replacing the framebuffer with anonymous shared memory
901
     *   instead.  This releases the guest pages and keeps qemu happy.
902
     */
903
    fb->pixels = mmap(fb->pixels, fb->fbpages * XC_PAGE_SIZE,
904
                      PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON,
905
                      -1, 0);
906
    common_unbind(&fb->c);
907
    fb->feature_update = 0;
908
    fb->bug_trigger    = 0;
909
}
910

    
911
static void fb_frontend_changed(struct XenDevice *xendev, const char *node)
912
{
913
    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
914

    
915
    /*
916
     * Set state to Connected *again* once the frontend switched
917
     * to connected.  We must trigger the watch a second time to
918
     * workaround a frontend bug.
919
     */
920
    if (fb->bug_trigger == 0 && strcmp(node, "state") == 0 &&
921
        xendev->fe_state == XenbusStateConnected &&
922
        xendev->be_state == XenbusStateConnected) {
923
        xen_be_printf(xendev, 2, "re-trigger connected (frontend bug)\n");
924
        xen_be_set_state(xendev, XenbusStateConnected);
925
        fb->bug_trigger = 1; /* only once */
926
    }
927
}
928

    
929
static void fb_event(struct XenDevice *xendev)
930
{
931
    struct XenFB *xenfb = container_of(xendev, struct XenFB, c.xendev);
932

    
933
    xenfb_handle_events(xenfb);
934
    xen_be_send_notify(&xenfb->c.xendev);
935
}
936

    
937
/* -------------------------------------------------------------------- */
938

    
939
struct XenDevOps xen_kbdmouse_ops = {
940
    .size       = sizeof(struct XenInput),
941
    .init       = input_init,
942
    .initialise = input_initialise,
943
    .connected  = input_connected,
944
    .disconnect = input_disconnect,
945
    .event      = input_event,
946
};
947

    
948
struct XenDevOps xen_framebuffer_ops = {
949
    .size       = sizeof(struct XenFB),
950
    .init       = fb_init,
951
    .initialise = fb_initialise,
952
    .disconnect = fb_disconnect,
953
    .event      = fb_event,
954
    .frontend_changed = fb_frontend_changed,
955
};
956

    
957
static const GraphicHwOps xenfb_ops = {
958
    .invalidate  = xenfb_invalidate,
959
    .gfx_update  = xenfb_update,
960
    .update_interval = xenfb_update_interval,
961
};
962

    
963
/*
964
 * FIXME/TODO: Kill this.
965
 * Temporary needed while DisplayState reorganization is in flight.
966
 */
967
void xen_init_display(int domid)
968
{
969
    struct XenDevice *xfb, *xin;
970
    struct XenFB *fb;
971
    struct XenInput *in;
972
    int i = 0;
973

    
974
wait_more:
975
    i++;
976
    main_loop_wait(true);
977
    xfb = xen_be_find_xendev("vfb", domid, 0);
978
    xin = xen_be_find_xendev("vkbd", domid, 0);
979
    if (!xfb || !xin) {
980
        if (i < 256) {
981
            usleep(10000);
982
            goto wait_more;
983
        }
984
        xen_be_printf(NULL, 1, "displaystate setup failed\n");
985
        return;
986
    }
987

    
988
    /* vfb */
989
    fb = container_of(xfb, struct XenFB, c.xendev);
990
    fb->c.con = graphic_console_init(NULL, &xenfb_ops, fb);
991
    fb->have_console = 1;
992

    
993
    /* vkbd */
994
    in = container_of(xin, struct XenInput, c.xendev);
995
    in->c.con = fb->c.con;
996

    
997
    /* retry ->init() */
998
    xen_be_check_state(xin);
999
    xen_be_check_state(xfb);
1000
}