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    int mfn;
  97
  98    if (xenstore_read_fe_int(&c->xendev, "page-ref", &mfn) == -1)
  99        return -1;
 100    if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1)
 101        return -1;
 102
 103    c->page = xc_map_foreign_range(xen_xc, c->xendev.dom,
 104                                   XC_PAGE_SIZE,
 105                                   PROT_READ | PROT_WRITE, mfn);
 106    if (c->page == NULL)
 107        return -1;
 108
 109    xen_be_bind_evtchn(&c->xendev);
 110    xen_be_printf(&c->xendev, 1, "ring mfn %d, remote-port %d, local-port %d\n",
 111                  mfn, c->xendev.remote_port, c->xendev.local_port);
 112
 113    return 0;
 114}
 115
 116static void common_unbind(struct common *c)
 117{
 118    xen_be_unbind_evtchn(&c->xendev);
 119    if (c->page) {
 120        munmap(c->page, XC_PAGE_SIZE);
 121        c->page = NULL;
 122    }
 123}
 124
 125/* -------------------------------------------------------------------- */
 126
 127#if 0
 128/*
 129 * These two tables are not needed any more, but left in here
 130 * intentionally as documentation, to show how scancode2linux[]
 131 * was generated.
 132 *
 133 * Tables to map from scancode to Linux input layer keycode.
 134 * Scancodes are hardware-specific.  These maps assumes a
 135 * standard AT or PS/2 keyboard which is what QEMU feeds us.
 136 */
 137const unsigned char atkbd_set2_keycode[512] = {
 138
 139     0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
 140     0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
 141     0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
 142     0, 49, 48, 35, 34, 21,  7,184,  0,  0, 50, 36, 22,  8,  9,185,
 143     0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
 144     0, 89, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0, 85,
 145     0, 86, 91, 90, 92,  0, 14, 94,  0, 79,124, 75, 71,121,  0,  0,
 146    82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
 147
 148      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 149    217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
 150    173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
 151    159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
 152    157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
 153    226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
 154      0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
 155    110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
 156
 157};
 158
 159const unsigned char atkbd_unxlate_table[128] = {
 160
 161      0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
 162     21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
 163     35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
 164     50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
 165     11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
 166    114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
 167     71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
 168     19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
 169
 170};
 171#endif
 172
 173/*
 174 * for (i = 0; i < 128; i++) {
 175 *     scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
 176 *     scancode2linux[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
 177 * }
 178 */
 179static const unsigned char scancode2linux[512] = {
 180      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 181     16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
 182     32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
 183     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
 184     64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
 185     80, 81, 82, 83, 99,  0, 86, 87, 88,117,  0,  0, 95,183,184,185,
 186      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 187     93,  0,  0, 89,  0,  0, 85, 91, 90, 92,  0, 94,  0,124,121,  0,
 188
 189      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 190    165,  0,  0,  0,  0,  0,  0,  0,  0,163,  0,  0, 96, 97,  0,  0,
 191    113,140,164,  0,166,  0,  0,  0,  0,  0,255,  0,  0,  0,114,  0,
 192    115,  0,150,  0,  0, 98,255, 99,100,  0,  0,  0,  0,  0,  0,  0,
 193      0,  0,  0,  0,  0,119,119,102,103,104,  0,105,112,106,118,107,
 194    108,109,110,111,  0,  0,  0,  0,  0,  0,  0,125,126,127,116,142,
 195      0,  0,  0,143,  0,217,156,173,128,159,158,157,155,226,  0,112,
 196      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 197};
 198
 199/* Send an event to the keyboard frontend driver */
 200static int xenfb_kbd_event(struct XenInput *xenfb,
 201                           union xenkbd_in_event *event)
 202{
 203    struct xenkbd_page *page = xenfb->c.page;
 204    uint32_t prod;
 205
 206    if (xenfb->c.xendev.be_state != XenbusStateConnected)
 207        return 0;
 208    if (!page)
 209        return 0;
 210
 211    prod = page->in_prod;
 212    if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
 213        errno = EAGAIN;
 214        return -1;
 215    }
 216
 217    xen_mb();           /* ensure ring space available */
 218    XENKBD_IN_RING_REF(page, prod) = *event;
 219    xen_wmb();          /* ensure ring contents visible */
 220    page->in_prod = prod + 1;
 221    return xen_be_send_notify(&xenfb->c.xendev);
 222}
 223
 224/* Send a keyboard (or mouse button) event */
 225static int xenfb_send_key(struct XenInput *xenfb, bool down, int keycode)
 226{
 227    union xenkbd_in_event event;
 228
 229    memset(&event, 0, XENKBD_IN_EVENT_SIZE);
 230    event.type = XENKBD_TYPE_KEY;
 231    event.key.pressed = down ? 1 : 0;
 232    event.key.keycode = keycode;
 233
 234    return xenfb_kbd_event(xenfb, &event);
 235}
 236
 237/* Send a relative mouse movement event */
 238static int xenfb_send_motion(struct XenInput *xenfb,
 239                             int rel_x, int rel_y, int rel_z)
 240{
 241    union xenkbd_in_event event;
 242
 243    memset(&event, 0, XENKBD_IN_EVENT_SIZE);
 244    event.type = XENKBD_TYPE_MOTION;
 245    event.motion.rel_x = rel_x;
 246    event.motion.rel_y = rel_y;
 247#if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030207
 248    event.motion.rel_z = rel_z;
 249#endif
 250
 251    return xenfb_kbd_event(xenfb, &event);
 252}
 253
 254/* Send an absolute mouse movement event */
 255static int xenfb_send_position(struct XenInput *xenfb,
 256                               int abs_x, int abs_y, int z)
 257{
 258    union xenkbd_in_event event;
 259
 260    memset(&event, 0, XENKBD_IN_EVENT_SIZE);
 261    event.type = XENKBD_TYPE_POS;
 262    event.pos.abs_x = abs_x;
 263    event.pos.abs_y = abs_y;
 264#if __XEN_LATEST_INTERFACE_VERSION__ == 0x00030207
 265    event.pos.abs_z = z;
 266#endif
 267#if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030208
 268    event.pos.rel_z = z;
 269#endif
 270
 271    return xenfb_kbd_event(xenfb, &event);
 272}
 273
 274/*
 275 * Send a key event from the client to the guest OS
 276 * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
 277 * We have to turn this into a Linux Input layer keycode.
 278 *
 279 * Extra complexity from the fact that with extended scancodes
 280 * (like those produced by arrow keys) this method gets called
 281 * twice, but we only want to send a single event. So we have to
 282 * track the '0xe0' scancode state & collapse the extended keys
 283 * as needed.
 284 *
 285 * Wish we could just send scancodes straight to the guest which
 286 * already has code for dealing with this...
 287 */
 288static void xenfb_key_event(void *opaque, int scancode)
 289{
 290    struct XenInput *xenfb = opaque;
 291    int down = 1;
 292
 293    if (scancode == 0xe0) {
 294        xenfb->extended = 1;
 295        return;
 296    } else if (scancode & 0x80) {
 297        scancode &= 0x7f;
 298        down = 0;
 299    }
 300    if (xenfb->extended) {
 301        scancode |= 0x80;
 302        xenfb->extended = 0;
 303    }
 304    xenfb_send_key(xenfb, down, scancode2linux[scancode]);
 305}
 306
 307/*
 308 * Send a mouse event from the client to the guest OS
 309 *
 310 * The QEMU mouse can be in either relative, or absolute mode.
 311 * Movement is sent separately from button state, which has to
 312 * be encoded as virtual key events. We also don't actually get
 313 * given any button up/down events, so have to track changes in
 314 * the button state.
 315 */
 316static void xenfb_mouse_event(void *opaque,
 317                              int dx, int dy, int dz, int button_state)
 318{
 319    struct XenInput *xenfb = opaque;
 320    DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
 321    int dw = surface_width(surface);
 322    int dh = surface_height(surface);
 323    int i;
 324
 325    if (xenfb->abs_pointer_wanted)
 326        xenfb_send_position(xenfb,
 327                            dx * (dw - 1) / 0x7fff,
 328                            dy * (dh - 1) / 0x7fff,
 329                            dz);
 330    else
 331        xenfb_send_motion(xenfb, dx, dy, dz);
 332
 333    for (i = 0 ; i < 8 ; i++) {
 334        int lastDown = xenfb->button_state & (1 << i);
 335        int down = button_state & (1 << i);
 336        if (down == lastDown)
 337            continue;
 338
 339        if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
 340            return;
 341    }
 342    xenfb->button_state = button_state;
 343}
 344
 345static int input_init(struct XenDevice *xendev)
 346{
 347    xenstore_write_be_int(xendev, "feature-abs-pointer", 1);
 348    return 0;
 349}
 350
 351static int input_initialise(struct XenDevice *xendev)
 352{
 353    struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
 354    int rc;
 355
 356    if (!in->c.con) {
 357        xen_be_printf(xendev, 1, "ds not set (yet)\n");
 358        return -1;
 359    }
 360
 361    rc = common_bind(&in->c);
 362    if (rc != 0)
 363        return rc;
 364
 365    qemu_add_kbd_event_handler(xenfb_key_event, in);
 366    return 0;
 367}
 368
 369static void input_connected(struct XenDevice *xendev)
 370{
 371    struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
 372
 373    if (xenstore_read_fe_int(xendev, "request-abs-pointer",
 374                             &in->abs_pointer_wanted) == -1) {
 375        in->abs_pointer_wanted = 0;
 376    }
 377
 378    if (in->qmouse) {
 379        qemu_remove_mouse_event_handler(in->qmouse);
 380    }
 381    in->qmouse = qemu_add_mouse_event_handler(xenfb_mouse_event, in,
 382                                              in->abs_pointer_wanted,
 383                                              "Xen PVFB Mouse");
 384}
 385
 386static 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
 398static 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
 412static 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
 422static 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
 504out:
 505    g_free(pgmfns);
 506    g_free(fbmfns);
 507    return ret;
 508}
 509
 510static 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 */
 609static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
 610{
 611    DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
 612    int line, oops = 0;
 613    int bpp = surface_bits_per_pixel(surface);
 614    int linesize = surface_stride(surface);
 615    uint8_t *data = surface_data(surface);
 616
 617    if (!is_buffer_shared(surface)) {
 618        switch (xenfb->depth) {
 619        case 8:
 620            if (bpp == 16) {
 621                BLT(uint8_t, uint16_t,   3, 3, 2,   5, 6, 5);
 622            } else if (bpp == 32) {
 623                BLT(uint8_t, uint32_t,   3, 3, 2,   8, 8, 8);
 624            } else {
 625                oops = 1;
 626            }
 627            break;
 628        case 24:
 629            if (bpp == 16) {
 630                BLT(uint32_t, uint16_t,  8, 8, 8,   5, 6, 5);
 631            } else if (bpp == 32) {
 632                BLT(uint32_t, uint32_t,  8, 8, 8,   8, 8, 8);
 633            } else {
 634                oops = 1;
 635            }
 636            break;
 637        default:
 638            oops = 1;
 639        }
 640    }
 641    if (oops) /* should not happen */
 642        xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n",
 643                      __FUNCTION__, xenfb->depth, bpp);
 644
 645    dpy_gfx_update(xenfb->c.con, x, y, w, h);
 646}
 647
 648#ifdef XENFB_TYPE_REFRESH_PERIOD
 649static int xenfb_queue_full(struct XenFB *xenfb)
 650{
 651    struct xenfb_page *page = xenfb->c.page;
 652    uint32_t cons, prod;
 653
 654    if (!page)
 655        return 1;
 656
 657    prod = page->in_prod;
 658    cons = page->in_cons;
 659    return prod - cons == XENFB_IN_RING_LEN;
 660}
 661
 662static void xenfb_send_event(struct XenFB *xenfb, union xenfb_in_event *event)
 663{
 664    uint32_t prod;
 665    struct xenfb_page *page = xenfb->c.page;
 666
 667    prod = page->in_prod;
 668    /* caller ensures !xenfb_queue_full() */
 669    xen_mb();                   /* ensure ring space available */
 670    XENFB_IN_RING_REF(page, prod) = *event;
 671    xen_wmb();                  /* ensure ring contents visible */
 672    page->in_prod = prod + 1;
 673
 674    xen_be_send_notify(&xenfb->c.xendev);
 675}
 676
 677static void xenfb_send_refresh_period(struct XenFB *xenfb, int period)
 678{
 679    union xenfb_in_event event;
 680
 681    memset(&event, 0, sizeof(event));
 682    event.type = XENFB_TYPE_REFRESH_PERIOD;
 683    event.refresh_period.period = period;
 684    xenfb_send_event(xenfb, &event);
 685}
 686#endif
 687
 688/*
 689 * Periodic update of display.
 690 * Also transmit the refresh interval to the frontend.
 691 *
 692 * Never ever do any qemu display operations
 693 * (resize, screen update) outside this function.
 694 * Our screen might be inactive.  When asked for
 695 * an update we know it is active.
 696 */
 697static void xenfb_update(void *opaque)
 698{
 699    struct XenFB *xenfb = opaque;
 700    DisplaySurface *surface;
 701    int i;
 702
 703    if (xenfb->c.xendev.be_state != XenbusStateConnected)
 704        return;
 705
 706    if (!xenfb->feature_update) {
 707        /* we don't get update notifications, thus use the
 708         * sledge hammer approach ... */
 709        xenfb->up_fullscreen = 1;
 710    }
 711
 712    /* resize if needed */
 713    if (xenfb->do_resize) {
 714        xenfb->do_resize = 0;
 715        switch (xenfb->depth) {
 716        case 16:
 717        case 32:
 718            /* console.c supported depth -> buffer can be used directly */
 719            surface = qemu_create_displaysurface_from
 720                (xenfb->width, xenfb->height, xenfb->depth,
 721                 xenfb->row_stride, xenfb->pixels + xenfb->offset,
 722                 false);
 723            break;
 724        default:
 725            /* we must convert stuff */
 726            surface = qemu_create_displaysurface(xenfb->width, xenfb->height);
 727            break;
 728        }
 729        dpy_gfx_replace_surface(xenfb->c.con, surface);
 730        xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n",
 731                      xenfb->width, xenfb->height, xenfb->depth,
 732                      is_buffer_shared(surface) ? " (shared)" : "");
 733        xenfb->up_fullscreen = 1;
 734    }
 735
 736    /* run queued updates */
 737    if (xenfb->up_fullscreen) {
 738        xen_be_printf(&xenfb->c.xendev, 3, "update: fullscreen\n");
 739        xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
 740    } else if (xenfb->up_count) {
 741        xen_be_printf(&xenfb->c.xendev, 3, "update: %d rects\n", xenfb->up_count);
 742        for (i = 0; i < xenfb->up_count; i++)
 743            xenfb_guest_copy(xenfb,
 744                             xenfb->up_rects[i].x,
 745                             xenfb->up_rects[i].y,
 746                             xenfb->up_rects[i].w,
 747                             xenfb->up_rects[i].h);
 748    } else {
 749        xen_be_printf(&xenfb->c.xendev, 3, "update: nothing\n");
 750    }
 751    xenfb->up_count = 0;
 752    xenfb->up_fullscreen = 0;
 753}
 754
 755static void xenfb_update_interval(void *opaque, uint64_t interval)
 756{
 757    struct XenFB *xenfb = opaque;
 758
 759    if (xenfb->feature_update) {
 760#ifdef XENFB_TYPE_REFRESH_PERIOD
 761        if (xenfb_queue_full(xenfb)) {
 762            return;
 763        }
 764        xenfb_send_refresh_period(xenfb, interval);
 765#endif
 766    }
 767}
 768
 769/* QEMU display state changed, so refresh the framebuffer copy */
 770static void xenfb_invalidate(void *opaque)
 771{
 772    struct XenFB *xenfb = opaque;
 773    xenfb->up_fullscreen = 1;
 774}
 775
 776static void xenfb_handle_events(struct XenFB *xenfb)
 777{
 778    uint32_t prod, cons;
 779    struct xenfb_page *page = xenfb->c.page;
 780
 781    prod = page->out_prod;
 782    if (prod == page->out_cons)
 783        return;
 784    xen_rmb();          /* ensure we see ring contents up to prod */
 785    for (cons = page->out_cons; cons != prod; cons++) {
 786        union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
 787        int x, y, w, h;
 788
 789        switch (event->type) {
 790        case XENFB_TYPE_UPDATE:
 791            if (xenfb->up_count == UP_QUEUE)
 792                xenfb->up_fullscreen = 1;
 793            if (xenfb->up_fullscreen)
 794                break;
 795            x = MAX(event->update.x, 0);
 796            y = MAX(event->update.y, 0);
 797            w = MIN(event->update.width, xenfb->width - x);
 798            h = MIN(event->update.height, xenfb->height - y);
 799            if (w < 0 || h < 0) {
 800                xen_be_printf(&xenfb->c.xendev, 1, "bogus update ignored\n");
 801                break;
 802            }
 803            if (x != event->update.x ||
 804                y != event->update.y ||
 805                w != event->update.width ||
 806                h != event->update.height) {
 807                xen_be_printf(&xenfb->c.xendev, 1, "bogus update clipped\n");
 808            }
 809            if (w == xenfb->width && h > xenfb->height / 2) {
 810                /* scroll detector: updated more than 50% of the lines,
 811                 * don't bother keeping track of the rectangles then */
 812                xenfb->up_fullscreen = 1;
 813            } else {
 814                xenfb->up_rects[xenfb->up_count].x = x;
 815                xenfb->up_rects[xenfb->up_count].y = y;
 816                xenfb->up_rects[xenfb->up_count].w = w;
 817                xenfb->up_rects[xenfb->up_count].h = h;
 818                xenfb->up_count++;
 819            }
 820            break;
 821#ifdef XENFB_TYPE_RESIZE
 822        case XENFB_TYPE_RESIZE:
 823            if (xenfb_configure_fb(xenfb, xenfb->fb_len,
 824                                   event->resize.width,
 825                                   event->resize.height,
 826                                   event->resize.depth,
 827                                   xenfb->fb_len,
 828                                   event->resize.offset,
 829                                   event->resize.stride) < 0)
 830                break;
 831            xenfb_invalidate(xenfb);
 832            break;
 833#endif
 834        }
 835    }
 836    xen_mb();           /* ensure we're done with ring contents */
 837    page->out_cons = cons;
 838}
 839
 840static int fb_init(struct XenDevice *xendev)
 841{
 842#ifdef XENFB_TYPE_RESIZE
 843    xenstore_write_be_int(xendev, "feature-resize", 1);
 844#endif
 845    return 0;
 846}
 847
 848static int fb_initialise(struct XenDevice *xendev)
 849{
 850    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
 851    struct xenfb_page *fb_page;
 852    int videoram;
 853    int rc;
 854
 855    if (xenstore_read_fe_int(xendev, "videoram", &videoram) == -1)
 856        videoram = 0;
 857
 858    rc = common_bind(&fb->c);
 859    if (rc != 0)
 860        return rc;
 861
 862    fb_page = fb->c.page;
 863    rc = xenfb_configure_fb(fb, videoram * 1024 * 1024U,
 864                            fb_page->width, fb_page->height, fb_page->depth,
 865                            fb_page->mem_length, 0, fb_page->line_length);
 866    if (rc != 0)
 867        return rc;
 868
 869    rc = xenfb_map_fb(fb);
 870    if (rc != 0)
 871        return rc;
 872
 873#if 0  /* handled in xen_init_display() for now */
 874    if (!fb->have_console) {
 875        fb->c.ds = graphic_console_init(xenfb_update,
 876                                        xenfb_invalidate,
 877                                        NULL,
 878                                        NULL,
 879                                        fb);
 880        fb->have_console = 1;
 881    }
 882#endif
 883
 884    if (xenstore_read_fe_int(xendev, "feature-update", &fb->feature_update) == -1)
 885        fb->feature_update = 0;
 886    if (fb->feature_update)
 887        xenstore_write_be_int(xendev, "request-update", 1);
 888
 889    xen_be_printf(xendev, 1, "feature-update=%d, videoram=%d\n",
 890                  fb->feature_update, videoram);
 891    return 0;
 892}
 893
 894static void fb_disconnect(struct XenDevice *xendev)
 895{
 896    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
 897
 898    /*
 899     * FIXME: qemu can't un-init gfx display (yet?).
 900     *   Replacing the framebuffer with anonymous shared memory
 901     *   instead.  This releases the guest pages and keeps qemu happy.
 902     */
 903    fb->pixels = mmap(fb->pixels, fb->fbpages * XC_PAGE_SIZE,
 904                      PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON,
 905                      -1, 0);
 906    common_unbind(&fb->c);
 907    fb->feature_update = 0;
 908    fb->bug_trigger    = 0;
 909}
 910
 911static void fb_frontend_changed(struct XenDevice *xendev, const char *node)
 912{
 913    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
 914
 915    /*
 916     * Set state to Connected *again* once the frontend switched
 917     * to connected.  We must trigger the watch a second time to
 918     * workaround a frontend bug.
 919     */
 920    if (fb->bug_trigger == 0 && strcmp(node, "state") == 0 &&
 921        xendev->fe_state == XenbusStateConnected &&
 922        xendev->be_state == XenbusStateConnected) {
 923        xen_be_printf(xendev, 2, "re-trigger connected (frontend bug)\n");
 924        xen_be_set_state(xendev, XenbusStateConnected);
 925        fb->bug_trigger = 1; /* only once */
 926    }
 927}
 928
 929static void fb_event(struct XenDevice *xendev)
 930{
 931    struct XenFB *xenfb = container_of(xendev, struct XenFB, c.xendev);
 932
 933    xenfb_handle_events(xenfb);
 934    xen_be_send_notify(&xenfb->c.xendev);
 935}
 936
 937/* -------------------------------------------------------------------- */
 938
 939struct XenDevOps xen_kbdmouse_ops = {
 940    .size       = sizeof(struct XenInput),
 941    .init       = input_init,
 942    .initialise = input_initialise,
 943    .connected  = input_connected,
 944    .disconnect = input_disconnect,
 945    .event      = input_event,
 946};
 947
 948struct XenDevOps xen_framebuffer_ops = {
 949    .size       = sizeof(struct XenFB),
 950    .init       = fb_init,
 951    .initialise = fb_initialise,
 952    .disconnect = fb_disconnect,
 953    .event      = fb_event,
 954    .frontend_changed = fb_frontend_changed,
 955};
 956
 957static const GraphicHwOps xenfb_ops = {
 958    .invalidate  = xenfb_invalidate,
 959    .gfx_update  = xenfb_update,
 960    .update_interval = xenfb_update_interval,
 961};
 962
 963/*
 964 * FIXME/TODO: Kill this.
 965 * Temporary needed while DisplayState reorganization is in flight.
 966 */
 967void xen_init_display(int domid)
 968{
 969    struct XenDevice *xfb, *xin;
 970    struct XenFB *fb;
 971    struct XenInput *in;
 972    int i = 0;
 973
 974wait_more:
 975    i++;
 976    main_loop_wait(true);
 977    xfb = xen_be_find_xendev("vfb", domid, 0);
 978    xin = xen_be_find_xendev("vkbd", domid, 0);
 979    if (!xfb || !xin) {
 980        if (i < 256) {
 981            usleep(10000);
 982            goto wait_more;
 983        }
 984        xen_be_printf(NULL, 1, "displaystate setup failed\n");
 985        return;
 986    }
 987
 988    /* vfb */
 989    fb = container_of(xfb, struct XenFB, c.xendev);
 990    fb->c.con = graphic_console_init(NULL, &xenfb_ops, fb);
 991    fb->have_console = 1;
 992
 993    /* vkbd */
 994    in = container_of(xin, struct XenInput, c.xendev);
 995    in->c.con = fb->c.con;
 996
 997    /* retry ->init() */
 998    xen_be_check_state(xin);
 999    xen_be_check_state(xfb);
1000}
1001