2 * xen paravirt framebuffer backend
4 * Copyright IBM, Corp. 2005-2006
5 * Copyright Red Hat, Inc. 2006-2008
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.
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.
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/>.
27 #include "qemu/osdep.h"
30 #include "ui/console.h"
31 #include "sysemu/char.h"
32 #include "hw/xen/xen_backend.h"
34 #include <xen/event_channel.h>
35 #include <xen/io/fbif.h>
36 #include <xen/io/kbdif.h>
37 #include <xen/io/protocols.h>
42 #define BTN_LEFT 0x110 /* from <linux/input.h> */
45 /* -------------------------------------------------------------------- */
48 struct XenDevice xendev; /* must be first */
55 int abs_pointer_wanted; /* Whether guest supports absolute pointer */
56 int button_state; /* Last seen pointer button state */
58 QEMUPutMouseEntry *qmouse;
85 /* -------------------------------------------------------------------- */
87 static int common_bind(struct common *c)
92 if (xenstore_read_fe_uint64(&c->xendev, "page-ref", &val) == -1)
97 if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1)
100 c->page = xenforeignmemory_map(xen_fmem, c->xendev.dom,
101 PROT_READ | PROT_WRITE, 1, &mfn, NULL);
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);
112 static void common_unbind(struct common *c)
114 xen_be_unbind_evtchn(&c->xendev);
116 xenforeignmemory_unmap(xen_fmem, c->page, 1);
121 /* -------------------------------------------------------------------- */
125 * These two tables are not needed any more, but left in here
126 * intentionally as documentation, to show how scancode2linux[]
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.
133 const unsigned char atkbd_set2_keycode[512] = {
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,
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,
155 const unsigned char atkbd_unxlate_table[128] = {
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
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];
175 static 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,
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,
195 /* Send an event to the keyboard frontend driver */
196 static int xenfb_kbd_event(struct XenInput *xenfb,
197 union xenkbd_in_event *event)
199 struct xenkbd_page *page = xenfb->c.page;
202 if (xenfb->c.xendev.be_state != XenbusStateConnected)
207 prod = page->in_prod;
208 if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
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);
220 /* Send a keyboard (or mouse button) event */
221 static int xenfb_send_key(struct XenInput *xenfb, bool down, int keycode)
223 union xenkbd_in_event event;
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;
230 return xenfb_kbd_event(xenfb, &event);
233 /* Send a relative mouse movement event */
234 static int xenfb_send_motion(struct XenInput *xenfb,
235 int rel_x, int rel_y, int rel_z)
237 union xenkbd_in_event event;
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;
245 return xenfb_kbd_event(xenfb, &event);
248 /* Send an absolute mouse movement event */
249 static int xenfb_send_position(struct XenInput *xenfb,
250 int abs_x, int abs_y, int z)
252 union xenkbd_in_event event;
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;
260 return xenfb_kbd_event(xenfb, &event);
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.
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
274 * Wish we could just send scancodes straight to the guest which
275 * already has code for dealing with this...
277 static void xenfb_key_event(void *opaque, int scancode)
279 struct XenInput *xenfb = opaque;
282 if (scancode == 0xe0) {
285 } else if (scancode & 0x80) {
289 if (xenfb->extended) {
293 xenfb_send_key(xenfb, down, scancode2linux[scancode]);
297 * Send a mouse event from the client to the guest OS
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
305 static void xenfb_mouse_event(void *opaque,
306 int dx, int dy, int dz, int button_state)
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);
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,
322 xenfb_send_motion(xenfb, dx, dy, dz);
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)
330 if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
333 xenfb->button_state = button_state;
336 static int input_init(struct XenDevice *xendev)
338 xenstore_write_be_int(xendev, "feature-abs-pointer", 1);
342 static int input_initialise(struct XenDevice *xendev)
344 struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
348 xen_be_printf(xendev, 1, "ds not set (yet)\n");
352 rc = common_bind(&in->c);
356 qemu_add_kbd_event_handler(xenfb_key_event, in);
360 static void input_connected(struct XenDevice *xendev)
362 struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
364 if (xenstore_read_fe_int(xendev, "request-abs-pointer",
365 &in->abs_pointer_wanted) == -1) {
366 in->abs_pointer_wanted = 0;
370 qemu_remove_mouse_event_handler(in->qmouse);
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,
378 static void input_disconnect(struct XenDevice *xendev)
380 struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
383 qemu_remove_mouse_event_handler(in->qmouse);
386 qemu_add_kbd_event_handler(NULL, NULL);
387 common_unbind(&in->c);
390 static void input_event(struct XenDevice *xendev)
392 struct XenInput *xenfb = container_of(xendev, struct XenInput, c.xendev);
393 struct xenkbd_page *page = xenfb->c.page;
395 /* We don't understand any keyboard events, so just ignore them. */
396 if (page->out_prod == page->out_cons)
398 page->out_cons = page->out_prod;
399 xen_be_send_notify(&xenfb->c.xendev);
402 /* -------------------------------------------------------------------- */
404 static void xenfb_copy_mfns(int mode, int count, xen_pfn_t *dst, void *src)
406 uint32_t *src32 = src;
407 uint64_t *src64 = src;
410 for (i = 0; i < count; i++)
411 dst[i] = (mode == 32) ? src32[i] : src64[i];
414 static int xenfb_map_fb(struct XenFB *xenfb)
416 struct xenfb_page *page = xenfb->c.page;
417 char *protocol = xenfb->c.xendev.protocol;
419 xen_pfn_t *pgmfns = NULL;
420 xen_pfn_t *fbmfns = NULL;
424 /* default to native */
426 mode = sizeof(unsigned long) * 8;
430 * Undefined protocol, some guesswork needed.
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 ...
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;
456 #if defined(__x86_64__)
457 } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) {
458 /* 64bit dom0, 32bit domU */
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 */
465 pd = ((void*)page->pd) + 4;
470 munmap(xenfb->pixels, xenfb->fbpages * XC_PAGE_SIZE);
471 xenfb->pixels = NULL;
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);
478 pgmfns = g_malloc0(sizeof(xen_pfn_t) * n_fbdirs);
479 fbmfns = g_malloc0(sizeof(xen_pfn_t) * xenfb->fbpages);
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);
486 xenfb_copy_mfns(mode, xenfb->fbpages, fbmfns, map);
487 xenforeignmemory_unmap(xen_fmem, map, n_fbdirs);
489 xenfb->pixels = xenforeignmemory_map(xen_fmem, xenfb->c.xendev.dom,
490 PROT_READ, xenfb->fbpages, fbmfns, NULL);
491 if (xenfb->pixels == NULL)
494 ret = 0; /* all is fine */
502 static 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)
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;
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;
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",
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",
527 if (row_stride <= 0 || row_stride > fb_len) {
528 xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend stride %d\n", row_stride);
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",
537 if (offset < 0 || offset >= fb_len) {
538 xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend offset %d (max %zu)\n",
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",
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);
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 \
566 + (line * xenfb->row_stride) \
567 + (x * xenfb->depth / 8)); \
568 DST_T *dst = (DST_T *)(data \
569 + (line * linesize) \
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); \
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.
601 static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
603 DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
605 int bpp = surface_bits_per_pixel(surface);
606 int linesize = surface_stride(surface);
607 uint8_t *data = surface_data(surface);
609 if (!is_buffer_shared(surface)) {
610 switch (xenfb->depth) {
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);
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);
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);
637 dpy_gfx_update(xenfb->c.con, x, y, w, h);
640 #ifdef XENFB_TYPE_REFRESH_PERIOD
641 static int xenfb_queue_full(struct XenFB *xenfb)
643 struct xenfb_page *page = xenfb->c.page;
649 prod = page->in_prod;
650 cons = page->in_cons;
651 return prod - cons == XENFB_IN_RING_LEN;
654 static void xenfb_send_event(struct XenFB *xenfb, union xenfb_in_event *event)
657 struct xenfb_page *page = xenfb->c.page;
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;
666 xen_be_send_notify(&xenfb->c.xendev);
669 static void xenfb_send_refresh_period(struct XenFB *xenfb, int period)
671 union xenfb_in_event event;
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);
681 * Periodic update of display.
682 * Also transmit the refresh interval to the frontend.
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.
689 static void xenfb_update(void *opaque)
691 struct XenFB *xenfb = opaque;
692 DisplaySurface *surface;
695 if (xenfb->c.xendev.be_state != XenbusStateConnected)
698 if (!xenfb->feature_update) {
699 /* we don't get update notifications, thus use the
700 * sledge hammer approach ... */
701 xenfb->up_fullscreen = 1;
704 /* resize if needed */
705 if (xenfb->do_resize) {
706 pixman_format_code_t format;
708 xenfb->do_resize = 0;
709 switch (xenfb->depth) {
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);
719 /* we must convert stuff */
720 surface = qemu_create_displaysurface(xenfb->width, xenfb->height);
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;
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);
743 xen_be_printf(&xenfb->c.xendev, 3, "update: nothing\n");
746 xenfb->up_fullscreen = 0;
749 static void xenfb_update_interval(void *opaque, uint64_t interval)
751 struct XenFB *xenfb = opaque;
753 if (xenfb->feature_update) {
754 #ifdef XENFB_TYPE_REFRESH_PERIOD
755 if (xenfb_queue_full(xenfb)) {
758 xenfb_send_refresh_period(xenfb, interval);
763 /* QEMU display state changed, so refresh the framebuffer copy */
764 static void xenfb_invalidate(void *opaque)
766 struct XenFB *xenfb = opaque;
767 xenfb->up_fullscreen = 1;
770 static void xenfb_handle_events(struct XenFB *xenfb)
772 uint32_t prod, cons, out_cons;
773 struct xenfb_page *page = xenfb->c.page;
775 prod = page->out_prod;
776 out_cons = page->out_cons;
777 if (prod - out_cons > XENFB_OUT_RING_LEN) {
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;
787 case XENFB_TYPE_UPDATE:
788 if (xenfb->up_count == UP_QUEUE)
789 xenfb->up_fullscreen = 1;
790 if (xenfb->up_fullscreen)
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");
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");
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;
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;
818 #ifdef XENFB_TYPE_RESIZE
819 case XENFB_TYPE_RESIZE:
820 if (xenfb_configure_fb(xenfb, xenfb->fb_len,
822 event->resize.height,
825 event->resize.offset,
826 event->resize.stride) < 0)
828 xenfb_invalidate(xenfb);
833 xen_mb(); /* ensure we're done with ring contents */
834 page->out_cons = cons;
837 static int fb_init(struct XenDevice *xendev)
839 #ifdef XENFB_TYPE_RESIZE
840 xenstore_write_be_int(xendev, "feature-resize", 1);
845 static int fb_initialise(struct XenDevice *xendev)
847 struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
848 struct xenfb_page *fb_page;
852 if (xenstore_read_fe_int(xendev, "videoram", &videoram) == -1)
855 rc = common_bind(&fb->c);
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);
866 rc = xenfb_map_fb(fb);
870 #if 0 /* handled in xen_init_display() for now */
871 if (!fb->have_console) {
872 fb->c.ds = graphic_console_init(xenfb_update,
877 fb->have_console = 1;
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);
886 xen_be_printf(xendev, 1, "feature-update=%d, videoram=%d\n",
887 fb->feature_update, videoram);
891 static void fb_disconnect(struct XenDevice *xendev)
893 struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
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.
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,
904 if (fb->pixels == MAP_FAILED) {
905 xen_be_printf(xendev, 0,
906 "Couldn't replace the framebuffer with anonymous memory errno=%d\n",
909 common_unbind(&fb->c);
910 fb->feature_update = 0;
914 static void fb_frontend_changed(struct XenDevice *xendev, const char *node)
916 struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
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.
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 */
932 static void fb_event(struct XenDevice *xendev)
934 struct XenFB *xenfb = container_of(xendev, struct XenFB, c.xendev);
936 xenfb_handle_events(xenfb);
937 xen_be_send_notify(&xenfb->c.xendev);
940 /* -------------------------------------------------------------------- */
942 struct XenDevOps xen_kbdmouse_ops = {
943 .size = sizeof(struct XenInput),
945 .initialise = input_initialise,
946 .connected = input_connected,
947 .disconnect = input_disconnect,
948 .event = input_event,
951 struct XenDevOps xen_framebuffer_ops = {
952 .size = sizeof(struct XenFB),
954 .initialise = fb_initialise,
955 .disconnect = fb_disconnect,
957 .frontend_changed = fb_frontend_changed,
960 static const GraphicHwOps xenfb_ops = {
961 .invalidate = xenfb_invalidate,
962 .gfx_update = xenfb_update,
963 .update_interval = xenfb_update_interval,
967 * FIXME/TODO: Kill this.
968 * Temporary needed while DisplayState reorganization is in flight.
970 void xen_init_display(int domid)
972 struct XenDevice *xfb, *xin;
979 main_loop_wait(true);
980 xfb = xen_be_find_xendev("vfb", domid, 0);
981 xin = xen_be_find_xendev("vkbd", domid, 0);
987 xen_be_printf(NULL, 1, "displaystate setup failed\n");
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;
997 in = container_of(xin, struct XenInput, c.xendev);
998 in->c.con = fb->c.con;
1000 /* retry ->init() */
1001 xen_be_check_state(xin);
1002 xen_be_check_state(xfb);