Statistics
| Branch: | Revision:

root / hw / xenfb.c @ a08784dd

History | View | Annotate | Download (30.1 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
    struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
351

    
352
    if (!in->c.ds) {
353
        xen_be_printf(xendev, 1, "ds not set (yet)\n");
354
        return -1;
355
    }
356

    
357
    xenstore_write_be_int(xendev, "feature-abs-pointer", 1);
358
    return 0;
359
}
360

    
361
static int input_connect(struct XenDevice *xendev)
362
{
363
    struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
364
    int rc;
365

    
366
    if (xenstore_read_fe_int(xendev, "request-abs-pointer",
367
                             &in->abs_pointer_wanted) == -1)
368
        in->abs_pointer_wanted = 0;
369

    
370
    rc = common_bind(&in->c);
371
    if (rc != 0)
372
        return rc;
373

    
374
    qemu_add_kbd_event_handler(xenfb_key_event, in);
375
    in->qmouse = qemu_add_mouse_event_handler(xenfb_mouse_event, in,
376
                                              in->abs_pointer_wanted,
377
                                              "Xen PVFB Mouse");
378
    return 0;
379
}
380

    
381
static void input_disconnect(struct XenDevice *xendev)
382
{
383
    struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
384

    
385
    if (in->qmouse) {
386
        qemu_remove_mouse_event_handler(in->qmouse);
387
        in->qmouse = NULL;
388
    }
389
    qemu_add_kbd_event_handler(NULL, NULL);
390
    common_unbind(&in->c);
391
}
392

    
393
static void input_event(struct XenDevice *xendev)
394
{
395
    struct XenInput *xenfb = container_of(xendev, struct XenInput, c.xendev);
396
    struct xenkbd_page *page = xenfb->c.page;
397

    
398
    /* We don't understand any keyboard events, so just ignore them. */
399
    if (page->out_prod == page->out_cons)
400
        return;
401
    page->out_cons = page->out_prod;
402
    xen_be_send_notify(&xenfb->c.xendev);
403
}
404

    
405
/* -------------------------------------------------------------------- */
406

    
407
static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
408
{
409
    uint32_t *src32 = src;
410
    uint64_t *src64 = src;
411
    int i;
412

    
413
    for (i = 0; i < count; i++)
414
        dst[i] = (mode == 32) ? src32[i] : src64[i];
415
}
416

    
417
static int xenfb_map_fb(struct XenFB *xenfb)
418
{
419
    struct xenfb_page *page = xenfb->c.page;
420
    char *protocol = xenfb->c.xendev.protocol;
421
    int n_fbdirs;
422
    unsigned long *pgmfns = NULL;
423
    unsigned long *fbmfns = NULL;
424
    void *map, *pd;
425
    int mode, ret = -1;
426

    
427
    /* default to native */
428
    pd = page->pd;
429
    mode = sizeof(unsigned long) * 8;
430

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

    
472
    if (xenfb->pixels) {
473
        munmap(xenfb->pixels, xenfb->fbpages * XC_PAGE_SIZE);
474
        xenfb->pixels = NULL;
475
    }
476

    
477
    xenfb->fbpages = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
478
    n_fbdirs = xenfb->fbpages * mode / 8;
479
    n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
480

    
481
    pgmfns = qemu_mallocz(sizeof(unsigned long) * n_fbdirs);
482
    fbmfns = qemu_mallocz(sizeof(unsigned long) * xenfb->fbpages);
483

    
484
    xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
485
    map = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
486
                               PROT_READ, pgmfns, n_fbdirs);
487
    if (map == NULL)
488
        goto out;
489
    xenfb_copy_mfns(mode, xenfb->fbpages, fbmfns, map);
490
    munmap(map, n_fbdirs * XC_PAGE_SIZE);
491

    
492
    xenfb->pixels = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
493
                                         PROT_READ | PROT_WRITE, fbmfns, xenfb->fbpages);
494
    if (xenfb->pixels == NULL)
495
        goto out;
496

    
497
    ret = 0; /* all is fine */
498

    
499
out:
500
    qemu_free(pgmfns);
501
    qemu_free(fbmfns);
502
    return ret;
503
}
504

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

    
515
    if (fb_len_lim > fb_len_max) {
516
        xen_be_printf(&xenfb->c.xendev, 0, "fb size limit %zu exceeds %zu, corrected\n",
517
                      fb_len_lim, fb_len_max);
518
        fb_len_lim = fb_len_max;
519
    }
520
    if (fb_len_lim && fb_len > fb_len_lim) {
521
        xen_be_printf(&xenfb->c.xendev, 0, "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_be_printf(&xenfb->c.xendev, 0, "can't handle frontend fb depth %d\n",
527
                      depth);
528
        return -1;
529
    }
530
    if (row_stride <= 0 || row_stride > fb_len) {
531
        xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend stride %d\n", row_stride);
532
        return -1;
533
    }
534
    max_width = row_stride / (depth / 8);
535
    if (width < 0 || width > max_width) {
536
        xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend width %d limited to %d\n",
537
                      width, max_width);
538
        width = max_width;
539
    }
540
    if (offset < 0 || offset >= fb_len) {
541
        xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend offset %d (max %zu)\n",
542
                      offset, fb_len - 1);
543
        return -1;
544
    }
545
    max_height = (fb_len - offset) / row_stride;
546
    if (height < 0 || height > max_height) {
547
        xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend height %d limited to %d\n",
548
                      height, max_height);
549
        height = max_height;
550
    }
551
    xenfb->fb_len = fb_len;
552
    xenfb->row_stride = row_stride;
553
    xenfb->depth = depth;
554
    xenfb->width = width;
555
    xenfb->height = height;
556
    xenfb->offset = offset;
557
    xenfb->up_fullscreen = 1;
558
    xenfb->do_resize = 1;
559
    xen_be_printf(&xenfb->c.xendev, 1, "framebuffer %dx%dx%d offset %d stride %d\n",
560
                  width, height, depth, offset, row_stride);
561
    return 0;
562
}
563

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

    
597

    
598
/*
599
 * This copies data from the guest framebuffer region, into QEMU's
600
 * displaysurface. qemu uses 16 or 32 bpp.  In case the pv framebuffer
601
 * uses something else we must convert and copy, otherwise we can
602
 * supply the buffer directly and no thing here.
603
 */
604
static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
605
{
606
    int line, oops = 0;
607
    int bpp = ds_get_bits_per_pixel(xenfb->c.ds);
608
    int linesize = ds_get_linesize(xenfb->c.ds);
609
    uint8_t *data = ds_get_data(xenfb->c.ds);
610

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

    
639
    dpy_update(xenfb->c.ds, x, y, w, h);
640
}
641

    
642
#ifdef XENFB_TYPE_REFRESH_PERIOD
643
static int xenfb_queue_full(struct XenFB *xenfb)
644
{
645
    struct xenfb_page *page = xenfb->c.page;
646
    uint32_t cons, prod;
647

    
648
    if (!page)
649
        return 1;
650

    
651
    prod = page->in_prod;
652
    cons = page->in_cons;
653
    return prod - cons == XENFB_IN_RING_LEN;
654
}
655

    
656
static void xenfb_send_event(struct XenFB *xenfb, union xenfb_in_event *event)
657
{
658
    uint32_t prod;
659
    struct xenfb_page *page = xenfb->c.page;
660

    
661
    prod = page->in_prod;
662
    /* caller ensures !xenfb_queue_full() */
663
    xen_mb();                   /* ensure ring space available */
664
    XENFB_IN_RING_REF(page, prod) = *event;
665
    xen_wmb();                  /* ensure ring contents visible */
666
    page->in_prod = prod + 1;
667

    
668
    xen_be_send_notify(&xenfb->c.xendev);
669
}
670

    
671
static void xenfb_send_refresh_period(struct XenFB *xenfb, int period)
672
{
673
    union xenfb_in_event event;
674

    
675
    memset(&event, 0, sizeof(event));
676
    event.type = XENFB_TYPE_REFRESH_PERIOD;
677
    event.refresh_period.period = period;
678
    xenfb_send_event(xenfb, &event);
679
}
680
#endif
681

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

    
696
    if (xenfb->c.xendev.be_state != XenbusStateConnected)
697
        return;
698

    
699
    if (xenfb->feature_update) {
700
#ifdef XENFB_TYPE_REFRESH_PERIOD
701
        struct DisplayChangeListener *l;
702
        int period = 99999999;
703
        int idle = 1;
704

    
705
        if (xenfb_queue_full(xenfb))
706
            return;
707

    
708
        for (l = xenfb->c.ds->listeners; l != NULL; l = l->next) {
709
            if (l->idle)
710
                continue;
711
            idle = 0;
712
            if (!l->gui_timer_interval) {
713
                if (period > GUI_REFRESH_INTERVAL)
714
                    period = GUI_REFRESH_INTERVAL;
715
            } else {
716
                if (period > l->gui_timer_interval)
717
                    period = l->gui_timer_interval;
718
            }
719
        }
720
        if (idle)
721
            period = XENFB_NO_REFRESH;
722

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

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

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

    
780
/* QEMU display state changed, so refresh the framebuffer copy */
781
static void xenfb_invalidate(void *opaque)
782
{
783
    struct XenFB *xenfb = opaque;
784
    xenfb->up_fullscreen = 1;
785
}
786

    
787
static void xenfb_handle_events(struct XenFB *xenfb)
788
{
789
    uint32_t prod, cons;
790
    struct xenfb_page *page = xenfb->c.page;
791

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

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

    
851
static int fb_init(struct XenDevice *xendev)
852
{
853
    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
854

    
855
    fb->refresh_period = -1;
856

    
857
#ifdef XENFB_TYPE_RESIZE
858
    xenstore_write_be_int(xendev, "feature-resize", 1);
859
#endif
860
    return 0;
861
}
862

    
863
static int fb_connect(struct XenDevice *xendev)
864
{
865
    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
866
    struct xenfb_page *fb_page;
867
    int videoram;
868
    int rc;
869

    
870
    if (xenstore_read_fe_int(xendev, "videoram", &videoram) == -1)
871
        videoram = 0;
872

    
873
    rc = common_bind(&fb->c);
874
    if (rc != 0)
875
        return rc;
876

    
877
    fb_page = fb->c.page;
878
    rc = xenfb_configure_fb(fb, videoram * 1024 * 1024U,
879
                            fb_page->width, fb_page->height, fb_page->depth,
880
                            fb_page->mem_length, 0, fb_page->line_length);
881
    if (rc != 0)
882
        return rc;
883

    
884
    rc = xenfb_map_fb(fb);
885
    if (rc != 0)
886
        return rc;
887

    
888
#if 0  /* handled in xen_init_display() for now */
889
    if (!fb->have_console) {
890
        fb->c.ds = graphic_console_init(xenfb_update,
891
                                        xenfb_invalidate,
892
                                        NULL,
893
                                        NULL,
894
                                        fb);
895
        fb->have_console = 1;
896
    }
897
#endif
898

    
899
    if (xenstore_read_fe_int(xendev, "feature-update", &fb->feature_update) == -1)
900
        fb->feature_update = 0;
901
    if (fb->feature_update)
902
        xenstore_write_be_int(xendev, "request-update", 1);
903

    
904
    xen_be_printf(xendev, 1, "feature-update=%d, videoram=%d\n",
905
                  fb->feature_update, videoram);
906
    return 0;
907
}
908

    
909
static void fb_disconnect(struct XenDevice *xendev)
910
{
911
    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
912

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

    
926
static void fb_frontend_changed(struct XenDevice *xendev, const char *node)
927
{
928
    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
929

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

    
944
static void fb_event(struct XenDevice *xendev)
945
{
946
    struct XenFB *xenfb = container_of(xendev, struct XenFB, c.xendev);
947

    
948
    xenfb_handle_events(xenfb);
949
    xen_be_send_notify(&xenfb->c.xendev);
950
}
951

    
952
/* -------------------------------------------------------------------- */
953

    
954
struct XenDevOps xen_kbdmouse_ops = {
955
    .size       = sizeof(struct XenInput),
956
    .init       = input_init,
957
    .connect    = input_connect,
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
    .connect    = fb_connect,
966
    .disconnect = fb_disconnect,
967
    .event      = fb_event,
968
    .frontend_changed = fb_frontend_changed,
969
};
970

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

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

    
996
    /* vfb */
997
    fb = container_of(xfb, struct XenFB, c.xendev);
998
    fb->c.ds = graphic_console_init(xenfb_update,
999
                                    xenfb_invalidate,
1000
                                    NULL,
1001
                                    NULL,
1002
                                    fb);
1003
    fb->have_console = 1;
1004

    
1005
    /* vkbd */
1006
    in = container_of(xin, struct XenInput, c.xendev);
1007
    in->c.ds = fb->c.ds;
1008

    
1009
    /* retry ->init() */
1010
    xen_be_check_state(xin);
1011
    xen_be_check_state(xfb);
1012
}