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