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/>.
29 #include <sys/types.h>
39 #include "ui/console.h"
40 #include "sysemu/char.h"
41 #include "hw/xen/xen_backend.h"
43 #include <xen/event_channel.h>
44 #include <xen/io/fbif.h>
45 #include <xen/io/kbdif.h>
46 #include <xen/io/protocols.h>
49 #define BTN_LEFT 0x110 /* from <linux/input.h> */
52 /* -------------------------------------------------------------------- */
55 struct XenDevice xendev
; /* must be first */
62 int abs_pointer_wanted
; /* Whether guest supports absolute pointer */
63 int button_state
; /* Last seen pointer button state */
65 QEMUPutMouseEntry
*qmouse
;
92 /* -------------------------------------------------------------------- */
94 static int common_bind(struct common
*c
)
98 if (xenstore_read_fe_int(&c
->xendev
, "page-ref", &mfn
) == -1)
100 if (xenstore_read_fe_int(&c
->xendev
, "event-channel", &c
->xendev
.remote_port
) == -1)
103 c
->page
= xc_map_foreign_range(xen_xc
, c
->xendev
.dom
,
105 PROT_READ
| PROT_WRITE
, mfn
);
109 xen_be_bind_evtchn(&c
->xendev
);
110 xen_be_printf(&c
->xendev
, 1, "ring mfn %d, remote-port %d, local-port %d\n",
111 mfn
, c
->xendev
.remote_port
, c
->xendev
.local_port
);
116 static void common_unbind(struct common
*c
)
118 xen_be_unbind_evtchn(&c
->xendev
);
120 munmap(c
->page
, XC_PAGE_SIZE
);
125 /* -------------------------------------------------------------------- */
129 * These two tables are not needed any more, but left in here
130 * intentionally as documentation, to show how scancode2linux[]
133 * Tables to map from scancode to Linux input layer keycode.
134 * Scancodes are hardware-specific. These maps assumes a
135 * standard AT or PS/2 keyboard which is what QEMU feeds us.
137 const unsigned char atkbd_set2_keycode
[512] = {
139 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
140 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
141 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
142 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
143 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
144 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
145 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
146 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
148 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
149 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
150 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
151 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
152 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
153 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
154 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
155 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
159 const unsigned char atkbd_unxlate_table
[128] = {
161 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
162 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
163 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
164 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
165 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
166 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
167 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
168 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
174 * for (i = 0; i < 128; i++) {
175 * scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
176 * scancode2linux[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
179 static const unsigned char scancode2linux
[512] = {
180 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
181 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
182 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
183 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
184 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
185 80, 81, 82, 83, 99, 0, 86, 87, 88,117, 0, 0, 95,183,184,185,
186 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
187 93, 0, 0, 89, 0, 0, 85, 91, 90, 92, 0, 94, 0,124,121, 0,
189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
190 165, 0, 0, 0, 0, 0, 0, 0, 0,163, 0, 0, 96, 97, 0, 0,
191 113,140,164, 0,166, 0, 0, 0, 0, 0,255, 0, 0, 0,114, 0,
192 115, 0,150, 0, 0, 98,255, 99,100, 0, 0, 0, 0, 0, 0, 0,
193 0, 0, 0, 0, 0,119,119,102,103,104, 0,105,112,106,118,107,
194 108,109,110,111, 0, 0, 0, 0, 0, 0, 0,125,126,127,116,142,
195 0, 0, 0,143, 0,217,156,173,128,159,158,157,155,226, 0,112,
196 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
199 /* Send an event to the keyboard frontend driver */
200 static int xenfb_kbd_event(struct XenInput
*xenfb
,
201 union xenkbd_in_event
*event
)
203 struct xenkbd_page
*page
= xenfb
->c
.page
;
206 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
211 prod
= page
->in_prod
;
212 if (prod
- page
->in_cons
== XENKBD_IN_RING_LEN
) {
217 xen_mb(); /* ensure ring space available */
218 XENKBD_IN_RING_REF(page
, prod
) = *event
;
219 xen_wmb(); /* ensure ring contents visible */
220 page
->in_prod
= prod
+ 1;
221 return xen_be_send_notify(&xenfb
->c
.xendev
);
224 /* Send a keyboard (or mouse button) event */
225 static int xenfb_send_key(struct XenInput
*xenfb
, bool down
, int keycode
)
227 union xenkbd_in_event event
;
229 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
230 event
.type
= XENKBD_TYPE_KEY
;
231 event
.key
.pressed
= down
? 1 : 0;
232 event
.key
.keycode
= keycode
;
234 return xenfb_kbd_event(xenfb
, &event
);
237 /* Send a relative mouse movement event */
238 static int xenfb_send_motion(struct XenInput
*xenfb
,
239 int rel_x
, int rel_y
, int rel_z
)
241 union xenkbd_in_event event
;
243 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
244 event
.type
= XENKBD_TYPE_MOTION
;
245 event
.motion
.rel_x
= rel_x
;
246 event
.motion
.rel_y
= rel_y
;
247 #if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030207
248 event
.motion
.rel_z
= rel_z
;
251 return xenfb_kbd_event(xenfb
, &event
);
254 /* Send an absolute mouse movement event */
255 static int xenfb_send_position(struct XenInput
*xenfb
,
256 int abs_x
, int abs_y
, int z
)
258 union xenkbd_in_event event
;
260 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
261 event
.type
= XENKBD_TYPE_POS
;
262 event
.pos
.abs_x
= abs_x
;
263 event
.pos
.abs_y
= abs_y
;
264 #if __XEN_LATEST_INTERFACE_VERSION__ == 0x00030207
267 #if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030208
271 return xenfb_kbd_event(xenfb
, &event
);
275 * Send a key event from the client to the guest OS
276 * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
277 * We have to turn this into a Linux Input layer keycode.
279 * Extra complexity from the fact that with extended scancodes
280 * (like those produced by arrow keys) this method gets called
281 * twice, but we only want to send a single event. So we have to
282 * track the '0xe0' scancode state & collapse the extended keys
285 * Wish we could just send scancodes straight to the guest which
286 * already has code for dealing with this...
288 static void xenfb_key_event(void *opaque
, int scancode
)
290 struct XenInput
*xenfb
= opaque
;
293 if (scancode
== 0xe0) {
296 } else if (scancode
& 0x80) {
300 if (xenfb
->extended
) {
304 xenfb_send_key(xenfb
, down
, scancode2linux
[scancode
]);
308 * Send a mouse event from the client to the guest OS
310 * The QEMU mouse can be in either relative, or absolute mode.
311 * Movement is sent separately from button state, which has to
312 * be encoded as virtual key events. We also don't actually get
313 * given any button up/down events, so have to track changes in
316 static void xenfb_mouse_event(void *opaque
,
317 int dx
, int dy
, int dz
, int button_state
)
319 struct XenInput
*xenfb
= opaque
;
320 DisplaySurface
*surface
= qemu_console_surface(xenfb
->c
.con
);
321 int dw
= surface_width(surface
);
322 int dh
= surface_height(surface
);
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
);
357 xen_be_printf(xendev
, 1, "ds not set (yet)\n");
361 rc
= common_bind(&in
->c
);
365 qemu_add_kbd_event_handler(xenfb_key_event
, in
);
369 static void input_connected(struct XenDevice
*xendev
)
371 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
373 if (xenstore_read_fe_int(xendev
, "request-abs-pointer",
374 &in
->abs_pointer_wanted
) == -1) {
375 in
->abs_pointer_wanted
= 0;
379 qemu_remove_mouse_event_handler(in
->qmouse
);
381 in
->qmouse
= qemu_add_mouse_event_handler(xenfb_mouse_event
, in
,
382 in
->abs_pointer_wanted
,
386 static void input_disconnect(struct XenDevice
*xendev
)
388 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
391 qemu_remove_mouse_event_handler(in
->qmouse
);
394 qemu_add_kbd_event_handler(NULL
, NULL
);
395 common_unbind(&in
->c
);
398 static void input_event(struct XenDevice
*xendev
)
400 struct XenInput
*xenfb
= container_of(xendev
, struct XenInput
, c
.xendev
);
401 struct xenkbd_page
*page
= xenfb
->c
.page
;
403 /* We don't understand any keyboard events, so just ignore them. */
404 if (page
->out_prod
== page
->out_cons
)
406 page
->out_cons
= page
->out_prod
;
407 xen_be_send_notify(&xenfb
->c
.xendev
);
410 /* -------------------------------------------------------------------- */
412 static void xenfb_copy_mfns(int mode
, int count
, unsigned long *dst
, void *src
)
414 uint32_t *src32
= src
;
415 uint64_t *src64
= src
;
418 for (i
= 0; i
< count
; i
++)
419 dst
[i
] = (mode
== 32) ? src32
[i
] : src64
[i
];
422 static int xenfb_map_fb(struct XenFB
*xenfb
)
424 struct xenfb_page
*page
= xenfb
->c
.page
;
425 char *protocol
= xenfb
->c
.xendev
.protocol
;
427 unsigned long *pgmfns
= NULL
;
428 unsigned long *fbmfns
= NULL
;
432 /* default to native */
434 mode
= sizeof(unsigned long) * 8;
438 * Undefined protocol, some guesswork needed.
440 * Old frontends which don't set the protocol use
441 * one page directory only, thus pd[1] must be zero.
442 * pd[1] of the 32bit struct layout and the lower
443 * 32 bits of pd[0] of the 64bit struct layout have
444 * the same location, so we can check that ...
446 uint32_t *ptr32
= NULL
;
447 uint32_t *ptr64
= NULL
;
448 #if defined(__i386__)
449 ptr32
= (void*)page
->pd
;
450 ptr64
= ((void*)page
->pd
) + 4;
451 #elif defined(__x86_64__)
452 ptr32
= ((void*)page
->pd
) - 4;
453 ptr64
= (void*)page
->pd
;
464 #if defined(__x86_64__)
465 } else if (strcmp(protocol
, XEN_IO_PROTO_ABI_X86_32
) == 0) {
466 /* 64bit dom0, 32bit domU */
468 pd
= ((void*)page
->pd
) - 4;
469 #elif defined(__i386__)
470 } else if (strcmp(protocol
, XEN_IO_PROTO_ABI_X86_64
) == 0) {
471 /* 32bit dom0, 64bit domU */
473 pd
= ((void*)page
->pd
) + 4;
478 munmap(xenfb
->pixels
, xenfb
->fbpages
* XC_PAGE_SIZE
);
479 xenfb
->pixels
= NULL
;
482 xenfb
->fbpages
= (xenfb
->fb_len
+ (XC_PAGE_SIZE
- 1)) / XC_PAGE_SIZE
;
483 n_fbdirs
= xenfb
->fbpages
* mode
/ 8;
484 n_fbdirs
= (n_fbdirs
+ (XC_PAGE_SIZE
- 1)) / XC_PAGE_SIZE
;
486 pgmfns
= g_malloc0(sizeof(unsigned long) * n_fbdirs
);
487 fbmfns
= g_malloc0(sizeof(unsigned long) * xenfb
->fbpages
);
489 xenfb_copy_mfns(mode
, n_fbdirs
, pgmfns
, pd
);
490 map
= xc_map_foreign_pages(xen_xc
, xenfb
->c
.xendev
.dom
,
491 PROT_READ
, pgmfns
, n_fbdirs
);
494 xenfb_copy_mfns(mode
, xenfb
->fbpages
, fbmfns
, map
);
495 munmap(map
, n_fbdirs
* XC_PAGE_SIZE
);
497 xenfb
->pixels
= xc_map_foreign_pages(xen_xc
, xenfb
->c
.xendev
.dom
,
498 PROT_READ
| PROT_WRITE
, fbmfns
, xenfb
->fbpages
);
499 if (xenfb
->pixels
== NULL
)
502 ret
= 0; /* all is fine */
510 static int xenfb_configure_fb(struct XenFB
*xenfb
, size_t fb_len_lim
,
511 int width
, int height
, int depth
,
512 size_t fb_len
, int offset
, int row_stride
)
514 size_t mfn_sz
= sizeof(*((struct xenfb_page
*)0)->pd
);
515 size_t pd_len
= sizeof(((struct xenfb_page
*)0)->pd
) / mfn_sz
;
516 size_t fb_pages
= pd_len
* XC_PAGE_SIZE
/ mfn_sz
;
517 size_t fb_len_max
= fb_pages
* XC_PAGE_SIZE
;
518 int max_width
, max_height
;
520 if (fb_len_lim
> fb_len_max
) {
521 xen_be_printf(&xenfb
->c
.xendev
, 0, "fb size limit %zu exceeds %zu, corrected\n",
522 fb_len_lim
, fb_len_max
);
523 fb_len_lim
= fb_len_max
;
525 if (fb_len_lim
&& fb_len
> fb_len_lim
) {
526 xen_be_printf(&xenfb
->c
.xendev
, 0, "frontend fb size %zu limited to %zu\n",
530 if (depth
!= 8 && depth
!= 16 && depth
!= 24 && depth
!= 32) {
531 xen_be_printf(&xenfb
->c
.xendev
, 0, "can't handle frontend fb depth %d\n",
535 if (row_stride
<= 0 || row_stride
> fb_len
) {
536 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend stride %d\n", row_stride
);
539 max_width
= row_stride
/ (depth
/ 8);
540 if (width
< 0 || width
> max_width
) {
541 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend width %d limited to %d\n",
545 if (offset
< 0 || offset
>= fb_len
) {
546 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend offset %d (max %zu)\n",
550 max_height
= (fb_len
- offset
) / row_stride
;
551 if (height
< 0 || height
> max_height
) {
552 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend height %d limited to %d\n",
556 xenfb
->fb_len
= fb_len
;
557 xenfb
->row_stride
= row_stride
;
558 xenfb
->depth
= depth
;
559 xenfb
->width
= width
;
560 xenfb
->height
= height
;
561 xenfb
->offset
= offset
;
562 xenfb
->up_fullscreen
= 1;
563 xenfb
->do_resize
= 1;
564 xen_be_printf(&xenfb
->c
.xendev
, 1, "framebuffer %dx%dx%d offset %d stride %d\n",
565 width
, height
, depth
, offset
, row_stride
);
569 /* A convenient function for munging pixels between different depths */
570 #define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB) \
571 for (line = y ; line < (y+h) ; line++) { \
572 SRC_T *src = (SRC_T *)(xenfb->pixels \
574 + (line * xenfb->row_stride) \
575 + (x * xenfb->depth / 8)); \
576 DST_T *dst = (DST_T *)(data \
577 + (line * linesize) \
580 const int RSS = 32 - (RSB + GSB + BSB); \
581 const int GSS = 32 - (GSB + BSB); \
582 const int BSS = 32 - (BSB); \
583 const uint32_t RSM = (~0U) << (32 - RSB); \
584 const uint32_t GSM = (~0U) << (32 - GSB); \
585 const uint32_t BSM = (~0U) << (32 - BSB); \
586 const int RDS = 32 - (RDB + GDB + BDB); \
587 const int GDS = 32 - (GDB + BDB); \
588 const int BDS = 32 - (BDB); \
589 const uint32_t RDM = (~0U) << (32 - RDB); \
590 const uint32_t GDM = (~0U) << (32 - GDB); \
591 const uint32_t BDM = (~0U) << (32 - BDB); \
592 for (col = x ; col < (x+w) ; col++) { \
593 uint32_t spix = *src; \
594 *dst = (((spix << RSS) & RSM & RDM) >> RDS) | \
595 (((spix << GSS) & GSM & GDM) >> GDS) | \
596 (((spix << BSS) & BSM & BDM) >> BDS); \
597 src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8); \
598 dst = (DST_T *) ((unsigned long) dst + bpp / 8); \
604 * This copies data from the guest framebuffer region, into QEMU's
605 * displaysurface. qemu uses 16 or 32 bpp. In case the pv framebuffer
606 * uses something else we must convert and copy, otherwise we can
607 * supply the buffer directly and no thing here.
609 static void xenfb_guest_copy(struct XenFB
*xenfb
, int x
, int y
, int w
, int h
)
611 DisplaySurface
*surface
= qemu_console_surface(xenfb
->c
.con
);
613 int bpp
= surface_bits_per_pixel(surface
);
614 int linesize
= surface_stride(surface
);
615 uint8_t *data
= surface_data(surface
);
617 if (!is_buffer_shared(surface
)) {
618 switch (xenfb
->depth
) {
621 BLT(uint8_t, uint16_t, 3, 3, 2, 5, 6, 5);
622 } else if (bpp
== 32) {
623 BLT(uint8_t, uint32_t, 3, 3, 2, 8, 8, 8);
630 BLT(uint32_t, uint16_t, 8, 8, 8, 5, 6, 5);
631 } else if (bpp
== 32) {
632 BLT(uint32_t, uint32_t, 8, 8, 8, 8, 8, 8);
641 if (oops
) /* should not happen */
642 xen_be_printf(&xenfb
->c
.xendev
, 0, "%s: oops: convert %d -> %d bpp?\n",
643 __FUNCTION__
, xenfb
->depth
, bpp
);
645 dpy_gfx_update(xenfb
->c
.con
, x
, y
, w
, h
);
648 #ifdef XENFB_TYPE_REFRESH_PERIOD
649 static int xenfb_queue_full(struct XenFB
*xenfb
)
651 struct xenfb_page
*page
= xenfb
->c
.page
;
657 prod
= page
->in_prod
;
658 cons
= page
->in_cons
;
659 return prod
- cons
== XENFB_IN_RING_LEN
;
662 static void xenfb_send_event(struct XenFB
*xenfb
, union xenfb_in_event
*event
)
665 struct xenfb_page
*page
= xenfb
->c
.page
;
667 prod
= page
->in_prod
;
668 /* caller ensures !xenfb_queue_full() */
669 xen_mb(); /* ensure ring space available */
670 XENFB_IN_RING_REF(page
, prod
) = *event
;
671 xen_wmb(); /* ensure ring contents visible */
672 page
->in_prod
= prod
+ 1;
674 xen_be_send_notify(&xenfb
->c
.xendev
);
677 static void xenfb_send_refresh_period(struct XenFB
*xenfb
, int period
)
679 union xenfb_in_event event
;
681 memset(&event
, 0, sizeof(event
));
682 event
.type
= XENFB_TYPE_REFRESH_PERIOD
;
683 event
.refresh_period
.period
= period
;
684 xenfb_send_event(xenfb
, &event
);
689 * Periodic update of display.
690 * Also transmit the refresh interval to the frontend.
692 * Never ever do any qemu display operations
693 * (resize, screen update) outside this function.
694 * Our screen might be inactive. When asked for
695 * an update we know it is active.
697 static void xenfb_update(void *opaque
)
699 struct XenFB
*xenfb
= opaque
;
700 DisplaySurface
*surface
;
703 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
706 if (!xenfb
->feature_update
) {
707 /* we don't get update notifications, thus use the
708 * sledge hammer approach ... */
709 xenfb
->up_fullscreen
= 1;
712 /* resize if needed */
713 if (xenfb
->do_resize
) {
714 xenfb
->do_resize
= 0;
715 switch (xenfb
->depth
) {
718 /* console.c supported depth -> buffer can be used directly */
719 surface
= qemu_create_displaysurface_from
720 (xenfb
->width
, xenfb
->height
, xenfb
->depth
,
721 xenfb
->row_stride
, xenfb
->pixels
+ xenfb
->offset
,
725 /* we must convert stuff */
726 surface
= qemu_create_displaysurface(xenfb
->width
, xenfb
->height
);
729 dpy_gfx_replace_surface(xenfb
->c
.con
, surface
);
730 xen_be_printf(&xenfb
->c
.xendev
, 1, "update: resizing: %dx%d @ %d bpp%s\n",
731 xenfb
->width
, xenfb
->height
, xenfb
->depth
,
732 is_buffer_shared(surface
) ? " (shared)" : "");
733 xenfb
->up_fullscreen
= 1;
736 /* run queued updates */
737 if (xenfb
->up_fullscreen
) {
738 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: fullscreen\n");
739 xenfb_guest_copy(xenfb
, 0, 0, xenfb
->width
, xenfb
->height
);
740 } else if (xenfb
->up_count
) {
741 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: %d rects\n", xenfb
->up_count
);
742 for (i
= 0; i
< xenfb
->up_count
; i
++)
743 xenfb_guest_copy(xenfb
,
744 xenfb
->up_rects
[i
].x
,
745 xenfb
->up_rects
[i
].y
,
746 xenfb
->up_rects
[i
].w
,
747 xenfb
->up_rects
[i
].h
);
749 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: nothing\n");
752 xenfb
->up_fullscreen
= 0;
755 static void xenfb_update_interval(void *opaque
, uint64_t interval
)
757 struct XenFB
*xenfb
= opaque
;
759 if (xenfb
->feature_update
) {
760 #ifdef XENFB_TYPE_REFRESH_PERIOD
761 if (xenfb_queue_full(xenfb
)) {
764 xenfb_send_refresh_period(xenfb
, interval
);
769 /* QEMU display state changed, so refresh the framebuffer copy */
770 static void xenfb_invalidate(void *opaque
)
772 struct XenFB
*xenfb
= opaque
;
773 xenfb
->up_fullscreen
= 1;
776 static void xenfb_handle_events(struct XenFB
*xenfb
)
779 struct xenfb_page
*page
= xenfb
->c
.page
;
781 prod
= page
->out_prod
;
782 if (prod
== page
->out_cons
)
784 xen_rmb(); /* ensure we see ring contents up to prod */
785 for (cons
= page
->out_cons
; cons
!= prod
; cons
++) {
786 union xenfb_out_event
*event
= &XENFB_OUT_RING_REF(page
, cons
);
789 switch (event
->type
) {
790 case XENFB_TYPE_UPDATE
:
791 if (xenfb
->up_count
== UP_QUEUE
)
792 xenfb
->up_fullscreen
= 1;
793 if (xenfb
->up_fullscreen
)
795 x
= MAX(event
->update
.x
, 0);
796 y
= MAX(event
->update
.y
, 0);
797 w
= MIN(event
->update
.width
, xenfb
->width
- x
);
798 h
= MIN(event
->update
.height
, xenfb
->height
- y
);
799 if (w
< 0 || h
< 0) {
800 xen_be_printf(&xenfb
->c
.xendev
, 1, "bogus update ignored\n");
803 if (x
!= event
->update
.x
||
804 y
!= event
->update
.y
||
805 w
!= event
->update
.width
||
806 h
!= event
->update
.height
) {
807 xen_be_printf(&xenfb
->c
.xendev
, 1, "bogus update clipped\n");
809 if (w
== xenfb
->width
&& h
> xenfb
->height
/ 2) {
810 /* scroll detector: updated more than 50% of the lines,
811 * don't bother keeping track of the rectangles then */
812 xenfb
->up_fullscreen
= 1;
814 xenfb
->up_rects
[xenfb
->up_count
].x
= x
;
815 xenfb
->up_rects
[xenfb
->up_count
].y
= y
;
816 xenfb
->up_rects
[xenfb
->up_count
].w
= w
;
817 xenfb
->up_rects
[xenfb
->up_count
].h
= h
;
821 #ifdef XENFB_TYPE_RESIZE
822 case XENFB_TYPE_RESIZE
:
823 if (xenfb_configure_fb(xenfb
, xenfb
->fb_len
,
825 event
->resize
.height
,
828 event
->resize
.offset
,
829 event
->resize
.stride
) < 0)
831 xenfb_invalidate(xenfb
);
836 xen_mb(); /* ensure we're done with ring contents */
837 page
->out_cons
= cons
;
840 static int fb_init(struct XenDevice
*xendev
)
842 #ifdef XENFB_TYPE_RESIZE
843 xenstore_write_be_int(xendev
, "feature-resize", 1);
848 static int fb_initialise(struct XenDevice
*xendev
)
850 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
851 struct xenfb_page
*fb_page
;
855 if (xenstore_read_fe_int(xendev
, "videoram", &videoram
) == -1)
858 rc
= common_bind(&fb
->c
);
862 fb_page
= fb
->c
.page
;
863 rc
= xenfb_configure_fb(fb
, videoram
* 1024 * 1024U,
864 fb_page
->width
, fb_page
->height
, fb_page
->depth
,
865 fb_page
->mem_length
, 0, fb_page
->line_length
);
869 rc
= xenfb_map_fb(fb
);
873 #if 0 /* handled in xen_init_display() for now */
874 if (!fb
->have_console
) {
875 fb
->c
.ds
= graphic_console_init(xenfb_update
,
880 fb
->have_console
= 1;
884 if (xenstore_read_fe_int(xendev
, "feature-update", &fb
->feature_update
) == -1)
885 fb
->feature_update
= 0;
886 if (fb
->feature_update
)
887 xenstore_write_be_int(xendev
, "request-update", 1);
889 xen_be_printf(xendev
, 1, "feature-update=%d, videoram=%d\n",
890 fb
->feature_update
, videoram
);
894 static void fb_disconnect(struct XenDevice
*xendev
)
896 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
899 * FIXME: qemu can't un-init gfx display (yet?).
900 * Replacing the framebuffer with anonymous shared memory
901 * instead. This releases the guest pages and keeps qemu happy.
903 fb
->pixels
= mmap(fb
->pixels
, fb
->fbpages
* XC_PAGE_SIZE
,
904 PROT_READ
| PROT_WRITE
, MAP_SHARED
| MAP_ANON
,
906 common_unbind(&fb
->c
);
907 fb
->feature_update
= 0;
911 static void fb_frontend_changed(struct XenDevice
*xendev
, const char *node
)
913 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
916 * Set state to Connected *again* once the frontend switched
917 * to connected. We must trigger the watch a second time to
918 * workaround a frontend bug.
920 if (fb
->bug_trigger
== 0 && strcmp(node
, "state") == 0 &&
921 xendev
->fe_state
== XenbusStateConnected
&&
922 xendev
->be_state
== XenbusStateConnected
) {
923 xen_be_printf(xendev
, 2, "re-trigger connected (frontend bug)\n");
924 xen_be_set_state(xendev
, XenbusStateConnected
);
925 fb
->bug_trigger
= 1; /* only once */
929 static void fb_event(struct XenDevice
*xendev
)
931 struct XenFB
*xenfb
= container_of(xendev
, struct XenFB
, c
.xendev
);
933 xenfb_handle_events(xenfb
);
934 xen_be_send_notify(&xenfb
->c
.xendev
);
937 /* -------------------------------------------------------------------- */
939 struct XenDevOps xen_kbdmouse_ops
= {
940 .size
= sizeof(struct XenInput
),
942 .initialise
= input_initialise
,
943 .connected
= input_connected
,
944 .disconnect
= input_disconnect
,
945 .event
= input_event
,
948 struct XenDevOps xen_framebuffer_ops
= {
949 .size
= sizeof(struct XenFB
),
951 .initialise
= fb_initialise
,
952 .disconnect
= fb_disconnect
,
954 .frontend_changed
= fb_frontend_changed
,
957 static const GraphicHwOps xenfb_ops
= {
958 .invalidate
= xenfb_invalidate
,
959 .gfx_update
= xenfb_update
,
960 .update_interval
= xenfb_update_interval
,
964 * FIXME/TODO: Kill this.
965 * Temporary needed while DisplayState reorganization is in flight.
967 void xen_init_display(int domid
)
969 struct XenDevice
*xfb
, *xin
;
976 main_loop_wait(true);
977 xfb
= xen_be_find_xendev("vfb", domid
, 0);
978 xin
= xen_be_find_xendev("vkbd", domid
, 0);
984 xen_be_printf(NULL
, 1, "displaystate setup failed\n");
989 fb
= container_of(xfb
, struct XenFB
, c
.xendev
);
990 fb
->c
.con
= graphic_console_init(NULL
, &xenfb_ops
, fb
);
991 fb
->have_console
= 1;
994 in
= container_of(xin
, struct XenInput
, c
.xendev
);
995 in
->c
.con
= fb
->c
.con
;
998 xen_be_check_state(xin
);
999 xen_be_check_state(xfb
);