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"
30 #include "ui/console.h"
31 #include "hw/xen/xen_backend.h"
33 #include <xen/event_channel.h>
34 #include <xen/io/fbif.h>
35 #include <xen/io/kbdif.h>
36 #include <xen/io/protocols.h>
41 #define BTN_LEFT 0x110 /* from <linux/input.h> */
44 /* -------------------------------------------------------------------- */
47 struct XenDevice xendev
; /* must be first */
53 int abs_pointer_wanted
; /* Whether guest supports absolute pointer */
54 int button_state
; /* Last seen pointer button state */
56 QEMUPutMouseEntry
*qmouse
;
82 static const GraphicHwOps xenfb_ops
;
84 /* -------------------------------------------------------------------- */
86 static int common_bind(struct common
*c
)
91 if (xenstore_read_fe_uint64(&c
->xendev
, "page-ref", &val
) == -1)
96 if (xenstore_read_fe_int(&c
->xendev
, "event-channel", &c
->xendev
.remote_port
) == -1)
99 c
->page
= xenforeignmemory_map(xen_fmem
, c
->xendev
.dom
,
100 PROT_READ
| PROT_WRITE
, 1, &mfn
, NULL
);
104 xen_be_bind_evtchn(&c
->xendev
);
105 xen_pv_printf(&c
->xendev
, 1,
106 "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_pv_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_pv_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 QemuConsole
*con
= qemu_console_lookup_by_index(0);
310 DisplaySurface
*surface
;
314 xen_pv_printf(&xenfb
->c
.xendev
, 0, "No QEMU console available");
318 surface
= qemu_console_surface(con
);
319 dw
= surface_width(surface
);
320 dh
= surface_height(surface
);
322 trace_xenfb_mouse_event(opaque
, dx
, dy
, dz
, button_state
,
323 xenfb
->abs_pointer_wanted
);
324 if (xenfb
->abs_pointer_wanted
)
325 xenfb_send_position(xenfb
,
326 dx
* (dw
- 1) / 0x7fff,
327 dy
* (dh
- 1) / 0x7fff,
330 xenfb_send_motion(xenfb
, dx
, dy
, dz
);
332 for (i
= 0 ; i
< 8 ; i
++) {
333 int lastDown
= xenfb
->button_state
& (1 << i
);
334 int down
= button_state
& (1 << i
);
335 if (down
== lastDown
)
338 if (xenfb_send_key(xenfb
, down
, BTN_LEFT
+i
) < 0)
341 xenfb
->button_state
= button_state
;
344 static int input_init(struct XenDevice
*xendev
)
346 xenstore_write_be_int(xendev
, "feature-abs-pointer", 1);
350 static int input_initialise(struct XenDevice
*xendev
)
352 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
355 rc
= common_bind(&in
->c
);
359 qemu_add_kbd_event_handler(xenfb_key_event
, in
);
363 static void input_connected(struct XenDevice
*xendev
)
365 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
367 if (xenstore_read_fe_int(xendev
, "request-abs-pointer",
368 &in
->abs_pointer_wanted
) == -1) {
369 in
->abs_pointer_wanted
= 0;
373 qemu_remove_mouse_event_handler(in
->qmouse
);
375 trace_xenfb_input_connected(xendev
, in
->abs_pointer_wanted
);
376 in
->qmouse
= qemu_add_mouse_event_handler(xenfb_mouse_event
, in
,
377 in
->abs_pointer_wanted
,
381 static void input_disconnect(struct XenDevice
*xendev
)
383 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
386 qemu_remove_mouse_event_handler(in
->qmouse
);
389 qemu_add_kbd_event_handler(NULL
, NULL
);
390 common_unbind(&in
->c
);
393 static void input_event(struct XenDevice
*xendev
)
395 struct XenInput
*xenfb
= container_of(xendev
, struct XenInput
, c
.xendev
);
396 struct xenkbd_page
*page
= xenfb
->c
.page
;
398 /* We don't understand any keyboard events, so just ignore them. */
399 if (page
->out_prod
== page
->out_cons
)
401 page
->out_cons
= page
->out_prod
;
402 xen_pv_send_notify(&xenfb
->c
.xendev
);
405 /* -------------------------------------------------------------------- */
407 static void xenfb_copy_mfns(int mode
, int count
, xen_pfn_t
*dst
, void *src
)
409 uint32_t *src32
= src
;
410 uint64_t *src64
= src
;
413 for (i
= 0; i
< count
; i
++)
414 dst
[i
] = (mode
== 32) ? src32
[i
] : src64
[i
];
417 static int xenfb_map_fb(struct XenFB
*xenfb
)
419 struct xenfb_page
*page
= xenfb
->c
.page
;
420 char *protocol
= xenfb
->c
.xendev
.protocol
;
422 xen_pfn_t
*pgmfns
= NULL
;
423 xen_pfn_t
*fbmfns
= NULL
;
427 /* default to native */
429 mode
= sizeof(unsigned long) * 8;
433 * Undefined protocol, some guesswork needed.
435 * Old frontends which don't set the protocol use
436 * one page directory only, thus pd[1] must be zero.
437 * pd[1] of the 32bit struct layout and the lower
438 * 32 bits of pd[0] of the 64bit struct layout have
439 * the same location, so we can check that ...
441 uint32_t *ptr32
= NULL
;
442 uint32_t *ptr64
= NULL
;
443 #if defined(__i386__)
444 ptr32
= (void*)page
->pd
;
445 ptr64
= ((void*)page
->pd
) + 4;
446 #elif defined(__x86_64__)
447 ptr32
= ((void*)page
->pd
) - 4;
448 ptr64
= (void*)page
->pd
;
459 #if defined(__x86_64__)
460 } else if (strcmp(protocol
, XEN_IO_PROTO_ABI_X86_32
) == 0) {
461 /* 64bit dom0, 32bit domU */
463 pd
= ((void*)page
->pd
) - 4;
464 #elif defined(__i386__)
465 } else if (strcmp(protocol
, XEN_IO_PROTO_ABI_X86_64
) == 0) {
466 /* 32bit dom0, 64bit domU */
468 pd
= ((void*)page
->pd
) + 4;
473 munmap(xenfb
->pixels
, xenfb
->fbpages
* XC_PAGE_SIZE
);
474 xenfb
->pixels
= NULL
;
477 xenfb
->fbpages
= DIV_ROUND_UP(xenfb
->fb_len
, XC_PAGE_SIZE
);
478 n_fbdirs
= xenfb
->fbpages
* mode
/ 8;
479 n_fbdirs
= DIV_ROUND_UP(n_fbdirs
, XC_PAGE_SIZE
);
481 pgmfns
= g_malloc0(sizeof(xen_pfn_t
) * n_fbdirs
);
482 fbmfns
= g_malloc0(sizeof(xen_pfn_t
) * xenfb
->fbpages
);
484 xenfb_copy_mfns(mode
, n_fbdirs
, pgmfns
, pd
);
485 map
= xenforeignmemory_map(xen_fmem
, xenfb
->c
.xendev
.dom
,
486 PROT_READ
, n_fbdirs
, pgmfns
, NULL
);
489 xenfb_copy_mfns(mode
, xenfb
->fbpages
, fbmfns
, map
);
490 xenforeignmemory_unmap(xen_fmem
, map
, n_fbdirs
);
492 xenfb
->pixels
= xenforeignmemory_map(xen_fmem
, xenfb
->c
.xendev
.dom
,
493 PROT_READ
, xenfb
->fbpages
, fbmfns
, NULL
);
494 if (xenfb
->pixels
== NULL
)
497 ret
= 0; /* all is fine */
505 static int xenfb_configure_fb(struct XenFB
*xenfb
, size_t fb_len_lim
,
506 int width
, int height
, int depth
,
507 size_t fb_len
, int offset
, int row_stride
)
509 size_t mfn_sz
= sizeof(*((struct xenfb_page
*)0)->pd
);
510 size_t pd_len
= sizeof(((struct xenfb_page
*)0)->pd
) / mfn_sz
;
511 size_t fb_pages
= pd_len
* XC_PAGE_SIZE
/ mfn_sz
;
512 size_t fb_len_max
= fb_pages
* XC_PAGE_SIZE
;
513 int max_width
, max_height
;
515 if (fb_len_lim
> fb_len_max
) {
516 xen_pv_printf(&xenfb
->c
.xendev
, 0,
517 "fb size limit %zu exceeds %zu, corrected\n",
518 fb_len_lim
, fb_len_max
);
519 fb_len_lim
= fb_len_max
;
521 if (fb_len_lim
&& fb_len
> fb_len_lim
) {
522 xen_pv_printf(&xenfb
->c
.xendev
, 0,
523 "frontend fb size %zu limited to %zu\n",
527 if (depth
!= 8 && depth
!= 16 && depth
!= 24 && depth
!= 32) {
528 xen_pv_printf(&xenfb
->c
.xendev
, 0,
529 "can't handle frontend fb depth %d\n",
533 if (row_stride
<= 0 || row_stride
> fb_len
) {
534 xen_pv_printf(&xenfb
->c
.xendev
, 0, "invalid frontend stride %d\n",
538 max_width
= row_stride
/ (depth
/ 8);
539 if (width
< 0 || width
> max_width
) {
540 xen_pv_printf(&xenfb
->c
.xendev
, 0,
541 "invalid frontend width %d limited to %d\n",
545 if (offset
< 0 || offset
>= fb_len
) {
546 xen_pv_printf(&xenfb
->c
.xendev
, 0,
547 "invalid frontend offset %d (max %zu)\n",
551 max_height
= (fb_len
- offset
) / row_stride
;
552 if (height
< 0 || height
> max_height
) {
553 xen_pv_printf(&xenfb
->c
.xendev
, 0,
554 "invalid frontend height %d limited to %d\n",
558 xenfb
->fb_len
= fb_len
;
559 xenfb
->row_stride
= row_stride
;
560 xenfb
->depth
= depth
;
561 xenfb
->width
= width
;
562 xenfb
->height
= height
;
563 xenfb
->offset
= offset
;
564 xenfb
->up_fullscreen
= 1;
565 xenfb
->do_resize
= 1;
566 xen_pv_printf(&xenfb
->c
.xendev
, 1,
567 "framebuffer %dx%dx%d offset %d stride %d\n",
568 width
, height
, depth
, offset
, row_stride
);
572 /* A convenient function for munging pixels between different depths */
573 #define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB) \
574 for (line = y ; line < (y+h) ; line++) { \
575 SRC_T *src = (SRC_T *)(xenfb->pixels \
577 + (line * xenfb->row_stride) \
578 + (x * xenfb->depth / 8)); \
579 DST_T *dst = (DST_T *)(data \
580 + (line * linesize) \
583 const int RSS = 32 - (RSB + GSB + BSB); \
584 const int GSS = 32 - (GSB + BSB); \
585 const int BSS = 32 - (BSB); \
586 const uint32_t RSM = (~0U) << (32 - RSB); \
587 const uint32_t GSM = (~0U) << (32 - GSB); \
588 const uint32_t BSM = (~0U) << (32 - BSB); \
589 const int RDS = 32 - (RDB + GDB + BDB); \
590 const int GDS = 32 - (GDB + BDB); \
591 const int BDS = 32 - (BDB); \
592 const uint32_t RDM = (~0U) << (32 - RDB); \
593 const uint32_t GDM = (~0U) << (32 - GDB); \
594 const uint32_t BDM = (~0U) << (32 - BDB); \
595 for (col = x ; col < (x+w) ; col++) { \
596 uint32_t spix = *src; \
597 *dst = (((spix << RSS) & RSM & RDM) >> RDS) | \
598 (((spix << GSS) & GSM & GDM) >> GDS) | \
599 (((spix << BSS) & BSM & BDM) >> BDS); \
600 src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8); \
601 dst = (DST_T *) ((unsigned long) dst + bpp / 8); \
607 * This copies data from the guest framebuffer region, into QEMU's
608 * displaysurface. qemu uses 16 or 32 bpp. In case the pv framebuffer
609 * uses something else we must convert and copy, otherwise we can
610 * supply the buffer directly and no thing here.
612 static void xenfb_guest_copy(struct XenFB
*xenfb
, int x
, int y
, int w
, int h
)
614 DisplaySurface
*surface
= qemu_console_surface(xenfb
->con
);
616 int bpp
= surface_bits_per_pixel(surface
);
617 int linesize
= surface_stride(surface
);
618 uint8_t *data
= surface_data(surface
);
620 if (!is_buffer_shared(surface
)) {
621 switch (xenfb
->depth
) {
624 BLT(uint8_t, uint16_t, 3, 3, 2, 5, 6, 5);
625 } else if (bpp
== 32) {
626 BLT(uint8_t, uint32_t, 3, 3, 2, 8, 8, 8);
633 BLT(uint32_t, uint16_t, 8, 8, 8, 5, 6, 5);
634 } else if (bpp
== 32) {
635 BLT(uint32_t, uint32_t, 8, 8, 8, 8, 8, 8);
644 if (oops
) /* should not happen */
645 xen_pv_printf(&xenfb
->c
.xendev
, 0, "%s: oops: convert %d -> %d bpp?\n",
646 __FUNCTION__
, xenfb
->depth
, bpp
);
648 dpy_gfx_update(xenfb
->con
, x
, y
, w
, h
);
651 #ifdef XENFB_TYPE_REFRESH_PERIOD
652 static int xenfb_queue_full(struct XenFB
*xenfb
)
654 struct xenfb_page
*page
= xenfb
->c
.page
;
660 prod
= page
->in_prod
;
661 cons
= page
->in_cons
;
662 return prod
- cons
== XENFB_IN_RING_LEN
;
665 static void xenfb_send_event(struct XenFB
*xenfb
, union xenfb_in_event
*event
)
668 struct xenfb_page
*page
= xenfb
->c
.page
;
670 prod
= page
->in_prod
;
671 /* caller ensures !xenfb_queue_full() */
672 xen_mb(); /* ensure ring space available */
673 XENFB_IN_RING_REF(page
, prod
) = *event
;
674 xen_wmb(); /* ensure ring contents visible */
675 page
->in_prod
= prod
+ 1;
677 xen_pv_send_notify(&xenfb
->c
.xendev
);
680 static void xenfb_send_refresh_period(struct XenFB
*xenfb
, int period
)
682 union xenfb_in_event event
;
684 memset(&event
, 0, sizeof(event
));
685 event
.type
= XENFB_TYPE_REFRESH_PERIOD
;
686 event
.refresh_period
.period
= period
;
687 xenfb_send_event(xenfb
, &event
);
692 * Periodic update of display.
693 * Also transmit the refresh interval to the frontend.
695 * Never ever do any qemu display operations
696 * (resize, screen update) outside this function.
697 * Our screen might be inactive. When asked for
698 * an update we know it is active.
700 static void xenfb_update(void *opaque
)
702 struct XenFB
*xenfb
= opaque
;
703 DisplaySurface
*surface
;
706 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
709 if (!xenfb
->feature_update
) {
710 /* we don't get update notifications, thus use the
711 * sledge hammer approach ... */
712 xenfb
->up_fullscreen
= 1;
715 /* resize if needed */
716 if (xenfb
->do_resize
) {
717 pixman_format_code_t format
;
719 xenfb
->do_resize
= 0;
720 switch (xenfb
->depth
) {
723 /* console.c supported depth -> buffer can be used directly */
724 format
= qemu_default_pixman_format(xenfb
->depth
, true);
725 surface
= qemu_create_displaysurface_from
726 (xenfb
->width
, xenfb
->height
, format
,
727 xenfb
->row_stride
, xenfb
->pixels
+ xenfb
->offset
);
730 /* we must convert stuff */
731 surface
= qemu_create_displaysurface(xenfb
->width
, xenfb
->height
);
734 dpy_gfx_replace_surface(xenfb
->con
, surface
);
735 xen_pv_printf(&xenfb
->c
.xendev
, 1,
736 "update: resizing: %dx%d @ %d bpp%s\n",
737 xenfb
->width
, xenfb
->height
, xenfb
->depth
,
738 is_buffer_shared(surface
) ? " (shared)" : "");
739 xenfb
->up_fullscreen
= 1;
742 /* run queued updates */
743 if (xenfb
->up_fullscreen
) {
744 xen_pv_printf(&xenfb
->c
.xendev
, 3, "update: fullscreen\n");
745 xenfb_guest_copy(xenfb
, 0, 0, xenfb
->width
, xenfb
->height
);
746 } else if (xenfb
->up_count
) {
747 xen_pv_printf(&xenfb
->c
.xendev
, 3, "update: %d rects\n",
749 for (i
= 0; i
< xenfb
->up_count
; i
++)
750 xenfb_guest_copy(xenfb
,
751 xenfb
->up_rects
[i
].x
,
752 xenfb
->up_rects
[i
].y
,
753 xenfb
->up_rects
[i
].w
,
754 xenfb
->up_rects
[i
].h
);
756 xen_pv_printf(&xenfb
->c
.xendev
, 3, "update: nothing\n");
759 xenfb
->up_fullscreen
= 0;
762 static void xenfb_update_interval(void *opaque
, uint64_t interval
)
764 struct XenFB
*xenfb
= opaque
;
766 if (xenfb
->feature_update
) {
767 #ifdef XENFB_TYPE_REFRESH_PERIOD
768 if (xenfb_queue_full(xenfb
)) {
771 xenfb_send_refresh_period(xenfb
, interval
);
776 /* QEMU display state changed, so refresh the framebuffer copy */
777 static void xenfb_invalidate(void *opaque
)
779 struct XenFB
*xenfb
= opaque
;
780 xenfb
->up_fullscreen
= 1;
783 static void xenfb_handle_events(struct XenFB
*xenfb
)
785 uint32_t prod
, cons
, out_cons
;
786 struct xenfb_page
*page
= xenfb
->c
.page
;
788 prod
= page
->out_prod
;
789 out_cons
= page
->out_cons
;
790 if (prod
- out_cons
> XENFB_OUT_RING_LEN
) {
793 xen_rmb(); /* ensure we see ring contents up to prod */
794 for (cons
= out_cons
; cons
!= prod
; cons
++) {
795 union xenfb_out_event
*event
= &XENFB_OUT_RING_REF(page
, cons
);
796 uint8_t type
= event
->type
;
800 case XENFB_TYPE_UPDATE
:
801 if (xenfb
->up_count
== UP_QUEUE
)
802 xenfb
->up_fullscreen
= 1;
803 if (xenfb
->up_fullscreen
)
805 x
= MAX(event
->update
.x
, 0);
806 y
= MAX(event
->update
.y
, 0);
807 w
= MIN(event
->update
.width
, xenfb
->width
- x
);
808 h
= MIN(event
->update
.height
, xenfb
->height
- y
);
809 if (w
< 0 || h
< 0) {
810 xen_pv_printf(&xenfb
->c
.xendev
, 1, "bogus update ignored\n");
813 if (x
!= event
->update
.x
||
814 y
!= event
->update
.y
||
815 w
!= event
->update
.width
||
816 h
!= event
->update
.height
) {
817 xen_pv_printf(&xenfb
->c
.xendev
, 1, "bogus update clipped\n");
819 if (w
== xenfb
->width
&& h
> xenfb
->height
/ 2) {
820 /* scroll detector: updated more than 50% of the lines,
821 * don't bother keeping track of the rectangles then */
822 xenfb
->up_fullscreen
= 1;
824 xenfb
->up_rects
[xenfb
->up_count
].x
= x
;
825 xenfb
->up_rects
[xenfb
->up_count
].y
= y
;
826 xenfb
->up_rects
[xenfb
->up_count
].w
= w
;
827 xenfb
->up_rects
[xenfb
->up_count
].h
= h
;
831 #ifdef XENFB_TYPE_RESIZE
832 case XENFB_TYPE_RESIZE
:
833 if (xenfb_configure_fb(xenfb
, xenfb
->fb_len
,
835 event
->resize
.height
,
838 event
->resize
.offset
,
839 event
->resize
.stride
) < 0)
841 xenfb_invalidate(xenfb
);
846 xen_mb(); /* ensure we're done with ring contents */
847 page
->out_cons
= cons
;
850 static int fb_init(struct XenDevice
*xendev
)
852 #ifdef XENFB_TYPE_RESIZE
853 xenstore_write_be_int(xendev
, "feature-resize", 1);
858 static int fb_initialise(struct XenDevice
*xendev
)
860 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
861 struct xenfb_page
*fb_page
;
865 if (xenstore_read_fe_int(xendev
, "videoram", &videoram
) == -1)
868 rc
= common_bind(&fb
->c
);
872 fb_page
= fb
->c
.page
;
873 rc
= xenfb_configure_fb(fb
, videoram
* 1024 * 1024U,
874 fb_page
->width
, fb_page
->height
, fb_page
->depth
,
875 fb_page
->mem_length
, 0, fb_page
->line_length
);
879 rc
= xenfb_map_fb(fb
);
883 fb
->con
= graphic_console_init(NULL
, 0, &xenfb_ops
, fb
);
885 if (xenstore_read_fe_int(xendev
, "feature-update", &fb
->feature_update
) == -1)
886 fb
->feature_update
= 0;
887 if (fb
->feature_update
)
888 xenstore_write_be_int(xendev
, "request-update", 1);
890 xen_pv_printf(xendev
, 1, "feature-update=%d, videoram=%d\n",
891 fb
->feature_update
, videoram
);
895 static void fb_disconnect(struct XenDevice
*xendev
)
897 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
900 * FIXME: qemu can't un-init gfx display (yet?).
901 * Replacing the framebuffer with anonymous shared memory
902 * instead. This releases the guest pages and keeps qemu happy.
904 xenforeignmemory_unmap(xen_fmem
, fb
->pixels
, fb
->fbpages
);
905 fb
->pixels
= mmap(fb
->pixels
, fb
->fbpages
* XC_PAGE_SIZE
,
906 PROT_READ
| PROT_WRITE
, MAP_SHARED
| MAP_ANON
,
908 if (fb
->pixels
== MAP_FAILED
) {
909 xen_pv_printf(xendev
, 0,
910 "Couldn't replace the framebuffer with anonymous memory errno=%d\n",
913 common_unbind(&fb
->c
);
914 fb
->feature_update
= 0;
918 static void fb_frontend_changed(struct XenDevice
*xendev
, const char *node
)
920 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
923 * Set state to Connected *again* once the frontend switched
924 * to connected. We must trigger the watch a second time to
925 * workaround a frontend bug.
927 if (fb
->bug_trigger
== 0 && strcmp(node
, "state") == 0 &&
928 xendev
->fe_state
== XenbusStateConnected
&&
929 xendev
->be_state
== XenbusStateConnected
) {
930 xen_pv_printf(xendev
, 2, "re-trigger connected (frontend bug)\n");
931 xen_be_set_state(xendev
, XenbusStateConnected
);
932 fb
->bug_trigger
= 1; /* only once */
936 static void fb_event(struct XenDevice
*xendev
)
938 struct XenFB
*xenfb
= container_of(xendev
, struct XenFB
, c
.xendev
);
940 xenfb_handle_events(xenfb
);
941 xen_pv_send_notify(&xenfb
->c
.xendev
);
944 /* -------------------------------------------------------------------- */
946 struct XenDevOps xen_kbdmouse_ops
= {
947 .size
= sizeof(struct XenInput
),
949 .initialise
= input_initialise
,
950 .connected
= input_connected
,
951 .disconnect
= input_disconnect
,
952 .event
= input_event
,
955 struct XenDevOps xen_framebuffer_ops
= {
956 .size
= sizeof(struct XenFB
),
958 .initialise
= fb_initialise
,
959 .disconnect
= fb_disconnect
,
961 .frontend_changed
= fb_frontend_changed
,
964 static const GraphicHwOps xenfb_ops
= {
965 .invalidate
= xenfb_invalidate
,
966 .gfx_update
= xenfb_update
,
967 .update_interval
= xenfb_update_interval
,