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 trace_xenfb_key_event(opaque
, scancode2linux
[scancode
], down
);
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 QemuConsole
*con
= qemu_console_lookup_by_index(0);
311 DisplaySurface
*surface
;
315 xen_pv_printf(&xenfb
->c
.xendev
, 0, "No QEMU console available");
319 surface
= qemu_console_surface(con
);
320 dw
= surface_width(surface
);
321 dh
= surface_height(surface
);
323 trace_xenfb_mouse_event(opaque
, dx
, dy
, dz
, button_state
,
324 xenfb
->abs_pointer_wanted
);
325 if (xenfb
->abs_pointer_wanted
)
326 xenfb_send_position(xenfb
,
327 dx
* (dw
- 1) / 0x7fff,
328 dy
* (dh
- 1) / 0x7fff,
331 xenfb_send_motion(xenfb
, dx
, dy
, dz
);
333 for (i
= 0 ; i
< 8 ; i
++) {
334 int lastDown
= xenfb
->button_state
& (1 << i
);
335 int down
= button_state
& (1 << i
);
336 if (down
== lastDown
)
339 if (xenfb_send_key(xenfb
, down
, BTN_LEFT
+i
) < 0)
342 xenfb
->button_state
= button_state
;
345 static int input_init(struct XenDevice
*xendev
)
347 xenstore_write_be_int(xendev
, "feature-abs-pointer", 1);
351 static int input_initialise(struct XenDevice
*xendev
)
353 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
356 rc
= common_bind(&in
->c
);
360 qemu_add_kbd_event_handler(xenfb_key_event
, in
);
364 static void input_connected(struct XenDevice
*xendev
)
366 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
368 if (xenstore_read_fe_int(xendev
, "request-abs-pointer",
369 &in
->abs_pointer_wanted
) == -1) {
370 in
->abs_pointer_wanted
= 0;
374 qemu_remove_mouse_event_handler(in
->qmouse
);
376 trace_xenfb_input_connected(xendev
, in
->abs_pointer_wanted
);
377 in
->qmouse
= qemu_add_mouse_event_handler(xenfb_mouse_event
, in
,
378 in
->abs_pointer_wanted
,
382 static void input_disconnect(struct XenDevice
*xendev
)
384 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
387 qemu_remove_mouse_event_handler(in
->qmouse
);
390 qemu_add_kbd_event_handler(NULL
, NULL
);
391 common_unbind(&in
->c
);
394 static void input_event(struct XenDevice
*xendev
)
396 struct XenInput
*xenfb
= container_of(xendev
, struct XenInput
, c
.xendev
);
397 struct xenkbd_page
*page
= xenfb
->c
.page
;
399 /* We don't understand any keyboard events, so just ignore them. */
400 if (page
->out_prod
== page
->out_cons
)
402 page
->out_cons
= page
->out_prod
;
403 xen_pv_send_notify(&xenfb
->c
.xendev
);
406 /* -------------------------------------------------------------------- */
408 static void xenfb_copy_mfns(int mode
, int count
, xen_pfn_t
*dst
, void *src
)
410 uint32_t *src32
= src
;
411 uint64_t *src64
= src
;
414 for (i
= 0; i
< count
; i
++)
415 dst
[i
] = (mode
== 32) ? src32
[i
] : src64
[i
];
418 static int xenfb_map_fb(struct XenFB
*xenfb
)
420 struct xenfb_page
*page
= xenfb
->c
.page
;
421 char *protocol
= xenfb
->c
.xendev
.protocol
;
423 xen_pfn_t
*pgmfns
= NULL
;
424 xen_pfn_t
*fbmfns
= NULL
;
428 /* default to native */
430 mode
= sizeof(unsigned long) * 8;
434 * Undefined protocol, some guesswork needed.
436 * Old frontends which don't set the protocol use
437 * one page directory only, thus pd[1] must be zero.
438 * pd[1] of the 32bit struct layout and the lower
439 * 32 bits of pd[0] of the 64bit struct layout have
440 * the same location, so we can check that ...
442 uint32_t *ptr32
= NULL
;
443 uint32_t *ptr64
= NULL
;
444 #if defined(__i386__)
445 ptr32
= (void*)page
->pd
;
446 ptr64
= ((void*)page
->pd
) + 4;
447 #elif defined(__x86_64__)
448 ptr32
= ((void*)page
->pd
) - 4;
449 ptr64
= (void*)page
->pd
;
460 #if defined(__x86_64__)
461 } else if (strcmp(protocol
, XEN_IO_PROTO_ABI_X86_32
) == 0) {
462 /* 64bit dom0, 32bit domU */
464 pd
= ((void*)page
->pd
) - 4;
465 #elif defined(__i386__)
466 } else if (strcmp(protocol
, XEN_IO_PROTO_ABI_X86_64
) == 0) {
467 /* 32bit dom0, 64bit domU */
469 pd
= ((void*)page
->pd
) + 4;
474 munmap(xenfb
->pixels
, xenfb
->fbpages
* XC_PAGE_SIZE
);
475 xenfb
->pixels
= NULL
;
478 xenfb
->fbpages
= DIV_ROUND_UP(xenfb
->fb_len
, XC_PAGE_SIZE
);
479 n_fbdirs
= xenfb
->fbpages
* mode
/ 8;
480 n_fbdirs
= DIV_ROUND_UP(n_fbdirs
, XC_PAGE_SIZE
);
482 pgmfns
= g_malloc0(sizeof(xen_pfn_t
) * n_fbdirs
);
483 fbmfns
= g_malloc0(sizeof(xen_pfn_t
) * xenfb
->fbpages
);
485 xenfb_copy_mfns(mode
, n_fbdirs
, pgmfns
, pd
);
486 map
= xenforeignmemory_map(xen_fmem
, xenfb
->c
.xendev
.dom
,
487 PROT_READ
, n_fbdirs
, pgmfns
, NULL
);
490 xenfb_copy_mfns(mode
, xenfb
->fbpages
, fbmfns
, map
);
491 xenforeignmemory_unmap(xen_fmem
, map
, n_fbdirs
);
493 xenfb
->pixels
= xenforeignmemory_map(xen_fmem
, xenfb
->c
.xendev
.dom
,
494 PROT_READ
, xenfb
->fbpages
, fbmfns
, NULL
);
495 if (xenfb
->pixels
== NULL
)
498 ret
= 0; /* all is fine */
506 static int xenfb_configure_fb(struct XenFB
*xenfb
, size_t fb_len_lim
,
507 int width
, int height
, int depth
,
508 size_t fb_len
, int offset
, int row_stride
)
510 size_t mfn_sz
= sizeof(*((struct xenfb_page
*)0)->pd
);
511 size_t pd_len
= sizeof(((struct xenfb_page
*)0)->pd
) / mfn_sz
;
512 size_t fb_pages
= pd_len
* XC_PAGE_SIZE
/ mfn_sz
;
513 size_t fb_len_max
= fb_pages
* XC_PAGE_SIZE
;
514 int max_width
, max_height
;
516 if (fb_len_lim
> fb_len_max
) {
517 xen_pv_printf(&xenfb
->c
.xendev
, 0,
518 "fb size limit %zu exceeds %zu, corrected\n",
519 fb_len_lim
, fb_len_max
);
520 fb_len_lim
= fb_len_max
;
522 if (fb_len_lim
&& fb_len
> fb_len_lim
) {
523 xen_pv_printf(&xenfb
->c
.xendev
, 0,
524 "frontend fb size %zu limited to %zu\n",
528 if (depth
!= 8 && depth
!= 16 && depth
!= 24 && depth
!= 32) {
529 xen_pv_printf(&xenfb
->c
.xendev
, 0,
530 "can't handle frontend fb depth %d\n",
534 if (row_stride
<= 0 || row_stride
> fb_len
) {
535 xen_pv_printf(&xenfb
->c
.xendev
, 0, "invalid frontend stride %d\n",
539 max_width
= row_stride
/ (depth
/ 8);
540 if (width
< 0 || width
> max_width
) {
541 xen_pv_printf(&xenfb
->c
.xendev
, 0,
542 "invalid frontend width %d limited to %d\n",
546 if (offset
< 0 || offset
>= fb_len
) {
547 xen_pv_printf(&xenfb
->c
.xendev
, 0,
548 "invalid frontend offset %d (max %zu)\n",
552 max_height
= (fb_len
- offset
) / row_stride
;
553 if (height
< 0 || height
> max_height
) {
554 xen_pv_printf(&xenfb
->c
.xendev
, 0,
555 "invalid frontend height %d limited to %d\n",
559 xenfb
->fb_len
= fb_len
;
560 xenfb
->row_stride
= row_stride
;
561 xenfb
->depth
= depth
;
562 xenfb
->width
= width
;
563 xenfb
->height
= height
;
564 xenfb
->offset
= offset
;
565 xenfb
->up_fullscreen
= 1;
566 xenfb
->do_resize
= 1;
567 xen_pv_printf(&xenfb
->c
.xendev
, 1,
568 "framebuffer %dx%dx%d offset %d stride %d\n",
569 width
, height
, depth
, offset
, row_stride
);
573 /* A convenient function for munging pixels between different depths */
574 #define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB) \
575 for (line = y ; line < (y+h) ; line++) { \
576 SRC_T *src = (SRC_T *)(xenfb->pixels \
578 + (line * xenfb->row_stride) \
579 + (x * xenfb->depth / 8)); \
580 DST_T *dst = (DST_T *)(data \
581 + (line * linesize) \
584 const int RSS = 32 - (RSB + GSB + BSB); \
585 const int GSS = 32 - (GSB + BSB); \
586 const int BSS = 32 - (BSB); \
587 const uint32_t RSM = (~0U) << (32 - RSB); \
588 const uint32_t GSM = (~0U) << (32 - GSB); \
589 const uint32_t BSM = (~0U) << (32 - BSB); \
590 const int RDS = 32 - (RDB + GDB + BDB); \
591 const int GDS = 32 - (GDB + BDB); \
592 const int BDS = 32 - (BDB); \
593 const uint32_t RDM = (~0U) << (32 - RDB); \
594 const uint32_t GDM = (~0U) << (32 - GDB); \
595 const uint32_t BDM = (~0U) << (32 - BDB); \
596 for (col = x ; col < (x+w) ; col++) { \
597 uint32_t spix = *src; \
598 *dst = (((spix << RSS) & RSM & RDM) >> RDS) | \
599 (((spix << GSS) & GSM & GDM) >> GDS) | \
600 (((spix << BSS) & BSM & BDM) >> BDS); \
601 src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8); \
602 dst = (DST_T *) ((unsigned long) dst + bpp / 8); \
608 * This copies data from the guest framebuffer region, into QEMU's
609 * displaysurface. qemu uses 16 or 32 bpp. In case the pv framebuffer
610 * uses something else we must convert and copy, otherwise we can
611 * supply the buffer directly and no thing here.
613 static void xenfb_guest_copy(struct XenFB
*xenfb
, int x
, int y
, int w
, int h
)
615 DisplaySurface
*surface
= qemu_console_surface(xenfb
->con
);
617 int bpp
= surface_bits_per_pixel(surface
);
618 int linesize
= surface_stride(surface
);
619 uint8_t *data
= surface_data(surface
);
621 if (!is_buffer_shared(surface
)) {
622 switch (xenfb
->depth
) {
625 BLT(uint8_t, uint16_t, 3, 3, 2, 5, 6, 5);
626 } else if (bpp
== 32) {
627 BLT(uint8_t, uint32_t, 3, 3, 2, 8, 8, 8);
634 BLT(uint32_t, uint16_t, 8, 8, 8, 5, 6, 5);
635 } else if (bpp
== 32) {
636 BLT(uint32_t, uint32_t, 8, 8, 8, 8, 8, 8);
645 if (oops
) /* should not happen */
646 xen_pv_printf(&xenfb
->c
.xendev
, 0, "%s: oops: convert %d -> %d bpp?\n",
647 __FUNCTION__
, xenfb
->depth
, bpp
);
649 dpy_gfx_update(xenfb
->con
, x
, y
, w
, h
);
652 #ifdef XENFB_TYPE_REFRESH_PERIOD
653 static int xenfb_queue_full(struct XenFB
*xenfb
)
655 struct xenfb_page
*page
= xenfb
->c
.page
;
661 prod
= page
->in_prod
;
662 cons
= page
->in_cons
;
663 return prod
- cons
== XENFB_IN_RING_LEN
;
666 static void xenfb_send_event(struct XenFB
*xenfb
, union xenfb_in_event
*event
)
669 struct xenfb_page
*page
= xenfb
->c
.page
;
671 prod
= page
->in_prod
;
672 /* caller ensures !xenfb_queue_full() */
673 xen_mb(); /* ensure ring space available */
674 XENFB_IN_RING_REF(page
, prod
) = *event
;
675 xen_wmb(); /* ensure ring contents visible */
676 page
->in_prod
= prod
+ 1;
678 xen_pv_send_notify(&xenfb
->c
.xendev
);
681 static void xenfb_send_refresh_period(struct XenFB
*xenfb
, int period
)
683 union xenfb_in_event event
;
685 memset(&event
, 0, sizeof(event
));
686 event
.type
= XENFB_TYPE_REFRESH_PERIOD
;
687 event
.refresh_period
.period
= period
;
688 xenfb_send_event(xenfb
, &event
);
693 * Periodic update of display.
694 * Also transmit the refresh interval to the frontend.
696 * Never ever do any qemu display operations
697 * (resize, screen update) outside this function.
698 * Our screen might be inactive. When asked for
699 * an update we know it is active.
701 static void xenfb_update(void *opaque
)
703 struct XenFB
*xenfb
= opaque
;
704 DisplaySurface
*surface
;
707 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
710 if (!xenfb
->feature_update
) {
711 /* we don't get update notifications, thus use the
712 * sledge hammer approach ... */
713 xenfb
->up_fullscreen
= 1;
716 /* resize if needed */
717 if (xenfb
->do_resize
) {
718 pixman_format_code_t format
;
720 xenfb
->do_resize
= 0;
721 switch (xenfb
->depth
) {
724 /* console.c supported depth -> buffer can be used directly */
725 format
= qemu_default_pixman_format(xenfb
->depth
, true);
726 surface
= qemu_create_displaysurface_from
727 (xenfb
->width
, xenfb
->height
, format
,
728 xenfb
->row_stride
, xenfb
->pixels
+ xenfb
->offset
);
731 /* we must convert stuff */
732 surface
= qemu_create_displaysurface(xenfb
->width
, xenfb
->height
);
735 dpy_gfx_replace_surface(xenfb
->con
, surface
);
736 xen_pv_printf(&xenfb
->c
.xendev
, 1,
737 "update: resizing: %dx%d @ %d bpp%s\n",
738 xenfb
->width
, xenfb
->height
, xenfb
->depth
,
739 is_buffer_shared(surface
) ? " (shared)" : "");
740 xenfb
->up_fullscreen
= 1;
743 /* run queued updates */
744 if (xenfb
->up_fullscreen
) {
745 xen_pv_printf(&xenfb
->c
.xendev
, 3, "update: fullscreen\n");
746 xenfb_guest_copy(xenfb
, 0, 0, xenfb
->width
, xenfb
->height
);
747 } else if (xenfb
->up_count
) {
748 xen_pv_printf(&xenfb
->c
.xendev
, 3, "update: %d rects\n",
750 for (i
= 0; i
< xenfb
->up_count
; i
++)
751 xenfb_guest_copy(xenfb
,
752 xenfb
->up_rects
[i
].x
,
753 xenfb
->up_rects
[i
].y
,
754 xenfb
->up_rects
[i
].w
,
755 xenfb
->up_rects
[i
].h
);
757 xen_pv_printf(&xenfb
->c
.xendev
, 3, "update: nothing\n");
760 xenfb
->up_fullscreen
= 0;
763 static void xenfb_update_interval(void *opaque
, uint64_t interval
)
765 struct XenFB
*xenfb
= opaque
;
767 if (xenfb
->feature_update
) {
768 #ifdef XENFB_TYPE_REFRESH_PERIOD
769 if (xenfb_queue_full(xenfb
)) {
772 xenfb_send_refresh_period(xenfb
, interval
);
777 /* QEMU display state changed, so refresh the framebuffer copy */
778 static void xenfb_invalidate(void *opaque
)
780 struct XenFB
*xenfb
= opaque
;
781 xenfb
->up_fullscreen
= 1;
784 static void xenfb_handle_events(struct XenFB
*xenfb
)
786 uint32_t prod
, cons
, out_cons
;
787 struct xenfb_page
*page
= xenfb
->c
.page
;
789 prod
= page
->out_prod
;
790 out_cons
= page
->out_cons
;
791 if (prod
- out_cons
> XENFB_OUT_RING_LEN
) {
794 xen_rmb(); /* ensure we see ring contents up to prod */
795 for (cons
= out_cons
; cons
!= prod
; cons
++) {
796 union xenfb_out_event
*event
= &XENFB_OUT_RING_REF(page
, cons
);
797 uint8_t type
= event
->type
;
801 case XENFB_TYPE_UPDATE
:
802 if (xenfb
->up_count
== UP_QUEUE
)
803 xenfb
->up_fullscreen
= 1;
804 if (xenfb
->up_fullscreen
)
806 x
= MAX(event
->update
.x
, 0);
807 y
= MAX(event
->update
.y
, 0);
808 w
= MIN(event
->update
.width
, xenfb
->width
- x
);
809 h
= MIN(event
->update
.height
, xenfb
->height
- y
);
810 if (w
< 0 || h
< 0) {
811 xen_pv_printf(&xenfb
->c
.xendev
, 1, "bogus update ignored\n");
814 if (x
!= event
->update
.x
||
815 y
!= event
->update
.y
||
816 w
!= event
->update
.width
||
817 h
!= event
->update
.height
) {
818 xen_pv_printf(&xenfb
->c
.xendev
, 1, "bogus update clipped\n");
820 if (w
== xenfb
->width
&& h
> xenfb
->height
/ 2) {
821 /* scroll detector: updated more than 50% of the lines,
822 * don't bother keeping track of the rectangles then */
823 xenfb
->up_fullscreen
= 1;
825 xenfb
->up_rects
[xenfb
->up_count
].x
= x
;
826 xenfb
->up_rects
[xenfb
->up_count
].y
= y
;
827 xenfb
->up_rects
[xenfb
->up_count
].w
= w
;
828 xenfb
->up_rects
[xenfb
->up_count
].h
= h
;
832 #ifdef XENFB_TYPE_RESIZE
833 case XENFB_TYPE_RESIZE
:
834 if (xenfb_configure_fb(xenfb
, xenfb
->fb_len
,
836 event
->resize
.height
,
839 event
->resize
.offset
,
840 event
->resize
.stride
) < 0)
842 xenfb_invalidate(xenfb
);
847 xen_mb(); /* ensure we're done with ring contents */
848 page
->out_cons
= cons
;
851 static int fb_init(struct XenDevice
*xendev
)
853 #ifdef XENFB_TYPE_RESIZE
854 xenstore_write_be_int(xendev
, "feature-resize", 1);
859 static int fb_initialise(struct XenDevice
*xendev
)
861 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
862 struct xenfb_page
*fb_page
;
866 if (xenstore_read_fe_int(xendev
, "videoram", &videoram
) == -1)
869 rc
= common_bind(&fb
->c
);
873 fb_page
= fb
->c
.page
;
874 rc
= xenfb_configure_fb(fb
, videoram
* 1024 * 1024U,
875 fb_page
->width
, fb_page
->height
, fb_page
->depth
,
876 fb_page
->mem_length
, 0, fb_page
->line_length
);
880 rc
= xenfb_map_fb(fb
);
884 fb
->con
= graphic_console_init(NULL
, 0, &xenfb_ops
, fb
);
886 if (xenstore_read_fe_int(xendev
, "feature-update", &fb
->feature_update
) == -1)
887 fb
->feature_update
= 0;
888 if (fb
->feature_update
)
889 xenstore_write_be_int(xendev
, "request-update", 1);
891 xen_pv_printf(xendev
, 1, "feature-update=%d, videoram=%d\n",
892 fb
->feature_update
, videoram
);
896 static void fb_disconnect(struct XenDevice
*xendev
)
898 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
901 * FIXME: qemu can't un-init gfx display (yet?).
902 * Replacing the framebuffer with anonymous shared memory
903 * instead. This releases the guest pages and keeps qemu happy.
905 xenforeignmemory_unmap(xen_fmem
, fb
->pixels
, fb
->fbpages
);
906 fb
->pixels
= mmap(fb
->pixels
, fb
->fbpages
* XC_PAGE_SIZE
,
907 PROT_READ
| PROT_WRITE
, MAP_SHARED
| MAP_ANON
,
909 if (fb
->pixels
== MAP_FAILED
) {
910 xen_pv_printf(xendev
, 0,
911 "Couldn't replace the framebuffer with anonymous memory errno=%d\n",
914 common_unbind(&fb
->c
);
915 fb
->feature_update
= 0;
919 static void fb_frontend_changed(struct XenDevice
*xendev
, const char *node
)
921 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
924 * Set state to Connected *again* once the frontend switched
925 * to connected. We must trigger the watch a second time to
926 * workaround a frontend bug.
928 if (fb
->bug_trigger
== 0 && strcmp(node
, "state") == 0 &&
929 xendev
->fe_state
== XenbusStateConnected
&&
930 xendev
->be_state
== XenbusStateConnected
) {
931 xen_pv_printf(xendev
, 2, "re-trigger connected (frontend bug)\n");
932 xen_be_set_state(xendev
, XenbusStateConnected
);
933 fb
->bug_trigger
= 1; /* only once */
937 static void fb_event(struct XenDevice
*xendev
)
939 struct XenFB
*xenfb
= container_of(xendev
, struct XenFB
, c
.xendev
);
941 xenfb_handle_events(xenfb
);
942 xen_pv_send_notify(&xenfb
->c
.xendev
);
945 /* -------------------------------------------------------------------- */
947 struct XenDevOps xen_kbdmouse_ops
= {
948 .size
= sizeof(struct XenInput
),
950 .initialise
= input_initialise
,
951 .connected
= input_connected
,
952 .disconnect
= input_disconnect
,
953 .event
= input_event
,
956 struct XenDevOps xen_framebuffer_ops
= {
957 .size
= sizeof(struct XenFB
),
959 .initialise
= fb_initialise
,
960 .disconnect
= fb_disconnect
,
962 .frontend_changed
= fb_frontend_changed
,
965 static const GraphicHwOps xenfb_ops
= {
966 .invalidate
= xenfb_invalidate
,
967 .gfx_update
= xenfb_update
,
968 .update_interval
= xenfb_update_interval
,