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