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