2 * xen paravirt framebuffer backend
4 * Copyright IBM, Corp. 2005-2006
5 * Copyright Red Hat, Inc. 2006-2008
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>
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"
31 #include "ui/console.h"
32 #include "sysemu/char.h"
33 #include "hw/xen/xen_backend.h"
35 #include <xen/event_channel.h>
36 #include <xen/io/fbif.h>
37 #include <xen/io/kbdif.h>
38 #include <xen/io/protocols.h>
43 #define BTN_LEFT 0x110 /* from <linux/input.h> */
46 /* -------------------------------------------------------------------- */
49 struct XenDevice xendev
; /* must be first */
56 int abs_pointer_wanted
; /* Whether guest supports absolute pointer */
57 int button_state
; /* Last seen pointer button state */
59 QEMUPutMouseEntry
*qmouse
;
86 /* -------------------------------------------------------------------- */
88 static int common_bind(struct common
*c
)
93 if (xenstore_read_fe_uint64(&c
->xendev
, "page-ref", &val
) == -1)
98 if (xenstore_read_fe_int(&c
->xendev
, "event-channel", &c
->xendev
.remote_port
) == -1)
101 c
->page
= xenforeignmemory_map(xen_fmem
, c
->xendev
.dom
,
102 PROT_READ
| PROT_WRITE
, 1, &mfn
, NULL
);
106 xen_be_bind_evtchn(&c
->xendev
);
107 xen_be_printf(&c
->xendev
, 1, "ring mfn %"PRI_xen_pfn
", remote-port %d, local-port %d\n",
108 mfn
, c
->xendev
.remote_port
, c
->xendev
.local_port
);
113 static void common_unbind(struct common
*c
)
115 xen_be_unbind_evtchn(&c
->xendev
);
117 xenforeignmemory_unmap(xen_fmem
, c
->page
, 1);
122 /* -------------------------------------------------------------------- */
126 * These two tables are not needed any more, but left in here
127 * intentionally as documentation, to show how scancode2linux[]
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.
134 const unsigned char atkbd_set2_keycode
[512] = {
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,
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,
156 const unsigned char atkbd_unxlate_table
[128] = {
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
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];
176 static 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,
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,
196 /* Send an event to the keyboard frontend driver */
197 static int xenfb_kbd_event(struct XenInput
*xenfb
,
198 union xenkbd_in_event
*event
)
200 struct xenkbd_page
*page
= xenfb
->c
.page
;
203 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
208 prod
= page
->in_prod
;
209 if (prod
- page
->in_cons
== XENKBD_IN_RING_LEN
) {
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_be_send_notify(&xenfb
->c
.xendev
);
221 /* Send a keyboard (or mouse button) event */
222 static int xenfb_send_key(struct XenInput
*xenfb
, bool down
, int keycode
)
224 union xenkbd_in_event event
;
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
;
231 return xenfb_kbd_event(xenfb
, &event
);
234 /* Send a relative mouse movement event */
235 static int xenfb_send_motion(struct XenInput
*xenfb
,
236 int rel_x
, int rel_y
, int rel_z
)
238 union xenkbd_in_event event
;
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
;
246 return xenfb_kbd_event(xenfb
, &event
);
249 /* Send an absolute mouse movement event */
250 static int xenfb_send_position(struct XenInput
*xenfb
,
251 int abs_x
, int abs_y
, int z
)
253 union xenkbd_in_event event
;
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
;
261 return xenfb_kbd_event(xenfb
, &event
);
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.
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
275 * Wish we could just send scancodes straight to the guest which
276 * already has code for dealing with this...
278 static void xenfb_key_event(void *opaque
, int scancode
)
280 struct XenInput
*xenfb
= opaque
;
283 if (scancode
== 0xe0) {
286 } else if (scancode
& 0x80) {
290 if (xenfb
->extended
) {
294 xenfb_send_key(xenfb
, down
, scancode2linux
[scancode
]);
298 * Send a mouse event from the client to the guest OS
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
306 static void xenfb_mouse_event(void *opaque
,
307 int dx
, int dy
, int dz
, int button_state
)
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
);
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,
323 xenfb_send_motion(xenfb
, dx
, dy
, dz
);
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
)
331 if (xenfb_send_key(xenfb
, down
, BTN_LEFT
+i
) < 0)
334 xenfb
->button_state
= button_state
;
337 static int input_init(struct XenDevice
*xendev
)
339 xenstore_write_be_int(xendev
, "feature-abs-pointer", 1);
343 static int input_initialise(struct XenDevice
*xendev
)
345 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
349 xen_be_printf(xendev
, 1, "ds not set (yet)\n");
353 rc
= common_bind(&in
->c
);
357 qemu_add_kbd_event_handler(xenfb_key_event
, in
);
361 static void input_connected(struct XenDevice
*xendev
)
363 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
365 if (xenstore_read_fe_int(xendev
, "request-abs-pointer",
366 &in
->abs_pointer_wanted
) == -1) {
367 in
->abs_pointer_wanted
= 0;
371 qemu_remove_mouse_event_handler(in
->qmouse
);
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
,
379 static void input_disconnect(struct XenDevice
*xendev
)
381 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
384 qemu_remove_mouse_event_handler(in
->qmouse
);
387 qemu_add_kbd_event_handler(NULL
, NULL
);
388 common_unbind(&in
->c
);
391 static void input_event(struct XenDevice
*xendev
)
393 struct XenInput
*xenfb
= container_of(xendev
, struct XenInput
, c
.xendev
);
394 struct xenkbd_page
*page
= xenfb
->c
.page
;
396 /* We don't understand any keyboard events, so just ignore them. */
397 if (page
->out_prod
== page
->out_cons
)
399 page
->out_cons
= page
->out_prod
;
400 xen_be_send_notify(&xenfb
->c
.xendev
);
403 /* -------------------------------------------------------------------- */
405 static void xenfb_copy_mfns(int mode
, int count
, xen_pfn_t
*dst
, void *src
)
407 uint32_t *src32
= src
;
408 uint64_t *src64
= src
;
411 for (i
= 0; i
< count
; i
++)
412 dst
[i
] = (mode
== 32) ? src32
[i
] : src64
[i
];
415 static int xenfb_map_fb(struct XenFB
*xenfb
)
417 struct xenfb_page
*page
= xenfb
->c
.page
;
418 char *protocol
= xenfb
->c
.xendev
.protocol
;
420 xen_pfn_t
*pgmfns
= NULL
;
421 xen_pfn_t
*fbmfns
= NULL
;
425 /* default to native */
427 mode
= sizeof(unsigned long) * 8;
431 * Undefined protocol, some guesswork needed.
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 ...
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
;
457 #if defined(__x86_64__)
458 } else if (strcmp(protocol
, XEN_IO_PROTO_ABI_X86_32
) == 0) {
459 /* 64bit dom0, 32bit domU */
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 */
466 pd
= ((void*)page
->pd
) + 4;
471 munmap(xenfb
->pixels
, xenfb
->fbpages
* XC_PAGE_SIZE
);
472 xenfb
->pixels
= NULL
;
475 xenfb
->fbpages
= (xenfb
->fb_len
+ (XC_PAGE_SIZE
- 1)) / XC_PAGE_SIZE
;
476 n_fbdirs
= xenfb
->fbpages
* mode
/ 8;
477 n_fbdirs
= (n_fbdirs
+ (XC_PAGE_SIZE
- 1)) / XC_PAGE_SIZE
;
479 pgmfns
= g_malloc0(sizeof(xen_pfn_t
) * n_fbdirs
);
480 fbmfns
= g_malloc0(sizeof(xen_pfn_t
) * xenfb
->fbpages
);
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
);
487 xenfb_copy_mfns(mode
, xenfb
->fbpages
, fbmfns
, map
);
488 xenforeignmemory_unmap(xen_fmem
, map
, n_fbdirs
);
490 xenfb
->pixels
= xenforeignmemory_map(xen_fmem
, xenfb
->c
.xendev
.dom
,
491 PROT_READ
, xenfb
->fbpages
, fbmfns
, NULL
);
492 if (xenfb
->pixels
== NULL
)
495 ret
= 0; /* all is fine */
503 static 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
)
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
;
513 if (fb_len_lim
> fb_len_max
) {
514 xen_be_printf(&xenfb
->c
.xendev
, 0, "fb size limit %zu exceeds %zu, corrected\n",
515 fb_len_lim
, fb_len_max
);
516 fb_len_lim
= fb_len_max
;
518 if (fb_len_lim
&& fb_len
> fb_len_lim
) {
519 xen_be_printf(&xenfb
->c
.xendev
, 0, "frontend fb size %zu limited to %zu\n",
523 if (depth
!= 8 && depth
!= 16 && depth
!= 24 && depth
!= 32) {
524 xen_be_printf(&xenfb
->c
.xendev
, 0, "can't handle frontend fb depth %d\n",
528 if (row_stride
<= 0 || row_stride
> fb_len
) {
529 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend stride %d\n", row_stride
);
532 max_width
= row_stride
/ (depth
/ 8);
533 if (width
< 0 || width
> max_width
) {
534 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend width %d limited to %d\n",
538 if (offset
< 0 || offset
>= fb_len
) {
539 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend offset %d (max %zu)\n",
543 max_height
= (fb_len
- offset
) / row_stride
;
544 if (height
< 0 || height
> max_height
) {
545 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend height %d limited to %d\n",
549 xenfb
->fb_len
= fb_len
;
550 xenfb
->row_stride
= row_stride
;
551 xenfb
->depth
= depth
;
552 xenfb
->width
= width
;
553 xenfb
->height
= height
;
554 xenfb
->offset
= offset
;
555 xenfb
->up_fullscreen
= 1;
556 xenfb
->do_resize
= 1;
557 xen_be_printf(&xenfb
->c
.xendev
, 1, "framebuffer %dx%dx%d offset %d stride %d\n",
558 width
, height
, depth
, offset
, row_stride
);
562 /* A convenient function for munging pixels between different depths */
563 #define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB) \
564 for (line = y ; line < (y+h) ; line++) { \
565 SRC_T *src = (SRC_T *)(xenfb->pixels \
567 + (line * xenfb->row_stride) \
568 + (x * xenfb->depth / 8)); \
569 DST_T *dst = (DST_T *)(data \
570 + (line * linesize) \
573 const int RSS = 32 - (RSB + GSB + BSB); \
574 const int GSS = 32 - (GSB + BSB); \
575 const int BSS = 32 - (BSB); \
576 const uint32_t RSM = (~0U) << (32 - RSB); \
577 const uint32_t GSM = (~0U) << (32 - GSB); \
578 const uint32_t BSM = (~0U) << (32 - BSB); \
579 const int RDS = 32 - (RDB + GDB + BDB); \
580 const int GDS = 32 - (GDB + BDB); \
581 const int BDS = 32 - (BDB); \
582 const uint32_t RDM = (~0U) << (32 - RDB); \
583 const uint32_t GDM = (~0U) << (32 - GDB); \
584 const uint32_t BDM = (~0U) << (32 - BDB); \
585 for (col = x ; col < (x+w) ; col++) { \
586 uint32_t spix = *src; \
587 *dst = (((spix << RSS) & RSM & RDM) >> RDS) | \
588 (((spix << GSS) & GSM & GDM) >> GDS) | \
589 (((spix << BSS) & BSM & BDM) >> BDS); \
590 src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8); \
591 dst = (DST_T *) ((unsigned long) dst + bpp / 8); \
597 * This copies data from the guest framebuffer region, into QEMU's
598 * displaysurface. qemu uses 16 or 32 bpp. In case the pv framebuffer
599 * uses something else we must convert and copy, otherwise we can
600 * supply the buffer directly and no thing here.
602 static void xenfb_guest_copy(struct XenFB
*xenfb
, int x
, int y
, int w
, int h
)
604 DisplaySurface
*surface
= qemu_console_surface(xenfb
->c
.con
);
606 int bpp
= surface_bits_per_pixel(surface
);
607 int linesize
= surface_stride(surface
);
608 uint8_t *data
= surface_data(surface
);
610 if (!is_buffer_shared(surface
)) {
611 switch (xenfb
->depth
) {
614 BLT(uint8_t, uint16_t, 3, 3, 2, 5, 6, 5);
615 } else if (bpp
== 32) {
616 BLT(uint8_t, uint32_t, 3, 3, 2, 8, 8, 8);
623 BLT(uint32_t, uint16_t, 8, 8, 8, 5, 6, 5);
624 } else if (bpp
== 32) {
625 BLT(uint32_t, uint32_t, 8, 8, 8, 8, 8, 8);
634 if (oops
) /* should not happen */
635 xen_be_printf(&xenfb
->c
.xendev
, 0, "%s: oops: convert %d -> %d bpp?\n",
636 __FUNCTION__
, xenfb
->depth
, bpp
);
638 dpy_gfx_update(xenfb
->c
.con
, x
, y
, w
, h
);
641 #ifdef XENFB_TYPE_REFRESH_PERIOD
642 static int xenfb_queue_full(struct XenFB
*xenfb
)
644 struct xenfb_page
*page
= xenfb
->c
.page
;
650 prod
= page
->in_prod
;
651 cons
= page
->in_cons
;
652 return prod
- cons
== XENFB_IN_RING_LEN
;
655 static void xenfb_send_event(struct XenFB
*xenfb
, union xenfb_in_event
*event
)
658 struct xenfb_page
*page
= xenfb
->c
.page
;
660 prod
= page
->in_prod
;
661 /* caller ensures !xenfb_queue_full() */
662 xen_mb(); /* ensure ring space available */
663 XENFB_IN_RING_REF(page
, prod
) = *event
;
664 xen_wmb(); /* ensure ring contents visible */
665 page
->in_prod
= prod
+ 1;
667 xen_be_send_notify(&xenfb
->c
.xendev
);
670 static void xenfb_send_refresh_period(struct XenFB
*xenfb
, int period
)
672 union xenfb_in_event event
;
674 memset(&event
, 0, sizeof(event
));
675 event
.type
= XENFB_TYPE_REFRESH_PERIOD
;
676 event
.refresh_period
.period
= period
;
677 xenfb_send_event(xenfb
, &event
);
682 * Periodic update of display.
683 * Also transmit the refresh interval to the frontend.
685 * Never ever do any qemu display operations
686 * (resize, screen update) outside this function.
687 * Our screen might be inactive. When asked for
688 * an update we know it is active.
690 static void xenfb_update(void *opaque
)
692 struct XenFB
*xenfb
= opaque
;
693 DisplaySurface
*surface
;
696 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
699 if (!xenfb
->feature_update
) {
700 /* we don't get update notifications, thus use the
701 * sledge hammer approach ... */
702 xenfb
->up_fullscreen
= 1;
705 /* resize if needed */
706 if (xenfb
->do_resize
) {
707 pixman_format_code_t format
;
709 xenfb
->do_resize
= 0;
710 switch (xenfb
->depth
) {
713 /* console.c supported depth -> buffer can be used directly */
714 format
= qemu_default_pixman_format(xenfb
->depth
, true);
715 surface
= qemu_create_displaysurface_from
716 (xenfb
->width
, xenfb
->height
, format
,
717 xenfb
->row_stride
, xenfb
->pixels
+ xenfb
->offset
);
720 /* we must convert stuff */
721 surface
= qemu_create_displaysurface(xenfb
->width
, xenfb
->height
);
724 dpy_gfx_replace_surface(xenfb
->c
.con
, surface
);
725 xen_be_printf(&xenfb
->c
.xendev
, 1, "update: resizing: %dx%d @ %d bpp%s\n",
726 xenfb
->width
, xenfb
->height
, xenfb
->depth
,
727 is_buffer_shared(surface
) ? " (shared)" : "");
728 xenfb
->up_fullscreen
= 1;
731 /* run queued updates */
732 if (xenfb
->up_fullscreen
) {
733 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: fullscreen\n");
734 xenfb_guest_copy(xenfb
, 0, 0, xenfb
->width
, xenfb
->height
);
735 } else if (xenfb
->up_count
) {
736 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: %d rects\n", xenfb
->up_count
);
737 for (i
= 0; i
< xenfb
->up_count
; i
++)
738 xenfb_guest_copy(xenfb
,
739 xenfb
->up_rects
[i
].x
,
740 xenfb
->up_rects
[i
].y
,
741 xenfb
->up_rects
[i
].w
,
742 xenfb
->up_rects
[i
].h
);
744 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: nothing\n");
747 xenfb
->up_fullscreen
= 0;
750 static void xenfb_update_interval(void *opaque
, uint64_t interval
)
752 struct XenFB
*xenfb
= opaque
;
754 if (xenfb
->feature_update
) {
755 #ifdef XENFB_TYPE_REFRESH_PERIOD
756 if (xenfb_queue_full(xenfb
)) {
759 xenfb_send_refresh_period(xenfb
, interval
);
764 /* QEMU display state changed, so refresh the framebuffer copy */
765 static void xenfb_invalidate(void *opaque
)
767 struct XenFB
*xenfb
= opaque
;
768 xenfb
->up_fullscreen
= 1;
771 static void xenfb_handle_events(struct XenFB
*xenfb
)
773 uint32_t prod
, cons
, out_cons
;
774 struct xenfb_page
*page
= xenfb
->c
.page
;
776 prod
= page
->out_prod
;
777 out_cons
= page
->out_cons
;
778 if (prod
- out_cons
>= XENFB_OUT_RING_LEN
) {
781 xen_rmb(); /* ensure we see ring contents up to prod */
782 for (cons
= out_cons
; cons
!= prod
; cons
++) {
783 union xenfb_out_event
*event
= &XENFB_OUT_RING_REF(page
, cons
);
784 uint8_t type
= event
->type
;
788 case XENFB_TYPE_UPDATE
:
789 if (xenfb
->up_count
== UP_QUEUE
)
790 xenfb
->up_fullscreen
= 1;
791 if (xenfb
->up_fullscreen
)
793 x
= MAX(event
->update
.x
, 0);
794 y
= MAX(event
->update
.y
, 0);
795 w
= MIN(event
->update
.width
, xenfb
->width
- x
);
796 h
= MIN(event
->update
.height
, xenfb
->height
- y
);
797 if (w
< 0 || h
< 0) {
798 xen_be_printf(&xenfb
->c
.xendev
, 1, "bogus update ignored\n");
801 if (x
!= event
->update
.x
||
802 y
!= event
->update
.y
||
803 w
!= event
->update
.width
||
804 h
!= event
->update
.height
) {
805 xen_be_printf(&xenfb
->c
.xendev
, 1, "bogus update clipped\n");
807 if (w
== xenfb
->width
&& h
> xenfb
->height
/ 2) {
808 /* scroll detector: updated more than 50% of the lines,
809 * don't bother keeping track of the rectangles then */
810 xenfb
->up_fullscreen
= 1;
812 xenfb
->up_rects
[xenfb
->up_count
].x
= x
;
813 xenfb
->up_rects
[xenfb
->up_count
].y
= y
;
814 xenfb
->up_rects
[xenfb
->up_count
].w
= w
;
815 xenfb
->up_rects
[xenfb
->up_count
].h
= h
;
819 #ifdef XENFB_TYPE_RESIZE
820 case XENFB_TYPE_RESIZE
:
821 if (xenfb_configure_fb(xenfb
, xenfb
->fb_len
,
823 event
->resize
.height
,
826 event
->resize
.offset
,
827 event
->resize
.stride
) < 0)
829 xenfb_invalidate(xenfb
);
834 xen_mb(); /* ensure we're done with ring contents */
835 page
->out_cons
= cons
;
838 static int fb_init(struct XenDevice
*xendev
)
840 #ifdef XENFB_TYPE_RESIZE
841 xenstore_write_be_int(xendev
, "feature-resize", 1);
846 static int fb_initialise(struct XenDevice
*xendev
)
848 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
849 struct xenfb_page
*fb_page
;
853 if (xenstore_read_fe_int(xendev
, "videoram", &videoram
) == -1)
856 rc
= common_bind(&fb
->c
);
860 fb_page
= fb
->c
.page
;
861 rc
= xenfb_configure_fb(fb
, videoram
* 1024 * 1024U,
862 fb_page
->width
, fb_page
->height
, fb_page
->depth
,
863 fb_page
->mem_length
, 0, fb_page
->line_length
);
867 rc
= xenfb_map_fb(fb
);
871 #if 0 /* handled in xen_init_display() for now */
872 if (!fb
->have_console
) {
873 fb
->c
.ds
= graphic_console_init(xenfb_update
,
878 fb
->have_console
= 1;
882 if (xenstore_read_fe_int(xendev
, "feature-update", &fb
->feature_update
) == -1)
883 fb
->feature_update
= 0;
884 if (fb
->feature_update
)
885 xenstore_write_be_int(xendev
, "request-update", 1);
887 xen_be_printf(xendev
, 1, "feature-update=%d, videoram=%d\n",
888 fb
->feature_update
, videoram
);
892 static void fb_disconnect(struct XenDevice
*xendev
)
894 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
897 * FIXME: qemu can't un-init gfx display (yet?).
898 * Replacing the framebuffer with anonymous shared memory
899 * instead. This releases the guest pages and keeps qemu happy.
901 xenforeignmemory_unmap(xen_fmem
, fb
->pixels
, fb
->fbpages
);
902 fb
->pixels
= mmap(fb
->pixels
, fb
->fbpages
* XC_PAGE_SIZE
,
903 PROT_READ
| PROT_WRITE
, MAP_SHARED
| MAP_ANON
,
905 if (fb
->pixels
== MAP_FAILED
) {
906 xen_be_printf(xendev
, 0,
907 "Couldn't replace the framebuffer with anonymous memory errno=%d\n",
910 common_unbind(&fb
->c
);
911 fb
->feature_update
= 0;
915 static void fb_frontend_changed(struct XenDevice
*xendev
, const char *node
)
917 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
920 * Set state to Connected *again* once the frontend switched
921 * to connected. We must trigger the watch a second time to
922 * workaround a frontend bug.
924 if (fb
->bug_trigger
== 0 && strcmp(node
, "state") == 0 &&
925 xendev
->fe_state
== XenbusStateConnected
&&
926 xendev
->be_state
== XenbusStateConnected
) {
927 xen_be_printf(xendev
, 2, "re-trigger connected (frontend bug)\n");
928 xen_be_set_state(xendev
, XenbusStateConnected
);
929 fb
->bug_trigger
= 1; /* only once */
933 static void fb_event(struct XenDevice
*xendev
)
935 struct XenFB
*xenfb
= container_of(xendev
, struct XenFB
, c
.xendev
);
937 xenfb_handle_events(xenfb
);
938 xen_be_send_notify(&xenfb
->c
.xendev
);
941 /* -------------------------------------------------------------------- */
943 struct XenDevOps xen_kbdmouse_ops
= {
944 .size
= sizeof(struct XenInput
),
946 .initialise
= input_initialise
,
947 .connected
= input_connected
,
948 .disconnect
= input_disconnect
,
949 .event
= input_event
,
952 struct XenDevOps xen_framebuffer_ops
= {
953 .size
= sizeof(struct XenFB
),
955 .initialise
= fb_initialise
,
956 .disconnect
= fb_disconnect
,
958 .frontend_changed
= fb_frontend_changed
,
961 static const GraphicHwOps xenfb_ops
= {
962 .invalidate
= xenfb_invalidate
,
963 .gfx_update
= xenfb_update
,
964 .update_interval
= xenfb_update_interval
,
968 * FIXME/TODO: Kill this.
969 * Temporary needed while DisplayState reorganization is in flight.
971 void xen_init_display(int domid
)
973 struct XenDevice
*xfb
, *xin
;
980 main_loop_wait(true);
981 xfb
= xen_be_find_xendev("vfb", domid
, 0);
982 xin
= xen_be_find_xendev("vkbd", domid
, 0);
988 xen_be_printf(NULL
, 1, "displaystate setup failed\n");
993 fb
= container_of(xfb
, struct XenFB
, c
.xendev
);
994 fb
->c
.con
= graphic_console_init(NULL
, 0, &xenfb_ops
, fb
);
995 fb
->have_console
= 1;
998 in
= container_of(xin
, struct XenInput
, c
.xendev
);
999 in
->c
.con
= fb
->c
.con
;
1001 /* retry ->init() */
1002 xen_be_check_state(xin
);
1003 xen_be_check_state(xfb
);