Statistics
| Branch: | Revision:

root / hw / xenfb.c @ 7267c094

History | View | Annotate | Download (30.2 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 <xs.h>
39
#include <xenctrl.h>
40
#include <xen/event_channel.h>
41
#include <xen/io/xenbus.h>
42
#include <xen/io/fbif.h>
43
#include <xen/io/kbdif.h>
44
#include <xen/io/protocols.h>
45

    
46
#include "hw.h"
47
#include "console.h"
48
#include "qemu-char.h"
49
#include "xen_backend.h"
50

    
51
#ifndef BTN_LEFT
52
#define BTN_LEFT 0x110 /* from <linux/input.h> */
53
#endif
54

    
55
/* -------------------------------------------------------------------- */
56

    
57
struct common {
58
    struct XenDevice  xendev;  /* must be first */
59
    void              *page;
60
    DisplayState      *ds;
61
};
62

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

    
71
#define UP_QUEUE 8
72

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

    
89
    struct {
90
        int x,y,w,h;
91
    } up_rects[UP_QUEUE];
92
    int               up_count;
93
    int               up_fullscreen;
94
};
95

    
96
/* -------------------------------------------------------------------- */
97

    
98
static int common_bind(struct common *c)
99
{
100
    int mfn;
101

    
102
    if (xenstore_read_fe_int(&c->xendev, "page-ref", &mfn) == -1)
103
        return -1;
104
    if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1)
105
        return -1;
106

    
107
    c->page = xc_map_foreign_range(xen_xc, c->xendev.dom,
108
                                   XC_PAGE_SIZE,
109
                                   PROT_READ | PROT_WRITE, mfn);
110
    if (c->page == NULL)
111
        return -1;
112

    
113
    xen_be_bind_evtchn(&c->xendev);
114
    xen_be_printf(&c->xendev, 1, "ring mfn %d, remote-port %d, local-port %d\n",
115
                  mfn, c->xendev.remote_port, c->xendev.local_port);
116

    
117
    return 0;
118
}
119

    
120
static void common_unbind(struct common *c)
121
{
122
    xen_be_unbind_evtchn(&c->xendev);
123
    if (c->page) {
124
        munmap(c->page, XC_PAGE_SIZE);
125
        c->page = NULL;
126
    }
127
}
128

    
129
/* -------------------------------------------------------------------- */
130

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

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

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

161
};
162

163
const unsigned char atkbd_unxlate_table[128] = {
164

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

174
};
175
#endif
176

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

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

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

    
210
    if (xenfb->c.xendev.be_state != XenbusStateConnected)
211
        return 0;
212
    if (!page)
213
        return 0;
214

    
215
    prod = page->in_prod;
216
    if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
217
        errno = EAGAIN;
218
        return -1;
219
    }
220

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

    
228
/* Send a keyboard (or mouse button) event */
229
static int xenfb_send_key(struct XenInput *xenfb, bool down, int keycode)
230
{
231
    union xenkbd_in_event event;
232

    
233
    memset(&event, 0, XENKBD_IN_EVENT_SIZE);
234
    event.type = XENKBD_TYPE_KEY;
235
    event.key.pressed = down ? 1 : 0;
236
    event.key.keycode = keycode;
237

    
238
    return xenfb_kbd_event(xenfb, &event);
239
}
240

    
241
/* Send a relative mouse movement event */
242
static int xenfb_send_motion(struct XenInput *xenfb,
243
                             int rel_x, int rel_y, int rel_z)
244
{
245
    union xenkbd_in_event event;
246

    
247
    memset(&event, 0, XENKBD_IN_EVENT_SIZE);
248
    event.type = XENKBD_TYPE_MOTION;
249
    event.motion.rel_x = rel_x;
250
    event.motion.rel_y = rel_y;
251
#if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030207
252
    event.motion.rel_z = rel_z;
253
#endif
254

    
255
    return xenfb_kbd_event(xenfb, &event);
256
}
257

    
258
/* Send an absolute mouse movement event */
259
static int xenfb_send_position(struct XenInput *xenfb,
260
                               int abs_x, int abs_y, int z)
261
{
262
    union xenkbd_in_event event;
263

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

    
275
    return xenfb_kbd_event(xenfb, &event);
276
}
277

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

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

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

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

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

    
342
        if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
343
            return;
344
    }
345
    xenfb->button_state = button_state;
346
}
347

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

    
354
static int input_connect(struct XenDevice *xendev)
355
{
356
    struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
357
    int rc;
358

    
359
    if (xenstore_read_fe_int(xendev, "request-abs-pointer",
360
                             &in->abs_pointer_wanted) == -1)
361
        in->abs_pointer_wanted = 0;
362

    
363
    if (!in->c.ds) {
364
        char *vfb = xenstore_read_str(NULL, "device/vfb");
365
        if (vfb == NULL) {
366
            /* there is no vfb, run vkbd on its own */
367
            in->c.ds = get_displaystate();
368
        } else {
369
            g_free(vfb);
370
            xen_be_printf(xendev, 1, "ds not set (yet)\n");
371
            return -1;
372
        }
373
    }
374

    
375
    rc = common_bind(&in->c);
376
    if (rc != 0)
377
        return rc;
378

    
379
    qemu_add_kbd_event_handler(xenfb_key_event, in);
380
    in->qmouse = qemu_add_mouse_event_handler(xenfb_mouse_event, in,
381
                                              in->abs_pointer_wanted,
382
                                              "Xen PVFB Mouse");
383
    return 0;
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
    int line, oops = 0;
612
    int bpp = ds_get_bits_per_pixel(xenfb->c.ds);
613
    int linesize = ds_get_linesize(xenfb->c.ds);
614
    uint8_t *data = ds_get_data(xenfb->c.ds);
615

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

    
644
    dpy_update(xenfb->c.ds, x, y, w, h);
645
}
646

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

    
653
    if (!page)
654
        return 1;
655

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

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

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

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

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

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

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

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

    
704
    if (xenfb->feature_update) {
705
#ifdef XENFB_TYPE_REFRESH_PERIOD
706
        struct DisplayChangeListener *l;
707
        int period = 99999999;
708
        int idle = 1;
709

    
710
        if (xenfb_queue_full(xenfb))
711
            return;
712

    
713
        for (l = xenfb->c.ds->listeners; l != NULL; l = l->next) {
714
            if (l->idle)
715
                continue;
716
            idle = 0;
717
            if (!l->gui_timer_interval) {
718
                if (period > GUI_REFRESH_INTERVAL)
719
                    period = GUI_REFRESH_INTERVAL;
720
            } else {
721
                if (period > l->gui_timer_interval)
722
                    period = l->gui_timer_interval;
723
            }
724
        }
725
        if (idle)
726
            period = XENFB_NO_REFRESH;
727

    
728
        if (xenfb->refresh_period != period) {
729
            xenfb_send_refresh_period(xenfb, period);
730
            xenfb->refresh_period = period;
731
            xen_be_printf(&xenfb->c.xendev, 1, "refresh period: %d\n", period);
732
        }
733
#else
734
        ; /* nothing */
735
#endif
736
    } else {
737
        /* we don't get update notifications, thus use the
738
         * sledge hammer approach ... */
739
        xenfb->up_fullscreen = 1;
740
    }
741

    
742
    /* resize if needed */
743
    if (xenfb->do_resize) {
744
        xenfb->do_resize = 0;
745
        switch (xenfb->depth) {
746
        case 16:
747
        case 32:
748
            /* console.c supported depth -> buffer can be used directly */
749
            qemu_free_displaysurface(xenfb->c.ds);
750
            xenfb->c.ds->surface = qemu_create_displaysurface_from
751
                (xenfb->width, xenfb->height, xenfb->depth,
752
                 xenfb->row_stride, xenfb->pixels + xenfb->offset);
753
            break;
754
        default:
755
            /* we must convert stuff */
756
            qemu_resize_displaysurface(xenfb->c.ds, xenfb->width, xenfb->height);
757
            break;
758
        }
759
        xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n",
760
                      xenfb->width, xenfb->height, xenfb->depth,
761
                      is_buffer_shared(xenfb->c.ds->surface) ? " (shared)" : "");
762
        dpy_resize(xenfb->c.ds);
763
        xenfb->up_fullscreen = 1;
764
    }
765

    
766
    /* run queued updates */
767
    if (xenfb->up_fullscreen) {
768
        xen_be_printf(&xenfb->c.xendev, 3, "update: fullscreen\n");
769
        xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
770
    } else if (xenfb->up_count) {
771
        xen_be_printf(&xenfb->c.xendev, 3, "update: %d rects\n", xenfb->up_count);
772
        for (i = 0; i < xenfb->up_count; i++)
773
            xenfb_guest_copy(xenfb,
774
                             xenfb->up_rects[i].x,
775
                             xenfb->up_rects[i].y,
776
                             xenfb->up_rects[i].w,
777
                             xenfb->up_rects[i].h);
778
    } else {
779
        xen_be_printf(&xenfb->c.xendev, 3, "update: nothing\n");
780
    }
781
    xenfb->up_count = 0;
782
    xenfb->up_fullscreen = 0;
783
}
784

    
785
/* QEMU display state changed, so refresh the framebuffer copy */
786
static void xenfb_invalidate(void *opaque)
787
{
788
    struct XenFB *xenfb = opaque;
789
    xenfb->up_fullscreen = 1;
790
}
791

    
792
static void xenfb_handle_events(struct XenFB *xenfb)
793
{
794
    uint32_t prod, cons;
795
    struct xenfb_page *page = xenfb->c.page;
796

    
797
    prod = page->out_prod;
798
    if (prod == page->out_cons)
799
        return;
800
    xen_rmb();                /* ensure we see ring contents up to prod */
801
    for (cons = page->out_cons; cons != prod; cons++) {
802
        union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
803
        int x, y, w, h;
804

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

    
856
static int fb_init(struct XenDevice *xendev)
857
{
858
    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
859

    
860
    fb->refresh_period = -1;
861

    
862
#ifdef XENFB_TYPE_RESIZE
863
    xenstore_write_be_int(xendev, "feature-resize", 1);
864
#endif
865
    return 0;
866
}
867

    
868
static int fb_connect(struct XenDevice *xendev)
869
{
870
    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
871
    struct xenfb_page *fb_page;
872
    int videoram;
873
    int rc;
874

    
875
    if (xenstore_read_fe_int(xendev, "videoram", &videoram) == -1)
876
        videoram = 0;
877

    
878
    rc = common_bind(&fb->c);
879
    if (rc != 0)
880
        return rc;
881

    
882
    fb_page = fb->c.page;
883
    rc = xenfb_configure_fb(fb, videoram * 1024 * 1024U,
884
                            fb_page->width, fb_page->height, fb_page->depth,
885
                            fb_page->mem_length, 0, fb_page->line_length);
886
    if (rc != 0)
887
        return rc;
888

    
889
    rc = xenfb_map_fb(fb);
890
    if (rc != 0)
891
        return rc;
892

    
893
#if 0  /* handled in xen_init_display() for now */
894
    if (!fb->have_console) {
895
        fb->c.ds = graphic_console_init(xenfb_update,
896
                                        xenfb_invalidate,
897
                                        NULL,
898
                                        NULL,
899
                                        fb);
900
        fb->have_console = 1;
901
    }
902
#endif
903

    
904
    if (xenstore_read_fe_int(xendev, "feature-update", &fb->feature_update) == -1)
905
        fb->feature_update = 0;
906
    if (fb->feature_update)
907
        xenstore_write_be_int(xendev, "request-update", 1);
908

    
909
    xen_be_printf(xendev, 1, "feature-update=%d, videoram=%d\n",
910
                  fb->feature_update, videoram);
911
    return 0;
912
}
913

    
914
static void fb_disconnect(struct XenDevice *xendev)
915
{
916
    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
917

    
918
    /*
919
     * FIXME: qemu can't un-init gfx display (yet?).
920
     *   Replacing the framebuffer with anonymous shared memory
921
     *   instead.  This releases the guest pages and keeps qemu happy.
922
     */
923
    fb->pixels = mmap(fb->pixels, fb->fbpages * XC_PAGE_SIZE,
924
                      PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON,
925
                      -1, 0);
926
    common_unbind(&fb->c);
927
    fb->feature_update = 0;
928
    fb->bug_trigger    = 0;
929
}
930

    
931
static void fb_frontend_changed(struct XenDevice *xendev, const char *node)
932
{
933
    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
934

    
935
    /*
936
     * Set state to Connected *again* once the frontend switched
937
     * to connected.  We must trigger the watch a second time to
938
     * workaround a frontend bug.
939
     */
940
    if (fb->bug_trigger == 0 && strcmp(node, "state") == 0 &&
941
        xendev->fe_state == XenbusStateConnected &&
942
        xendev->be_state == XenbusStateConnected) {
943
        xen_be_printf(xendev, 2, "re-trigger connected (frontend bug)\n");
944
        xen_be_set_state(xendev, XenbusStateConnected);
945
        fb->bug_trigger = 1; /* only once */
946
    }
947
}
948

    
949
static void fb_event(struct XenDevice *xendev)
950
{
951
    struct XenFB *xenfb = container_of(xendev, struct XenFB, c.xendev);
952

    
953
    xenfb_handle_events(xenfb);
954
    xen_be_send_notify(&xenfb->c.xendev);
955
}
956

    
957
/* -------------------------------------------------------------------- */
958

    
959
struct XenDevOps xen_kbdmouse_ops = {
960
    .size       = sizeof(struct XenInput),
961
    .init       = input_init,
962
    .connect    = input_connect,
963
    .disconnect = input_disconnect,
964
    .event      = input_event,
965
};
966

    
967
struct XenDevOps xen_framebuffer_ops = {
968
    .size       = sizeof(struct XenFB),
969
    .init       = fb_init,
970
    .connect    = fb_connect,
971
    .disconnect = fb_disconnect,
972
    .event      = fb_event,
973
    .frontend_changed = fb_frontend_changed,
974
};
975

    
976
/*
977
 * FIXME/TODO: Kill this.
978
 * Temporary needed while DisplayState reorganization is in flight.
979
 */
980
void xen_init_display(int domid)
981
{
982
    struct XenDevice *xfb, *xin;
983
    struct XenFB *fb;
984
    struct XenInput *in;
985
    int i = 0;
986

    
987
wait_more:
988
    i++;
989
    main_loop_wait(true);
990
    xfb = xen_be_find_xendev("vfb", domid, 0);
991
    xin = xen_be_find_xendev("vkbd", domid, 0);
992
    if (!xfb || !xin) {
993
        if (i < 256) {
994
            usleep(10000);
995
            goto wait_more;
996
        }
997
        xen_be_printf(NULL, 1, "displaystate setup failed\n");
998
        return;
999
    }
1000

    
1001
    /* vfb */
1002
    fb = container_of(xfb, struct XenFB, c.xendev);
1003
    fb->c.ds = graphic_console_init(xenfb_update,
1004
                                    xenfb_invalidate,
1005
                                    NULL,
1006
                                    NULL,
1007
                                    fb);
1008
    fb->have_console = 1;
1009

    
1010
    /* vkbd */
1011
    in = container_of(xin, struct XenInput, c.xendev);
1012
    in->c.ds = fb->c.ds;
1013

    
1014
    /* retry ->init() */
1015
    xen_be_check_state(xin);
1016
    xen_be_check_state(xfb);
1017
}